SOLID – Object Oriented Design Principles
In object-oriented computer programming, SOLID is an acronym for five design principles intended to make software designs more understandable, flexible and maintainable.
S.O.L.I.D. STANDS FOR:
S — Single responsibility principle
O — Open closed principle
L — Liskov substitution principle
I — Interface segregation principle
D — Dependency Inversion principle
Single responsibility principle
A class should have one and only one reason to change, meaning that a class should only have one job. The Single Responsibility Principle is closely related to the concepts of coupling and cohesion. Coupling refers to how inextricably linked different aspects of an application are, while cohesion refers to how closely related the contents of a particular class or package may be.
Some examples of responsibilities to consider that may need to be separated include:
• Error Handling
• Class Selection / Instantiation
Objects or entities should be open for extension but closed for modification. Open for extension means that we should be able to add new features or components to the application without breaking existing code. Closed for modification means that we should not introduce breaking changes to existing functionality, because that would force you to refactor a lot of existing code — Eric Elliott
In simpler words, this means creating software entities whose behavior can be changed without the need to edit and recompile the code itself. The simplest way to demonstrate this principle is to consider a method that does one thing. Let’s say it writes to a file, the name of which is hard-coded into the method. If the requirements change, and the filename now needs to be different in certain situations, we must open up the method to change the filename. If, on the other hand, the filename had been passed in as a parameter, we would be able to modify the behavior of this method without changing its source, keeping it closed to modification.
Liskov substitution principle
The Liskov Substitution Principle (LSP) states that subtypes must be substitutable for their base types. The principle defines that objects of a superclass shall be replaceable with objects of its subclasses without breaking the application. That requires the objects of your subclasses to behave in the same way as the objects of your superclass.
When this principle is violated, it tends to result in a lot of extra conditional logic scattered throughout the application, checking to see the specific type of an object. This duplicate, scattered code becomes a ground for bugs as the application grows.
Interface segregation principle
A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use.
When we design an application, we should take care how we are going to make abstract a module which contains several submodules. Considering the module implemented by a class, we can have an abstraction of the system done in an interface. But if we want to extend our application adding another module that contains only some of the submodules of the original system, we are forced to implement the full interface and to write some dummy methods. Such an interface is named fat interface or polluted interface. Having an interface pollution is not a good solution and might induce inappropriate behavior in the system.
Dependency inversion principle
Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.Basically, Dependency inversion principle is one of the principles on which most of the design patterns are build upon. Dependency inversion talks about the coupling between the different classes or modules. It focuses on the approach where the higher classes are not dependent on the lower classes instead depend upon the abstraction of the lower classes. The main motto of the dependency inversion is Any higher classes should always depend upon the abstraction of the class rather than the detail.
This aims to reduce the coupling between the classes is achieved by introducing abstraction between the layer, thus doesn’t care about the real implementation.
“If you take the SOLID principles to their extremes, you arrive at something that makes Functional Programming look quite attractive” — Mark Seemann
S.O.L.I.D might seem to be a handful at first, but with continuous usage and adherence to its guidelines, it becomes a part of you and your code which can easily be modified, tested, extended, and refactored without any problems.