3 ms·
In my experience, there's a costly dimension to DRY that doesn't get enough love: dependencies. DRY incurs a significant dependency cost. This has been painfu
by cle 10y ago
In my experience, there's a costly dimension to DRY that doesn't get enough love: dependencies.
DRY incurs a significant dependency cost. This has been painful for me, since I work on distributed systems a lot. When you have an ardent follower of "DRY" who refactors a common utility so that many subsystems of a distributed system have a code dependency on the same piece of code, then changing that piece of code can become very costly. When that cost gets too high (e.g. requires coordinated deployments and lots of cat herding with owners of other systems), then the DRY has just painted you into a corner where the cost of changing your code is higher than it's worth, and you end up with a rotting code base because the cost of change is too high.
Please, please factor that cost into your decision to wield DRY in distributed/service-oriented systems!
Code dependencies have diminishing returns in increasingly distributed systems...try to find a way to encode the common functionality as data instead of code and you'll be way better off.
- icebraining 10y agoIn that case, can't you then just un-DRY (hydrate?) the code by branching it for each subsystem? Then each team can keep its own pace, and still cherry-pick improvements from each other, which would be difficult to do if they were simply pieces of code copied all around the codebase.
- taejavu 10y agoThe opposite of DRY is WET (Write Everything Twice) ;)
- dpark 10y agoYes and no. Once a half dozen components take a common dependency, that dependency tends to grow large and complex. Where each component needed a simple string templating class (for example), the aggregate dependency ends up doing too much and is overengineered. It has multiple layers of abstraction to make the various string manipulation classes "look the same" and therefore justify DRY refactoring. So yes, you can just "rehydrate" the dependency into each component, but you often end up needing a fair bit of work for each component to untangle the mess and create the minimal dependency that each component actually needs. If you just want to copy the dependency directly, then sure, that's typically pretty easy. But that's also typically a pretty terrible outcome as now you have tons of duplicated code and modifying the dependency implies duplicate work, and worse, duplicate pointless work as you must maintain the pieces your component doesn't even use.
- jnordwick 10y agoI work on mostly distributed systems too and that's why I'm in the DRY camp (but only after the 2nd iteration kind of thing -- mostly). That's where the experience pays off. I think DRY is taken to extremes and you get that one-line function that does nothing meaningful except rename append or something equally trivial (rename append then append space). I like small code bases. I like only have to make one bug fix. I like being able to rewrite large chunks of code (like entire protocols). And DRY lets that happen. But I also like readability, and something that can fight against DRY I realize. I'm a pragmatist at heart. And coding is really a craft. So all these maxims have their use, but it just takes experience to know when to use and break them. But overall I see DRY as one of the more vital.
- michaelcampbell 10y agoYup. While DRY is often sold as "everyone gets to use it!" but in reality becomes "everyone HAS to use it". I like to think of this as: DRY (Don't Repeat Yourself) needs to be weighed against DRY (Don't Refactor... Yet). This can be mitigated somewhat by liberal and thoughtful use of SemVer or equivalent. (There is also, of course somewhat tongue in cheek; WET - Write Everything Twice)
- naasking 10y ago> When you have an ardent follower of "DRY" who refactors a common utility so that many subsystems of a distributed system have a code dependency on the same piece of code, then changing that piece of code can become very costly. Is this a piece of code that actually requires co-ordinating all nodes so they're running the same version of the code? Otherwise I'm not sure I see the problem, since you can just run old versions of the shared code in parallel with new versions.
- rtpg 10y agoIf the utility requires all the subsystems, then doesn't the dependency exist no matter how the code looks? Of course you can refactor to reduce dependency scope at a code level(the essence of functional programming), but if in order to do X you need to access W, Y, and Z, then I don't see how code changes will affect this deeper truth.
- rimantas 10y agoThe something is wrong with your DRY. Otherwise it is not clear why that dependency is costly and why changing it is so painful. Sounds like code is moved outside but is still tightly coupled.