5 ms·
DRY is not about reducing code -- in fact, it's right in the definition the author provided: > Every piece of knowledge must have a single, unambiguous, author
by wvenable 6y ago
DRY is not about reducing code -- in fact, it's right in the definition the author provided:
> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
It says "knowledge" not "code". This is an important distinction. Removing duplicate code might not be removing duplicate knowledge and having duplicate/similar code doesn't necessarily mean you're duplicating knowledge.
A toy example: if you happen to have 2 products that are the same price you still wouldn't want to combine them into one constant value.
Some code might be similar by happenstance and combining that will cause problems when that happenstance stops being the case.
- ninkendo 6y agoWhile I largely agree with you about what the right kind of takeaway you should get from DRY, it seems like a no-true-Scotsman argument to me. DRY stands for “don’t repeat yourself”. that’s its de facto definition, unfortunately... whether it’s useful or not. Just like REST and OOP and a host of other things that “everyone gets wrong”, you have to consider that if everyone gets it wrong, maybe the messaging isn’t very good in the first place.
- dragontamer 6y ago> Just like REST and OOP and a host of other things that “everyone gets wrong”, you have to consider that if everyone gets it wrong, maybe the messaging isn’t very good in the first place. In my experience, it just means that an army of ignorant middlemen grabbed hold of a concept and ran too far with it. OOP / UML / XML / etc. etc. They all actually solve problems very well. But the people who taught those concepts were mostly selling snake-oil under the guise of XML or whatever. If any particular paradigm becomes useful: the parasite class of marketers / con-men come out and sell fake versions of the strategy. Eventually, the con-men completely corrupt the concept and we just have to move on to the new concepts that haven't been corrupted yet.
- fckthisguy 6y agoI see this all the time in well-intentioned "agile" projects. They fail to fully understand the domain and then micro optimisations like this lead to features breaking in interesting and unexpected ways.
- smitty1e 6y agoI get a kick out of the OO languages that factor everything to such a fine granularity that there seems to be one line of executable code per class. The exception traces go on for a couple of screens, so I guess the coders feel like their CompSci degrees are justified.
- TeMPOraL 6y agoOn a related note, I've seen people taking this too far in functional/procedural code. Not every concept needs its explicit name, not every function needs to be 5 lines of code or less. All that jumping around between function definitions is a serious impediment to readability. (EDIT: this is mentioned in the article as "localization complexity")
- sitkack 6y ago> Not every concept needs its explicit name There is a special subgenre of functional programming, where the style is to explicitly not have names https://en.wikipedia.org/wiki/Tacit_programming https://en.wikipedia.org/wiki/Tacit_programming (also known as point-free)
- dsego 6y agoI've been thinking about it lately. Esp. since I've taken another look at the refactoring chapters of Clean Code, but instead of being enlightened I felt disgusted. Like, for-loops are ok, if-statements are ok, those are the basic constructs of code, you can see the shapes visually and it's easy to follow the code path. This is what you find in low level C/C++ code, lots of switches, loops and conditionals. Those programmers just get used to the verbosity and look at shapes instead of reading line by line. Maybe it's easier for subtle mistakes to pass unnoticed, but refactoring out everything into layers of abstraction brings jumping around and context switching between these different pieces and trying to make a mental picture of how it all fits together.
- bcrosby95 6y agoYes, a better description of DRY might be "one place to change a fact". It's a specific example of my general rule in designing my projects: things that tend to change together should be closer together.
- brightball 6y agoI really like that explanation and I’m probably going to steal it. :)
- dgb23 6y agoPerfect! It implies that there is something you have to think about before you think about DRY. This "something" is representation of facts and data. The universal idea of pulling data out of code seems to be as old as programming itself and is proposed by Unix/C programmers and Lispers alike. After pulling out the data, the code becomes simpler, more general and more composable. The data structure then often reveals repetition that is not redundancy: If you look at a configuration file, a SQL table or a REST response that has repetition, it becomes clear that it represents different facts (to use your term) that happen to have the same values (Alice and Bob have the same age). This form or repetition is fine, correct and often interesting! So by the practice of pulling out data from code we get DRY (by the definition of the authors) code. However there is also also another form of repetition that is a bit more subtle: boilerplate. There, the representation of an algorithm (as code) is drowned in noise that does not convey the intent and the flow of what is happening. To increase the signal to noise ratio in code that is already(!) DRY but clouded by boilerplate, one needs a way to reduce syntax itself, which can be achieved by meta-programming and DSLs.
- keithnz 6y agowhen that happens it's called coincidental coupling, when two things get coupled together for the wrong reason. It often is done when people are trying to be too "dry" and trying to remove as much duplication as possible. But duplication is just an "indicator" that something might have bad modularity. However code should have good design principles guiding it and must drive modularity decisions like ensuring modular parts have good cohesion, it's not simply just because there is duplication.
- hinkley 6y agoThe Sahara-loving sort of people can justify both definitions of DRY for the same code change. Often they've gone into removing idiomatic code as if idiomatic code isn't a presumed piece of knowledge the entire team shares, and seeing that code indicates "everything is normal" while seeing a function indicates "something odd may be happening, spend cycles looking at me". The other definition is requirements, rather than knowledge or duplication. If two pieces of code are driven by separate requirements, eg, the price of two items is typically based on very different business situations, unless the two items are flavors of the same beverage perhaps, then the fact they share a price is an accident of the current state of the business, not dictated by a common requirement that they both be $1.50. If both have to calculate sales tax because of the same statute, then don't implement the calculation twice. If a new statute changes that situation, for instance due to a sugar tax, split the code when the new requirement comes in.
- MaxBarraclough 6y agoInteresting point. We could say then that it's a special case of the principle that illegal states should be unrepresentable. [0] [0] https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/ https://fsharpforfunandprofit.com/posts/designing-with-types...
- weeboid 6y agoYou talking politics in a coding thread?!
- dynamite-ready 6y ago"A toy example: if you happen to have 2 products that are the same price you still wouldn't want to combine them into one constant value." A more common example, take an online clothes store. They only sell shirts and trousers (pants - :]). It's a really simple app. Obviously, I'm skimming a great deal here, but each product category is described by the following properties: - Shirts -- Price -- Size -- Colour - Trousers (Pants - :]) -- Price -- Size -- Colour -- Length What the DRY principle generally addresses, is this basic idea. My instinct would be to create an abstract class called Clothing: - Clothing -- Price -- Size -- Colour Trousers (Pants - :]), for me, would definitely be an extension of Clothing. But until my suppliers can furnish me with Dresses, T-shirts, Scarves, etc, I would not be too concerned about even creating a separate Shirt class, but probably would. What I've since found through experience however, is that not everyone thinks this way. For some people, each product category would have absolutely have to have it's own wholly encapsulated class in this situation. I can see the problem such an approach attempts to head off, but until the problem actually exists, I believe this pattern makes the development process painfully inefficient, and harder to maintain. It's interesting to me, because while it seems like 'one of those' arguments, it's somewhat more impactful than 'tabs vs spaces'.
- weeboid 6y agoClassification systems ("ontologies") often represent a particular path through a graph, rather than an absolute tree. In your example, the store adds "Shoes". Then later, it adds "Sale Items". Now you want some shoes, trousers, and shirts to be on sale. So each item now has two edges, its "primary_category", and "sale_items". A little bit later, the store turns into a Sale Items at Massive Discounts! Store, and the primary ontology becomes price tiers. etc
- dynamite-ready 6y agoEven here, I feel we're overcomplicating things. For example, possibly ignoring what 'Shoes' are comprised of, were Clothing now to contain: - Clothing -- Price -- Size -- Colour -- Discount Then does your scenario really become as big a problem as you suggest? For one, some ontological relationships needn't be described in the same layer, or can simply be implied. A Red Fox, a Red Ant and a Red Snapper are definitely related in some way, but I wouldn't use the same class to program a representation of all three. A Red Shirt, and a Red Pair of Trousers/Pants though, probably share enough for a rough outline for online shopping app though.
- Cthulhu_ 6y agoI'm working in an older codebase (not THAT old, but it feels old because it's so bad), lots of database interactions. There's three data models (or sets thereof) that are mostly the same - MOSTLY. I could make the tables flexible (add columns to fit all data models). I could make the queries dynamic (make the table part flexible). But I'm duplicating code instead. As the proverb goes, a little duplication is better than the wrong abstraction. There's bits of code in here where the author tried to be smart, but queries like "select id from $table where x = $y" really throw my editor (and brain) off.
- sagichmal 6y ago> It says "knowledge" not "code". This is an important distinction. Yep. Though the same pathologies exist even with this framing. By that I mean it's easy to misdiagnose what the "knowledge" actually is. Even totally identical types and behaviors can be distinct in the knowledge sense if they exist in different contexts.
- zelphirkalt 6y agoOn the other hand you could argue, that "how a computer does things" is also some kind of knowledge. For example: How to render some part of a website for example or a calculation, which uses the same formula as is used in another part of the code to calculate a number. So with that interpretation of knowledge, you would have to avoid duplicating code. And it makes sense, because, if one day you need to change the way the computer does something, you want to avoid changing it in multiple places, because that makes it easy to forget places. This way avoiding duplicated code increases maintainability.