DRY stands for don’t repeat yourself, it is the software version of don’t reinvent the wheel. And DRY is a fine principal but it’s not like my favorite principal, we’ll get more into this in a bit.
For now let’s take a moment and be real with ourselves, we aren’t building deserts.
Code is recreated all of the time, I have written code to handle validation almost everywhere I’ve worked. How many OS’s are there? Do you think all of the streaming services are happily sharing code? And sure we could all use open source but let’s be real about that too, there are many open source libraries that do the same things. There are 100’s of libraries that handle JWT’s.
You know in your heart of hearts this is true. It may even be what is causing you to upsize your coffee in the morning.
We aren’t building DRY deserts it is more like a humidifier in a flooded room. Sure we gain some efficiency by reusing that module that Kenny wrote. And we should use Kenny’s module, way to go Kenny!
But this is a little desert island in the middle of a vast ocean.
Think of all of the competing products in the world, how many times has bejeweled been written? I think it is pretty safe to say there are more repeated bits of code than unique pieces of code.
I am not trying to be mean there is a point to this harsh reality check. I think it is important for us to leave our fantasy desserts fly up and gain some perspective every once in a while.
Reusing existing code should be something we try to do. But there is no need to get so fussed over some repeated code. There are times when we should repeat code.
Wrong Abstraction
“prefer duplication over the wrong abstraction” — Sandi Metz
The point Sandi is making here is if you only understand part of the problem, let’s say 7 out of ten use cases are unknown. And you create a generalized solution based on the 3 use cases you know, then when use cases 4–7 pop up over the next few years you are in for some pain. As dealing with incorrect abstractions either leads to duct tape code, or major refactors.
Whereas if you had built each use case separately there would be some duplicate code but adding newly discovered use cases would slide in with ease. And eventually the right abstraction could be created.
This partly comes down to how likely is a piece of code to change? The more likely code is to change the less worthwhile it is to generalize it.
One simple example of this is internalization, if you have two parts of your UI with the text “name,” you wouldn’t want to use the same key. This is because you want to have the freedom to change one of the labels without changing the other.
Complexity
Most of the time it is not worth introducing additional complexity into your system just to avoid repeated code.
It often seems that repeated code is the biggest lost of efficiency but it is not. Complexity is. Systems that are more complicated than they need to be waste the time of every developers that works on them.
If repeating some code is the way to keep things simple, by-gone-it repeat some code!
Conclusion
I could go on, there are actually a lot of reasons not to adhere to DRY all the time. It is a good principal but not a great one. We should strive to build things once and improve them, but foremost we should strive for simple code; code that is easy to read and modify.
That is what we should wear as a badge of pride, let’s stop getting so fussed over DRY and focus on more important parts of design.
And if you find yourself in a debate about this, remember we are not desert power, we are desperately trying to sop up water from a busted water heater with a couple towels. A few more cups of water, it isn’t going to make a difference, the war against repeated code has already been lost.