📜 ⬆️ ⬇️

DRY and the price of wrong abstractions


This article has long been on my list of tasks. But it seems that only today I have the strength and time to materialize it. Coincidence or not, but I am in the same cafe where I recently published my first article. Probably, in the drinks that are served here, something is mixed ...


So that? Bearded, good advice - follow the best practices? We constantly hear about them. We even gave them short nicknames, such as DRY or KISS, and use them on the machine in technical conversations. We are fanatically following the concept, and if someone accidentally wants to, or simply unknowingly, doesn’t observe them, we pour the buckets of dirty criticism onto them. We are prisoners of these beliefs and refuse to turn away from them at the right moment.


Of course, I do not hint that such principles as DRY are bad. This is definitely not the case. I just think that everything depends on the situation . Strong. As for DRY, it leads to the logical conclusion: "In fact, I am the one who sometimes inclines others to duplication, rather than abstraction."


Yes, you read that right. Duplicate code (also known as copy-paste) can be a useful practice. Especially when an abstraction that replaces repetitive parts of a code hurts when trying to figure it out.


How is the programmer's time distributed


When I tell people what I do for a living, they all think that I'm kind of weird, that I'm hitting the keyboard for ten hours a day or more.


Although I myself am not sure that I am fine, I am sure that I am not writing code for ten hours in a row. The bottom line is that we, as programmers, spend a lot more time reading the code , not writing it. I'm not sure that you have ever met such information, but research and Robert C. Martin argue that there is some proportion to this type of activity. And I, for one, see a striking difference. It turns out that for every hour of writing the code, there are ten hours of reading the code (one's or someone else's).


This is extremely important. The efforts that we put on the day of work go mostly to reading. Of course, reading the code is not enough. We still need to understand it . And this means that we must do everything possible to create clear, concise and easy to read code. It is beneficial to everyone, including ourselves in the future. Keep this in mind, because we will come back to this idea later.


A note about DRY


For those who are not familiar with the term DRY, it means - do not repeat (Don't Repeat Yourself). This principle of programming, or, if you wish, the best technique, is in favor of creating abstractions on top of each repeating part of the code.


DRY has a lot of advantages. The first is that abstractions suggest that if changes are needed in the future, you will have to cope with them in one place — in the abstraction itself.


Absorbing the functionality of another module, someone's API, etc. you only care about how the interface looks (or abstraction). You are not worried about the basic implementation. Therefore, software design patterns, such as an interface pattern, make it easy to perform refactoring of an implementation without interfering with the abstraction that others use.


So abstractions are good, and DRY fully justifies itself. Then why do I insist on copying code in some scenarios?


Well, just because ...


Price of abstractions


For each abstraction you have to pay. Costs can not always be estimated immediately. But over time, they float.


Abstractions contain an additional level of metadata. Metadata, the existence of which, in principle, may not be clear to you (especially if you did not write them). Each new piece of information increases the cognitive load on the brain. And, as a result, the time you spend reading such a piece of code increases.


Deep rabbit hole


The problem with DRY and fanatical worship of this principle is not noticeable in small projects. But noticeable in medium and large.


In such projects, it is very rare if only one abstraction falls on one copy. Because, as the project develops and new requirements emerge, the old code always needs correction.


Imagine such a scenario. You are joining a new project and viewing the code for the first time. After you get used to how it is built and understand how everything works, you begin to implement new options, change old ones and so on. You modify existing code and abstractions. You did not write all this, but it is there. And this, most likely, has a very good reason.


As Sandi Metz said:


Already written code has powerful authority. Its very existence testifies to its correctness and necessity.

He makes you not want to touch him.


Now a new feature can definitely use the good abstraction that already exists. But, as it turns out, abstraction needs a little refinement. It was not designed for this particular user scenario. If only you could change it a bit ... Or maybe write over the existing new abstraction that encapsulates additional repetitive logic, m? Yes, it seems the right decision! This is what DRY implies ...


You can clearly see how we can bring this madness to the absolute extreme. Extremes where everything is encapsulated in abstraction. And those, in turn, are wrapped in more complex abstractions. And so on to infinity ...


In such cases, abstraction loses its value. It exists because of the beliefs we blindly follow. And this makes abstraction incorrect. It exists only because we have the opportunity to create it.


As already mentioned, abstractions exert a cognitive load on the brain. Almost always, we pay with obstacles and time needed for decoding (remember, we spend more time reading the code than writing). But an incorrect abstraction is worse than just an abstraction.


Because incorrect abstractions not only beat you in the balls, they are still bending over with laughter even at this time.

DRY or not DRY


So when does encapsulate repeating code, and when not?


The answer is essentially simple. But from a practical point of view, not quite true. But it also comes with experience.


Abstract always, if abstraction does not turn out to be more expensive than duplicate code.

That is, if another project participant spends hours trying to understand the abstraction that you wrote, then you are probably doing something wrong. Do not create an abstraction just because you have the ability to do this. Predict whether the duplicate code will still occur in this particular part or not, and make the appropriate decision.


Sometimes duplicating is less labor-intensive than following the tree of nested calls of various methods, tracking the transmitted parameters and possible side effects, etc.


Final thought in defense of yourself


I hope this article does not scream "to hell with this DRY and other shit!". I unconditionally consider it a good programming principle. But still, I urge you not to follow him blindly. Consider everything you learn in context and always question the validity of your ideas and actions. This is the only reasonable way to improve professionalism.


(Translation by Natalia Bass )


')

Source: https://habr.com/ru/post/311014/


All Articles