The hidden cost of abstraction in modern software culture
TL;DR: Abstraction isn’t free. DRY isn’t sacred. And “clean code” isn’t always readable. We’ve built a culture that worships design principles without questioning their cost. It’s time we did.
🧱 The Gospel of Clean Code
When you write duplicate lines of code, your brain reflexively itches to extract them into an abstraction—not because the code demands it, but because the culture does.
You extract a function—or a class—and then try to pigeonhole it into another use case, forcing reusability where it wasn’t meant to fit.
And just like that, your local reasoning—perfectly at home in its corner—is marooned in the frozen tundra of remote abstractions.
Tracing indirection turns your mind into a stack of context switches, each deeper than the last.
But hey—it’s DRY. SOLID. Reusable.
Right?
Until it breaks your brain.
🧨 The Lie Beneath DRY
DRY—Don’t Repeat Yourself—was never meant to mean “never write the same line twice.” It was about not duplicating knowledge. Don’t let the same business rule live in two places.
But we turned it into a reflex. A dogma. A purity test.
And that’s when DRY becomes a lie.
We avoid repetition—and trade it for something worse: indirection, entanglement, and fragile abstractions.
🧩 The Hidden Cost of Abstraction
Abstraction is powerful—but it’s not free. Every time you extract something, you’re making a bet:
- That the duplication is real, not just superficial
- That the abstraction will hold up under future change
- That the people reading your code will understand what you’ve hidden
When those bets don’t pay off, the cost is brutal:
- Cognitive load: You’re jumping between files, tracing layers, decoding generic names—just to understand what’s happening.
- Rigidity: Your abstraction locks you into a structure that resists change.
- Fear: No one wants to touch the “shared” thing because it’s used in 12 places and no one remembers why.
But at least it’s DRY.
📚 The Cultural Blind Spot
We’ve built an entire culture around abstraction, and almost no vocabulary for its cost.
We have bookshelves full of Clean Code, Design Patterns, and SOLID Principles. We have workshops on “how to write reusable components” and “how to architect for scale.”
But where are the books titled:
- The Cost of Abstraction?
- Refactoring to Duplication?
- The Art of Intentional Repetition?
They don’t exist—because we’ve treated abstraction as a virtue, not a tradeoff. We’ve made avoiding duplication a rule—and reasoning an afterthought. And we’ve confused “reusable” with “good.”
🧘♂️ Local Reasoning Over Abstraction
Here’s a radical idea: what if we made local reasoning our highest design virtue? Not reusability. Not elegance. Not DRYness. Just code you can understand without chasing it across files and layers.
Because the real cost of abstraction isn’t in the code—it’s in your head. It’s the number of things you have to remember just to answer: “What does this actually do?”
Repetition isn’t the enemy. Indirection is.
Because the truth is: duplication is easy to fix. Bad abstractions are hard to unwind.
🔄 The Alternatives We Ignore
There are principles that push back against abstraction dogma. But they’re rarely taught with the same reverence:
- AHA (Avoid Hasty Abstractions): Don’t abstract until duplication becomes painful.
- YAGNI (You Aren’t Gonna Need It): Don’t build for a future that may never come.
- Rule of Three: Duplicate once, maybe twice. Abstract on the third time—if it still makes sense.
These aren’t anti-design. They’re pro-timing. They recognize that the cost of a wrong abstraction is higher than the cost of a little duplication.
🧨 The Callout
So here’s the challenge: Next time you reach for that abstraction—pause. Ask yourself:
- Am I solving a real problem, or just avoiding repetition?
- Will this abstraction make the code easier to change—or harder?
- Am I doing this for understanding, or for comfort?
And if the answer isn’t clear—don’t abstract. Repeat yourself. On purpose. With pride.
Because sometimes, the cleanest code is the code that’s just… repeated.
If this idea of local reasoning struck a nerve—good. You’re not alone. In a follow-up post, we’ll dive deeper into the real complexity we forgot to measure: not code complexity, but cognitive complexity. Because the hardest part of software isn’t writing it—it’s thinking about it.
Footnote: Acronyms like WTFW (Why The Framework Works) and GRR (Generalized Refactor Regret) are real-ish, at least emotionally.
I think the main rule to DRY code is, when changes are needed will it be for all the cases or are there exceptions. Once you know there are exceptions, don't DRY the code.
I wouldn't go that far as throwing clean code and design patterns on the same pile as DRY. The abstractions there have another goal.
The rule of three does not make sense. If you copy it once you used the code two times.