4 ms·
I don't think conventional wisdom is an anti-pattern, exactly. Better to think of it this way: It's a starting point, not an ending point. E.g., for DRY, if
by jmull 4y ago
I don't think conventional wisdom is an anti-pattern, exactly.
Better to think of it this way:
It's a starting point, not an ending point.
E.g., for DRY, if you notice yourself copying and pasting the same code around you might spend a few seconds thinking about whether there's some commonality worth capturing or abstraction worth building right now or not. The answer could be yes or no (for a variety of reasons), but it costs very little to reflect on it.
(I'm not a fan of DRY though, as it's generally presented. Whether something is a good abstraction point or not doesn't really directly depend on how many times you're writing that code. WET, as presented here is even worse in this regard. If you're copying code around there's probably some useful abstraction to make, but simply barfing out a utility function every time probably leads to a lot of bad abstractions. Code is expensive -- to write, test and maintain, so it's good to minimize it. But abstractions are expensive too, since they directly affect the code written in terms of them. Bad abstractions don't end up making anything better, and probably make them worse since they will force you into a form of spaghetti code you might otherwise have avoided.)
- bsder 4y ago> E.g., for DRY, if you notice yourself copying and pasting the same code around you might spend a few seconds thinking about whether there's some commonality worth capturing or abstraction worth building right now or not. DRY doesn't stop the kind of people who blindly copypasta, anyway. To me, DRY is more about avoiding desync. I should not define a constant in two different places--that will desync into a bug. I should not define a data structure in two different places--that will desync into a bug. A function, on the other hand, might actually want to desync after copypasta.
- aleksiy123 4y agoPretty sure this is what DRY is supposed to be. Should be renamed really. If something needs to stay in sync it should be defined once. Things that looks sort of similar, don't necessarily need to be defined only once because its okay for them to diverge or desync and they probably eventually will.
- kazinator 4y agoProblem is that the very definition of a cache is that you have the same thing in two (or more) places, which have to stay in sync. So blind adherence to DRY amounts to never using the technique of caching.
- aleksiy123 4y agoIts more a general guideline. In practice we break it all the time because it's not always possible or we may want to trade off for something else (performance in your case). Though generally I think when we talk about DRY in the code style sense vs the data (source of truth) sense these are related but different. However, even at Google there is a if_change_this_change_that lint rule to keep code changes between different files in sync. Meaning there's cases when you will have to define the same thing twice.
- kazinator 4y agoIf it's a general guideline, it reasonably extends to cover copy-paste code scenarios too.
- layer8 4y ago> Should be renamed really. There’s SPOT = Single Point Of Truth [0], which fits better for this. When multiple pieces of code are to be kept in sync, it’s because they’re based on a shared truth. And that truth should be defined in a single place, and not have multiple copies that need to be kept in sync. [0] https://wiki.c2.com/?SinglePointOfTruth https://wiki.c2.com/?SinglePointOfTruth
- ozim 4y agoData structure has traps like - it has the same properties so it seems like something to DRY up. But if we add context that one of these is used on exchange of data with DB and the other on exchange data with frontend. Now we want these to to desync because there are valid reasons for that but at the start of project it seems that these have the same properties but again these are used in different contexts.
- a4isms 4y agoI feel there are two separate things going on: First, the question of deduplication a/k/a normalization. Deduplication is cheap, and it's "a two-way door, not a one-way turnstile:" It's cheap to re-duplicate when you find that one of the users of your de-duplicated function or whatever needs new behaviour. Second, there is the question of the right versus wrong abstraction: If two different things use the same thing, that doesn't necessarily mean that they share the same abstraction conceptually. But of course, sometimes the duplication is a hint that there is some semantic commonality, and when you get this right, it's glorious, but if instead of de-duplicating we actually build the wrong abstraction, it can be extremely expensive to fix. That's more of a "one-way turnstile" problem. To me, when I see code that could be "DRY'd up," I have to ask myself whether it represents an opportunity to write a better abstraction, but I treat that decision conservatively, because of the cost of getting it wrong. In many cases, I choose to de-duplicate the code without creating what might be "the wrong abstraction," and it is often less expensive and lower risk to start there and only later consider abstractioneering. p.s. The tension between de-duplication and abstractioneering resembles the tension between is-a and has-a, often expressed by classical OO programmers as "inheritance" In those terms, I'm really describing my inclination as "Prefer composition to inheritance by default." p.p.s. Sandi Metz asserts that de-duplication is creating a new abstraction: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction. I feel that there is a sliding scale from "extract method" to "These two things share a superclass with a private message," but read her thoughts and come to your own conclusion.