5 ms·
The saying 'duplication is cheaper than the wrong abstraction' is a gem of a saying, but like many pieces of wisdom, takes experience to fully understand. I fi
by gorjusborg 3y ago
The saying 'duplication is cheaper than the wrong abstraction' is a gem of a saying, but like many pieces of wisdom, takes experience to fully understand.
I first saw the saying when DRY was being applied without any nuance. If a piece of code appeared in two places, it was obvious, and important, to factor it out, because that was 'good coding practice'.
The saying being discussed was pushback against that kneejerk, thoughtless application of DRY. The 'cheaper than the wrong abstraction' is pointing out that DRY isn't a 'no tradeoff' policy. By factoring out any duplication, many uses pass through the same code. If the uses don't quite match, there is a tendency for the code to get modified to fit them anyway. This, over time, makes the shared code simultaneously unfit for use, and widely used. A recipe for poor code quality and system health. Ironically, this is the outcome that DRY was called in to address.
- starbugs 3y agoAnything pushed to the extreme will result in its opposite. There's an interesting Wikipedia page about a concept from philosophy called "Unity of opposites": https://en.wikipedia.org/wiki/Unity_of_opposites https://en.wikipedia.org/wiki/Unity_of_opposites Worth a read IMHO.
- zogrodea 3y agoThanks for the link. This sounds more useful to refer to (because more general_ than horseshoe theory.
- starbugs 3y agoMaybe also worth a watch is this video from Ian McGilchrist: Ian McGilchrist: The Coincidence of Opposites https://www.youtube.com/watch?v=N4AFdNxLmb4 https://www.youtube.com/watch?v=N4AFdNxLmb4 Intro skipped: https://youtu.be/N4AFdNxLmb4?t=340 https://youtu.be/N4AFdNxLmb4?t=340
- serial_dev 3y ago> If the uses don't quite match, there is a tendency for the code to get modified to fit them anyway. And this is essential, this is how you'll end up 5 arguments and 6 further bool flags to an 7-line function.
- ilyt 3y agoAnd one of them for some reason takes from environmental variable...
- _the_inflator 3y agoDRY should be an option. Results may vary and depend on the code in question as well as the language you are using. We - a former team a couple of years ago using Java - started to duplicate code in Java, because we were totally tired of interface'ing and class'ing everything away that was not DRY. It became to tedious to bloat code with them as well as understanding whole classes when all you got was references to other interfaces etc. If there is a small service architecture like in Angular with TypeScript, abstracting away becomes fun and useful. It all depends. But what I really do not miss is the pile of interfaces in Java and C#. These became so tough to grasp and entangled, that we DRY'ed this cesspool. DRY on DRY so to say.
- switchbak 3y agoSo your issue was with the nature of the language and the size of the project more than the application of DRY? I think I see what you're getting at, but I've certainly also seen very large Java projects that are simple at a high level and composed in such a way that they're still legible without a ton of duplication. These might be somewhat orthogonal concepts.
- wvenable 3y agoThe most important thing to note about DRY is that it's not about code -- it's about knowledge. You should not repeat knowledge -> logic, constants, etc. If the temperature is 87 and the price of the widget is 87 that is coincidence and not repetition. There should just be one source of truth for any logic or process. If you duplicate that then bad things will eventually happen.
- jasonswett 3y agoTotally agree, although I'd maybe replace "knowledge" with "knowledge or behavior".
- newaccount74 3y ago> You should not repeat knowledge -> logic, constants, etc. It's easy to shoot yourself in the foot with that. I spent a few years working with binary formats, where you have lots of constants (byte offsets, flags, etc). There were two approaches to dealing with this: 1) Some people just put the raw numbers in the code, and if it wasn't clear added a comment 2) Other people used constants for everything, defined somewhere else, often through multiple layers of abstraction. If you follow DRY, then you should always chose 2). But in my experience, this often makes the code extremely hard to read. You often have to look through a dozen header files to find the constants used in a 5 line bit of code, and it becomes really hard to reason about the code. And in the end you almost always still need some duplication, because you have other files where you can't use the constants (eg. in sample files, docs, external libraries,etc.)
- wvenable 3y agoI don't understand? Why do you need to know the value of the constant if the name is descriptive enough? X = 5; // File header offset vs. X = FILE_HEADER_OFFSET; I don't think there's much value in the idea that just because someone can implement something badly, it validates the whole idea. You should always use constants instead of raw values if they have some meaning. If someone, somehow, manages to make that so complicated that it's a pain it's still not the fault of the concept. > And in the end you almost always still need some duplication, because you have other files where you can't use the constants And those will invariably end up out of date and incorrect at some point.
- devjab 3y agoI think it’s down to the systems, and I think the people who favour abstraction often forget who needs to write it. Duplication isn’t just cheaper than the wrong abstraction, it’s cheaper than almost any abstraction. Not because it should be, mind you, but because duplication works for a tired Thursday afternoon programmer and abstraction doesn’t. Maybe it’s because I spent some time in management, but a key concept I worked with when I did that was how we have two modes of mental capacity. One where we have the energy and wit to do the right thing, and one where we haven’t slept for a week, and, well… it’s Thursday afternoon after a day of too many useless meetings. I think the best way I saw it put was for a Theme-park to coin a slogan that any employee would be able to find inspiration in when dealing with a customer on that Thursday afternoon. To me most abstractions are similar to having a slogan along the lines of “Think Different”, which is an absolutely useless concept when you’re tired and dealing with an angry customer in your summer job about an hour before you clock out. I obviously don’t think you should avoid all abstraction. The author of the article is right, theoretically at least, it’s just that this way of thinking rarely works out. Similar to you, my experience is that it tends to fail after a few years of changing needs. These days I favour abstraction only when it’s use is never altered in the slightest. For everything else duplication is so much easier to handle over 5+ year periods. Of course there are many ways to deal with this. Small single purpose functions are abstractions as well, just don’t build big OOP hierarchies. Because they just don’t work for those Thursday afternoons.
- mekoka 3y agoEntirely agree. DRYing is compression. It serves similar purpose. Like a mathematical equation, it's terse, light, elegant, easy to carry in one's pocket, yet loaded with meaning. It's not, however, zero cost. At maintenance time, it needs unpacking. DRYing is also not an exact science, nor a hard rule. It's the factorization of a specific idea (at least that's what it should be). When applied, it requires usability and cognitive considerations. That's the delicate trade-off. "Will people coming after me have an easy time figuring this out?" The newbie who comes to an existing code base and proceeds to indiscriminately DRY things up often doesn't realize that the reason they were able to do so in the first place is because, although repetitive, they could understand the original source, often without much effort. That's why repetition is cheaper than the wrong abstraction.