I read that SOLID is a good time-tested recommendation, but you shouldn’t push them into every project. Googled examples when it is not necessary to use it and not found. Tell me, in what cases is the use of SOLID unnecessarily?
2 answers
Regarding any pattern / design principle, you can say:
- If you follow it, there is no guarantee that your code will automatically become more correct, extensible and maintainable.
- If you do not follow it, there is no guarantee that your code automatically becomes problematic, non-extensible and not maintainable.
- By following it you can solve one of the problems of your code (or not), but create new problems.
There is also an incomplete or even incorrect understanding of the principles / patterns used. And perhaps even the construction of the absolute, when the literal following them becomes beyond common sense.
Thus, the question is not when you should not use SOLID, but how much each of its principles is used in its own particular case.
S - Single Responsibility Principle
The class should have only one responsibility.
With insufficient division of responsibility, we get the anti-pattern "god", the class becomes a food processor. At the same time, in case of excessive separation, the code can be fragmented so that in each class there remains almost one method consisting of one line of code. As a result, the complexity of perception may increase.
O - Open / Closed Principle
Software entities must be open for expansion, but closed for modification.
Let's take a situation when the base class contains general implementation details, and several heirs specify it. Following this principle, when adding new descendants, their common features will have to be put into one intermediate class in order not to touch the base one. Over time, a bizarre hierarchy may emerge, although it was probably worth considering the option of modifying the base class (despite possible breakdowns of already existing descendants).
L - Liskov Substitution Principle
Objects in the program must be replaceable by instances of their subtypes without altering the correctness of the program execution.
For the sake of ensuring this principle, sometimes it is necessary to use dubious solutions. For example, the Ellipse class has a subclass of Circle , which is a case of Ellipse with the same length along the X and Y axes. In accordance with the principle, the Circle subclass must implement the behavior of the parent. If Ellipse contains the stretchX method, which allows modifying the length along the X axis, then the Cirlce class Cirlce also implement this behavior, despite the fact that this is not possible for a circle.
I - Interface Segregation Principle
Many interfaces specifically designed for customers are better than one general-purpose interface.
Requires that customers do not depend on interfaces that they do not use. In practice, especially with a poorly designed architecture, this can result in crushing into very small interfaces from one or two methods in order to satisfy many clients.
D - Dependency Inversion Principle
Principle of inversion of dependence
Take the situation when an object of class A calls methods of an object of class B So A depends on B Using this principle, an object of type B must be instantiated outside A and passed as a dependency to A Without applying this principle, this can be done by object A , which in many cases is much more convenient.
Based on http://www.tonymarston.net/php-mysql/not-so-solid-oo-principles.html . In the process of reading I learned a lot of new things. Holivar is welcome)
- As a holivar: “ when adding new descendants, their common features will have to be put into one intermediate class so as not to touch the base class” - I do not agree. Intermediate classes can not be added only to share the code! To share the code, you need to use the composition, not inheritance, put the common pieces into the helper classes. The class hierarchy should reflect the subject area, not the implementation details. - VladD
- @VladD even if you implement the implementation into a composition, new requirements may also appear to the subject area in the form of new interfaces. Plus, such a removal of the implementation (if you need access to many private data) can only complicate the code transfer of this data. - Vladimir Gamalyan
- Private data also makes sense to put in the auxiliary class. If the data is used in the mode “each part of the code uses each piece of data”, then it is more difficult, but such use is a sign of design problems and the lack of an internal structure. - VladD
- one@VladimirGamalian example and deduction from it for Liskov Substitution Principle is incorrect. Applying LSP to an example circle / ellipse (square / rectangle) gives the result "a circle and an ellipse should not be inherited from each other." - PashaPash ♦
- @VladimirGamalian, to be more precise, the presence of
stretchX/stretchYmethods will most likely lead to callingstretchX(2);stretchY(2)in the code. What, when called on an ellipse, stretches it twice in all directions, and when called on a circle, it will either not stretch at all, or stretch 4 times - that is, correct operation when using the Circle pattern as an Ellipse in any case will be broken. - PashaPash ♦
Like any tool, design principles need to be applied wisely.
There are two cases in which the application of design principles will lead to an increase in problems, and will not lead to anything good.
Yagni
Details - in response to the question " Does OCP and DIP (from SOLID) violate the principle of YAGNI? ".
Design principles are designed to mitigate a specific development problem (yes, it is “mitigation”, but not a solution to the problem), while adding its own problems.
Since programmers sometimes invent problems for themselves, following (especially literally) the principles of design will lead to a misalignment of design without solving a real problem.
In other words, overreliance on design principles can lead to an over-complicated solution where this complexity is not needed.
"Over" -SOLID
Read more in the article " On the principles of design ."
There are a number of typical pathological cases of using the SOLID principles:
Anti-SRP - The principle of vague responsibility. Classes are divided into many small classes, as a result of which the logic is spread over several classes / modules.
Anti-OCP - The principle of the factory of factories. The design is too general and extensible, there are too many levels of abstraction.
Anti-LCP - The principle of incomprehensible inheritance. The principle is manifested either in an excessive amount of inheritance, or in its complete absence, depending on the experience and views of the local chief architect.
Anti-ISP - The principle of thousands of interfaces. Interfaces of classes are broken into too many components, which makes them inconvenient for all customers to use.
Anti-DIP - The principle of inversion of consciousness or DI-brain. Interfaces are allocated for each class and are transmitted in batches through constructors. Understanding where the logic is located is almost impossible.
SOLIDprinciples led to an increase in the number of classes from 5 to 20? - Bald