Three Rules of Thumb for Code Reuse
Software engineers love acronyms for principles. DRY ("Don't Repeat Yourself") and WET ("Write Everything Twice") represent two ends of a spectrum: strict avoidance of duplication versus deliberate acceptance of it. Both can be taken too far. A more pragmatic middle ground is AHA — "Avoid Hasty Abstractions," an acronym attributed to Cher Scarlett.
The Limits of DRY
DRY is commonly summarized by Wikipedia's definition: "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system." In theory, this prevents bugs from propagating across duplicated code. In practice, the pain of discovering and fixing the same bug in eight different places — a scenario faced when inheriting a codebase with heavy copy/paste usage — makes a strong case for centralizing logic into reusable functions.
Yet the opposite extreme is equally problematic. A codebase can suffer from over-abstraction that is far more harmful than duplication. Imagine AngularJS controllers where a function monkey-patches methods and properties onto this to pseudo-inherit capabilities. The code might be technically reused in dozens of places, but the abstraction is so convoluted that developers are terrified to make changes. In that case, plain duplication would have been easier to understand and maintain.
This is why Sandi Metz's advice rings true: prefer duplication over the wrong abstraction. Hasty abstractions built on incomplete understanding of future requirements often become the very thing they were meant to prevent — a barrier to clean change.
Optimize for Change
Predicting what code will look like in the future is nearly impossible. A week of perfecting an API for a new abstraction can be wasted when assumptions prove incorrect or the feature itself is scrapped. Since code will inevitably change, the best strategy is to focus on making change easy rather than making abstractions elegant.
This is not an argument for chaos. It's an argument for timing. Duplication should be tolerated until the use cases become clear. Once the same code has been written in several places, the true commonalities emerge and the right shape for a function or component becomes apparent. Early abstraction, by contrast, invites developers to bend code to fit an assumed interface, eventually turning the abstraction into a tangle of conditionals.
A real-world check: when reviewing a codebase with a tool like jsinspect that finds copy/pasted chunks, the appropriate abstractions often seem obvious to an outside observer. But those observations only become reliable after seeing multiple instances of the duplicated code — not before.
A Pragmatic Takeaway
Software principles should guide judgment, not dictate hard rules. DRY encourages important consolidation. WET valides that writing the same code twice is acceptable. AHA suggests the real answer lies in mindfulness: don't be dogmatic about when to write an abstraction, but don't be afraid to duplicate code either. Write the abstraction when it feels right, and let the code itself signal when that moment has arrived.



