Solid Principles in a Flutter
These principles are commonly used by software engineers and provide developers with several benefits.
Hello Everyone, today we will be discussing a bit more general topic related to software engineering. We will look at patterns and also architectural decisions. The first part where we want to start is with the SOLID PRINCIPLES.
Almost every interview asks at least once about SOLID PRINCIPLES, one of the most common Software Development patterns. Thus, everyone should have a clear understanding of SOLID in Software Engineering.
SOLID stands for Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion, which we will discuss in the following sections. Developers generally recognize them as good practices and are very popular.
Each of them will be discussed and we will try to understand why they are important and why you should consider them in an object-oriented language like DART.
As we start, solid contains five principles, and we’ll take a look at each one. For each letter in solid, there is an abbreviation, and we’ll look at what they stand for. Hence, we will take a look at them all, but let’s take a moment to understand why we need solid in the first place. With solid, you can avoid bad software design patterns, engineering mistakes, and code depths, so your code will be easier and more readable as a result.
The SOLID principles were introduced in 2000 by software engineer and instructor Robert C. Martin, known as Uncle Bob. It is one of the most important standards in software engineering that nearly every developer who works with an object-oriented programming language has read at least once. If you want to learn more about the whole topic, I highly recommend reading that book. I have been asked at least once about solid in nearly every interview or coding interview that I have had, so I hope you will find this article useful and helpful.
S: The Single Responsibility Principle (SRP)
A solid principle begins with an “S”: the SINGLE RESPONSIBILITY PRINCIPLE. In the single responsibility principle, you are told that every class function method, no matter what you write, will have only one specific opportunity and should handle that responsibility exclusively. If you have a method that makes an HTTP request, the class should only know and understand how this HTTP request works, so it should only take care of the problems related to the car.
Suppose you have a try-catch, and the cache would do something like logging. That’s not really necessary for this HTTP request method, but you should understand how to create a logger.
So that you can abstract these different parts and you have just one responsibility for your function classes and other things, you will improve your code a lot and make it way more readable because other developers will be able to understand how it works right away. The single responsibility principle comes from two separate things.
First, one reason to make a change, and only one reason to make a change. Second, there must be only one responsibility — say, if you have data classes, they should only be responsible for the data of that type, not the register or anything else. Therefore, the single responsibility pattern or principle is derived from a single responsibility and a single reason to change.
let’s see an example:
Bad Practice
Good Practice
O: The Open-Closed Principle (OCP)
In addition, there is a second big principle that starts with an “O” called the OPEN-CLOSED PRINCIPLE. This principle says that every class and method should be open for extension, but closed for modification.
let’s assume you have a power plug you put it in the wall and done you can’t do anything at it right you can’t modify it you can’t move it around or change how it works you have another plug now or multiple plugs but what you can do is you can take a power board and connect it to it now you have extended the thing and it works still the same and we will think in soft engineering the same way so let’s take a bank account with different saving accounts one saving account could be your giro contour and the second one will be a saving account and the third one something else so what we do we could create a method that takes care of all three of them let’s say if saving if account if doing something else with the if else parts we would change the behaviour all the time so what would happen if the bank creates a new account type we would have to go into the method and change it so we would modify it but this is not really good right so what we want to have is more a possibility to extend the whole thing so if there is a new bank account type we want to extend the already existing one all right.
Consequently, we have learned from that, and as a result of the single responsibility method, we made it possible to develop more conceived and easier to maintain stuff, so we will have a better chance to test all the stuff, especially if it needs to be extended, so if new stuff comes in, we can just plug it in and it will work fine. Therefore, the first two principles have already been established, but now we have a new one.
The OPEN-CLOSED PRINCIPLE states that in effective architecture, new behaviours should be added without changing the existing code. It is commonly referred to as “classes should be open to extensions and closed to changes”.
Look at this example:
Bad Practice
Good Practice
L: The Liskov Substitution Principle (LSP)
The third big principle that starts with an “L” is LISKOV SUBSTITUTION PRINCIPLE this is quite a mouthful and is also one of the hardest parts of software engineering to grasp because the principle is difficult to explain, so we’ll try to explain it a bit easier so that the list of substitution principle can be explained more easily. As I mentioned, the purpose of substitution is to replace a subtype somehow with its general parent type, so let’s say we take a coffee machine as an example.
let’s assume you have a basic coffee machine you as a user want a coffee so you press a button you call the method make coffee for example and then you get your coffee right easy it’s very easy you put a filter inside it’s super simple you know how it works now you replace that old coffee machine with a new one that premium coffee maker deluxe 2000 with a grinder that makes speciality coffee inside it knows way more smarts it knows exactly the temperature that it needs but at the end you as a user still just call make coffee you don’t really care how to make the coffee right you don’t want to take care of all these different kinds of stuff so you can replace both of them very easily and this makes it possible with the list of principle.
According to the LSP(LISKOV SUBSTITUTION PRINCIPLE), subclasses should be replaced with superclasses without changing the logical correctness of the program. Essentially, a subtype must guarantee the “usage conditions” of its super-type along with some additional behaviours.
For example:
Bad Practice
Good Practice
I: The Interface Segregation Principle (ISP)
So this brings us to our fourth principle, the fourth big principle that starts with an “I” is INTERFACE SEGREGATION PRINCIPLE which sounds a bit complicated, but is actually quite easy to comprehend. We do not want to force our clients to use an interface that contains functions or methods that they don’t use easily enough.
According to this principle, clients don’t need to implement behaviors they don’t want. As a general rule, you should create small interfaces with few methods.
Let’s look at this example:
Bad Practice
Good Practice
D: The Dependency Inversion Principle (DIP)
Lastly, the last principle that is very important in software engineering, which starts with a “D”, is the DEPENDENCY INVERSION PRINCIPLE, which states that high-level modules must not depend on low-level modules without an abstraction. That’s a lot, but as an example, it’s quite easy to understand.
let’s say we want to copy something with our printer the copy function will have two dependencies one-two for example the keyboard reader because it gets its input from the keyboard and send it to the printer or to the copywriter these both are low-level dependencies if we would now connect our copy function right away to these two things then in order to change something in the lower layers if we want to change our printer how it behaves or if we want to change how the other stuff behaves we would to have to replace and change something in all three classes maybe and this would mean that we have to change the copy function on top of it even though that down there has something changed and we don’t want that so for that we create an abstraction layer that these things can connect to each other and this has been done with the dependency inversion principle.
According to the DIP(DEPENDENCY INVERSION PRINCIPLE), abstractions should be preferred over implementations. It’s good to extend abstract classes or implement interfaces, but it’s bad to descend from concrete classes. It’s already clear why when we look at the open-closed principle. Take a look at this example:
Bad Practice
Good Practice
So we talked about solid the five principles from Robert c martin or how we call them all the uncle bob so let’s recap five principles in solid “S” for single responsibility “O” for open close principle “L” for a list of substitution principle “I” for interface segregation principle and “D” for dependency inversion principle alright.
Now you are prepared for your interviews. Furthermore, SOLID principles were developed to combat these problematic design patterns. SOLID principles aim to reduce dependencies so that engineers can change one area of software without affecting others. As well as making designs easier to understand, maintain, and extend, they were also designed to make them simpler to maintain and extend.
So that’s all the information of Solid Principle, that I want to describe in short. I took it from many websites as some research also images that i collected by many places, if you find out any wrong info or misdirected, please point out or comment below.