A decade-old software-design essay by programmer and author Sandi Metz has returned to attention with a deliberately counterintuitive message: sometimes duplication costs less than forcing unlike requirements through a single abstraction. First published on her blog in January 2016 after appearing in her Chainline newsletter, the article develops an idea Metz had raised in a RailsConf talk two years earlier.

The argument starts with a familiar refactoring. A programmer sees repeated code, extracts the common work into a method or class, gives it a name and replaces the copies. At that moment the abstraction may be clear and useful. The trouble begins when a later requirement resembles the original cases without matching them. A second programmer preserves the shared component but adds a parameter and a conditional path. Further requirements bring more switches and branches until the once-universal concept performs several only loosely connected jobs.

Metz describes the result as difficult to understand and easy to break. Existing code also creates pressure to retain the accumulated investment, even when its shape no longer reflects the problem. That pressure is a version of the sunk-cost fallacy: the more effort a team has put into a complicated component, the harder it can feel to dismantle it.

Her proposed recovery is to move backward before trying another abstraction. Developers can inline the shared behavior into each caller, remove the conditionals and leave every call site with only the code it needs. With the cases visible independently again, teams can compare their current behavior rather than the assumptions that informed the original refactoring. New duplication may then reveal a smaller, more accurate common idea—or show that the cases should remain separate.

The advice is not a blanket rejection of reuse. Metz allows that a few conditional paths can sometimes help a team learn what a problem contains. Her warning is about continuing to expand a shared component after evidence shows it no longer represents one concept. Parameters that select substantially different behavior are a signal to reconsider the design, not an obligation to add another option.

The essay’s continued relevance comes from that distinction. “Don’t repeat yourself” is often taught as a direct rule, but the post treats abstraction as a hypothesis that requirements can disprove. Duplication is visible and local; a mistaken shared model can spread complexity across every caller. Metz’s practical conclusion is that deleting an obsolete abstraction is not a retreat. It is a way to make the current problem legible enough for a better structure to emerge.