In a previous post, we looked at principles to avoid when writing code. You can read it here. In this post, we will look
at SOLID design principles, programming standards that all developers must understand well to create good architecture.
Each object should be assigned one single responsibility.
A specific class should solve a specific problem.
Software entities must be open for expansion but closed for modification.
All classes, functions, etc. should be designed so that to change their behavior, it is not necessary to change their source code.
Objects in the program can be replaced by their inheritor without changing the properties of the program.
When using the class inheritor, the result of code execution should be predictable and not change the properties of the method.
It should be possible to substitute any subtype of the base type.
Functions that use references to base classes should be able to use objects of derived classes without knowing it.
Many specialized interfaces are better than one universal.
Compliance with this principle is necessary so that client classes using / implementing the interface are aware only of the methods that they use, which leads to a reduction in the amount of unused code.
Dependencies within the system are based on abstractions.
Top-level modules are independent of lower-level modules.
Abstractions should not depend on the details.
Details should depend on abstractions.
Single responsibility principle
One single responsibility should be assigned to each object.” To do this, we check how many reasons we have for changing the class - if more than one, then this class should be broken.
The principle of openness / closure (Open-closed)
Software entities must be open for expansion, but closed for modification." To do this, we present our class as a "black box" and see if we can change its behavior in this case.
The principle of substitution Barbara Liskov (Liskov substitution)
Objects in the program can be replaced by their heirs without changing the properties of the program." To do this, we check whether we have strengthened the preconditions and have weakened the postconditions. If this happens, then the principle is not respected.
Many specialized interfaces are better than one universal. We check how much the interface contains methods and how different functions are superimposed on these methods, and if necessary, we break the interfaces.
Dependency Inversion Principle
Dependencies should be built on abstractions, not details.” We check whether the classes depend on some other classes (directly instantiate objects of other classes, etc.) and if this dependence takes place, we replace it with a dependence on abstraction.