As the saying goes, “this is crazy, doing the same thing over and over, hoping for some other result without changing anything.” But sometimes using the same approaches, statements and actions to obtain a seemingly predictable result, a person sincerely wonders why it did not work out this time.
There is an area where such actions would not only cause skepticism, but can be presented as the only correct ones - object-oriented programming.
We begin, as expected, with the weakest of the paradigms of the “SOLID principles”, which are good for not knocking out in granite. Prepare a lot of letters ...
We give a brief definition:
SOLID abbr. from English
single responsibility, open-closed, Liskov substitution, interface segregation and dependency inversion . Those. a rather small set of principles from the whole variety, but drawing clear boundaries between what can be done, what is better not to do, and what should be accurately reworked in your project.
')
Let's start.
Barbara Liskov substitution principle
L, LSP, Liskov substitution principle“The
objects in the program must be replaceable by instances of their subtypes without altering the correctness of the execution of the program ”
One of the weakest and non-feasible principles that dictates that we can replace abstraction with its subtype, and nothing should happen. It is even difficult for me to imagine something more distant from reality and not possible to perform already from the very definition. (It would be very interesting to hear the definition of "the correctness of the program," but we will not need it).
For primersThe literal statement sounded like:
Subtype Requirement: Let f(x) be a property provable about objects x of type T. Then f(y) should be true for objects y of type S where S is a subtype of T.
It operates not with a program at all, but with a property of one type. Which of course is less, but does not change the essence. In OOP, many types determine the operation of a program.
Consider whether the duration of the execution is subject to the need to follow this principle. Yes, the running time of an application is the same contract (property) as its input parameters and the result of its execution, as its pre- and post-conditions, a list of possible exceptions. Often they do not pay attention to him as a difficult teenager, and suddenly nothing will happen. It’s good if it turns out this way, but then the principle has nothing to do with it - pure luck, it wasn’t very necessary, it wasn’t very desirable.
Let's go further.
The amount of resources consumed: memory, CPU time, used cores, the need or absence of additional. equipment.
Sometimes replacing a single entity, for example, a method of logging from a file to a database does not require trivial things: connecting additional libraries, changing configuration files (I foresee a dispute whether to consider the configuration file as part of, falling under this principle or not).
If you dig of course, of course, you can reduce the requirements: they say not for all types, not for all properties, and not always. But then the essence of the principle is very blurred. Something from the category "You can go only to the green light, but if the traffic light broke ... or in direct line of sight at a distance of two kilometers you can not see the cars ... or the unicorn flies ^ _ ^ ''"
As designers or developers We are already taking a risk (often justified) violating the
Barbara Liskov substitution principle when we optimize or refactor code.
This principle will never be fulfilled , the simple replacement of Int32 by Int64 already makes it not feasible. I hope the inverse replacement of Int64 on Int32 does not cause anyone doubt its violation.
Fanatically sticking with it, you create something already “dead”, because it does not “breathe” at birth and when it does not breathe after. You yourself with enviable persistence will cut off all the "extra" in order not to change the behavior of the new. Once having created something, you are doomed to create also in the future.
Congratulations, you have created a corpse and carefully monitor the many hands in rubber gloves.
Principle of openness / closeness
O, OCP, Open / closed principle"
Software entities ... must be open for expansion, but closed for modification "
If the previous one can somehow be brought to the possibility of real application, then there are no options here. In the limit, you cannot change your code right after you raise your hands above the keyboard.
Perhaps you are comforted that you can change the code: before testing, before transferring to production, before releasing a version, before ... (select a few, or underline what you need, or add your own). It does not matter, you will always have this "TO". Weak consolation in systems whose life is not calculated for hours and weeks, but to last for years.
Have you ever observed that in nature, something develops "before"? The tree does not grow two meters exactly, always slightly higher, slightly lower. And until it is cut down will grow, some branch dries, some will develop. The only thing that is
not achievable in the real world is consistency .
Why go far: C => C ++ => (Java =>) C # and Java => Scala => Kotlin attempts to avoid this problem and not to solve it. Forced to adhere to this principle, sooner or later you will sit down and rewrite everything, if, of course, by that time your project is not so rotten that you have buried it.
This principle puts a final and fat cross on your project at the very beginning. Using it you create Frankenstein, in the hope that no one will notice the smell of a carcass.
The remaining principles can be left for the next article (if of course it follows) ...
The conclusion is prosaic. Modern development resembles the creation of dead ends in kunstkamera and their joint preparation in the process of creating, implementing and supporting projects. Therefore, often the very concept of “recycling” (termination, decommissioning) is not present in many life cycles of methodologies. Or they are given a couple of paragraphs (For an example, look at the libraries of surgery, when they really try to keep them alive).
Why write about what has already been created and so carefully hidden, deodorized and dissected. When each of the participants in the action, to whom earlier, to whom later, it becomes clear that "it is time".
Hope?
But what to do, you ask? (If of course you have read and thought). Creating "mutants" is also not an option. If something changes its behavior unpredictably, unnecessarily, then usually it either dies itself or is removed.
The answer is quite simple - look around, crawl out from under the piles of principles and methodologies. Listen to the advice, but think about when it’s time to follow them and when to break. Observe the contract you need, but no more. In the end, not many people wonder what your code does if it works correctly and expectedly.
If someone has bypassed your "feature", it is better to let him remove this crutch, which has become unnecessary, than you will continue to support the erroneous decision with perseverance. (A good analogy with a patient who does not want to leave crutches that have become unnecessary after removing the gypsum, he is used to them. Conveniently, and his leg hurts when walking)
If someone (client, manager, PM) needs to stay in place, get a version for him and let him dissect, help him sometimes (especially if he pays). But do not hesitate to show a better solution. Give the person a chance to change solutions.
Do not go into an endless cycle. It makes no sense to justify the lack of results of the desire to create the eternal, it is impossible. Create small, but necessary now and “live”.
Beware the next time you train, instruct, and demand that you complete your tasks. Look if the "madman" who will "dissect the corpse" in full confidence that saves the "world" looks into your eyes.
Do not create corpses. Develop or die.