5 ms·
The most important underlying issue isn't discussed in the article: DRY must be understood and applied correctly. "Every piece of knowledge must have a single
by dgb23 3y ago
The most important underlying issue isn't discussed in the article:
DRY must be understood and applied correctly.
"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system"
The keyword here is _knowledge_.
When we see duplication, repetition and so on, then that might be because that piece of code represents:
- data of different entities that have similar structures
- logic that just happens to be similar.
- boilerplate code
None of these things have anything to do with representing the same piece of knowledge in a program. In fact, you can easily get into trouble _especially_ if you think the first two things are violating DRY when they are not.
I agree with the article, wholeheartedly though. If your code or data _model_ is not DRY, you can get into trouble very easily. Very nasty bugs, regressions during maintenance or extension, hours spent in frustration, money lost etc. On top of that: Non-DRY code almost always _proliferates incidental complexity_, because if you don't fix it, then eventually you patch over it.
Here's the best case scenario: Even if you are aware of code not being DRY, do everything right and turn multiple knobs at the same time to change or extend it correctly instead of fixing it, you will do so with much more reluctance and it will be much more mentally taxing.
Non-DRY code is by definition complex: You now have more interconnected parts than you need. So really, if you make your code more DRY, you _simplify_ it.
- dahart 3y agoMy favorite counter-acronym to DRY is WET: write everything twice (or thrice!). Doing and then redoing it once you understand it better is the best way to learn how to apply DRY correctly. > Non-DRY code is by definition complex: You now have more interconnected parts than you need. So really, if you make your code more DRY, you _simplify_ it. It really depends, I think there are some assumptions here that could use clarification. The whole point of choosing duplication is to disconnect parts that shouldn’t be connected, so I don’t understand what you mean about non-DRY code being more interconnected than duplicated code. Conscious duplication (often called “forking”) allows people who depend on a piece of code to change it without breaking anyone else. When you merge two pieces of similar code, they already had two or more separate uses, and you’re adding a new connection, tying together the fates of two or more different users. From now on, if they don’t have exactly the same agenda, there will be tension and/or bugs. If deduplication requires adding an abstraction layer, then that absolutely is adding complexity, and it happens because the code being de-duplicated was not exactly the same. Code that’s truly duplicated doesn’t need to change in order to de-duplicate. So you can delete a copy in that case and centralize the dependencies onto the remaining copy. That eliminates code but doesn’t really simplify; it has the potential to simplify future development, but it doesn’t simplify the code at the moment of deletion. With modern build systems and project structures, however, it might take a lot of work and it might add complexity to get the DRY code into the right spot where it’s visible to everyone who needs it. Another reason for duplication is to avoid having to do backflips to get the code into the right file or scope.
- hinkley 3y agoFor testing I prefer DAMP. Descriptive And Meaningful Prose/Phrases. I’ve watched otherwise smart people wrestle with testing boilerplate when requirements change and I’ve had my fill for this lifetime. Each test is a separate story. At most tests in a suite should share setup code. Anything more than that is coupling of tests, which is a no-no. The distinction between mocks and fakes are the most common place I see this blow up in our faces. Fakes result in coupling of tests. They were difficult to write so they get amortized across ten tests, making new requirements difficult to impossible to add without accidentally removing coverage of other requirements.
- dgb23 3y ago> Conscious duplication (often called “forking”) allows people who depend on a piece of code to change it without breaking anyone else. Then that code is DRY by definition and simpler. It can’t be Non-DRY because that would imply you’d need to change things in multiple places at once in order to avoid breakage. If you have two separate parts that can evolve independently, without coordination then those parts don’t represent the same piece of knowledge.
- dahart 3y agoWell all repeated code can evolve independently too, so by that definition, how can non-DRY code exist? This discussion is a bit too abstract and losing meaning as a result. I think you’re glossing over the very real scenarios of code (“knowledge”) that’s similar but not the exactly the same; of copies of code that are similar being merged; of code that’s exactly the same being intentionally forked and “repeated” and placed nearby; and others. Repeated code definitely can be the same piece of “knowledge” and exist in multiple places without coordination. After that the copies might drift in different directions, and the DRY dogma says this is bad. This is what people mean when they talk about DRY principles, the general idea to look for and merge similar code, and to prevent multiple pieces of similar code from being able to evolve independently. DRY in fact doesn’t really come up if two pieces of code are exactly the same; then it’s pretty obvious and easy to factor it. It’s a non-issue. The reason this is a concept we talk about is because bits of code are similar but not the same, or they’re they same but people need them to be modifiable without risk. I don’t know about using the word “knowledge” to represent processes with dependencies that change over time, it doesn’t seem like the best terminology for this discussion. Specifically, the word “knowledge” tends to imply a timeless static quality to the code. In reality all the of issues worth discussing here, all of the problems with DRY, and all of the benefits of DRY, relate to how code changes over time. Your point about similar but not the same code being different knowledge actually kind-of illustrates exactly why merging similar bits of code is dangerous, precisely why you shouldn’t just apply DRY principles blindly, and why sometimes rejecting the idea of DRY is appropriate in a given situation.