We have become obsessed with abstractions, DRY principles, and "best practices". The result? Codebases that are impossible to change. Here is why I embrace "Write Everything Twice"
I used to be a Clean Code zealot.
I would spend hours refactoring a working function just because it had too many lines. I would create abstract classes for features that didn't exist yet. I religiously followed DRY (Don't Repeat Yourself).
If I saw the same logic twice, I abstracted it immediately.
Ten years later, I realized something painful: My "clean" code was actually the hardest code to maintain.
Here is why the industry obsession with "Clean Code" is a trap, and why you should probably lower your standards.
1. The Wrong Abstraction is Expensive
The cardinal sin of Clean Code is "Premature Abstraction."
You see two functions that look similar. You merge them into one generic function with a few parameters. It looks neat.
Two months later, one use-case needs a slight variation. You add a boolean flag. Then another variation needs an if/else. Then another.
Suddenly, your "clean" generic function is a monstrosity of conditional logic that breaks 5 different parts of the app every time you touch it.
The Fix: Use the WET principle (Write Everything Twice). Copy and paste is not a crime. It decouples your logic. It is better to have duplicate code than the wrong abstraction.
2. Optimization for "Reading" vs. "Changing"
Clean Code books tell us to optimize for readability. Small functions. Descriptive names.
But in a startup or rapid-growth environment, the most important metric is Changeability.
Code that is split into 50 tiny files and abstract interfaces is hard to change. You have to jump between 12 tabs just to understand a single data flow. That is cognitive load.
Sometimes, a 500-line function where you can see everything happening in one scroll is superior to 10 "clean" 50-line functions scattered across the project.
3. "Best Practices" are for Google, Not You
Most "Best Practices" (Microservices, Hexagonal Architecture, intense TDD) were invented by companies with 10,000 engineers to solve communication problems, not engineering problems.
When you apply enterprise constraints to a 3-person team, you aren't ensuring quality. You are ensuring slowness.
4. Code is a Liability
We treat code like an asset. We polish it like a trophy.
But code is a liability. Every line you write is a line that can break, needs testing, and requires reading.
The goal of a Senior Engineer shouldn't be "Beautiful Code." It should be "Minimal Code."
The "Good Enough" Manifesto
I am not saying you should write garbage. But there is a massive difference between "Sloppy" and "Pragmatic."
Sloppy: No variable names, no consistency, bugs everywhere.
Pragmatic: Duplication is okay. Long functions are okay. Hard-coding values is okay until you need them dynamic.
Stop trying to impress the compiler. Stop trying to impress "Uncle Bob."
Write code that is easy to delete. Because the only code that doesn't have bugs is the code you delete.
Agree or disagree? Are we over-engineering our daily work? Let’s fight in the comments.
Top comments (8)
Every extreme is dangerous. The Truth is in the Middle way. The balance.
You are absolutely right. The middle way is usually where the actual engineering happens.
I wrote this with a bit of extreme energy because I feel the industry pendulum has swung too far toward abstract perfectionism. Sometimes you have to push hard in the other direction just to help people find that balance.
"abstract perfectionism" ... brrr... 🥶
Sounds like bloaty enterprise software coated by a Clean Code finish - bon appetit! 😅
This is the dichotomy of a software developer - purist vs pragmatism.
As one gains experience (it's in the struggling and understanding that learning takes place), we learn to not follow architectural dogma (a method needs to have max (x) lines of code), but instead focus on simplicity.
What I tell my devs is that if you build it, you have to maintain it, so following dogmatic principles for the sake of doing the "right thing because the industry says so", often leads to a lot of indirection, and opening like 5 or more files just to understand how a basic feature works.
The point about opening 5 files to understand a basic feature is painfully accurate.
We often confuse "decoupled" with "scattered." Excessive indirection is usually harder to maintain than a slightly longer function where the logic is actually visible.
Pragmatism over dogma is exactly right.
I wouldn’t recommend replacing one misunderstood rule with another rigid one. The whole Clean Code movement has strayed far from its original intent imho.
SOLID has become a dogma for many, blindly followed. And “The Bobfather” seems to feel pressured to keep churning out controversial content just to stay relevant.
Don’t get me wrong: SOLID, Clean Architecture, and the like are powerful tools for improving code communication. But following principles dogmatically misses the point.
In teams that “do Clean Code,” I often see SOLID or Clean Architecture applied “by the book”- resulting in bloated code, forced patterns, or unnecessary framework-like structures. This never happens out of malice, but always with the best intentions.
Clean, understandable structures are valuable because they guide you through the code and fulfill their purpose. But just because something is “modern” or “trendy,” you shouldn’t rewrite a 20-year-old, rock-solid codebase.
If your code pays the bills, make changes deliberately and wisely.
And then there’s all the tooling around coding:
I appreciate the suggestions from my IDE, ReSharper, SonarQube, CheckStyle, RuboCop, and the rest. These tools have taught me a lot and improved countless snippets. But here’s what I’ve learned from decades of working with hundreds of repos:
You never want to be surprised by a Monday-morning pull request with 10,000+ changes in your stable legacy code - just because someone wanted to “try out that new language feature,” “fix some minor sonar issues,” or “introduce some new pattern.” Or just to boost their personal Clean-O-Meter score.
All these tools and principles are meant to assist, not dictate.
This is the nuance that often gets lost. You are absolutely right that we shouldn't replace the Clean Code dogma with a "Sloppy Code" dogma.
The Monday-morning pull request scenario you described is painful. Refactoring 10,000 lines just to satisfy a linter or try a new pattern introduces massive risk for zero business value. That distinction—between improving code communication vs boosting a "Clean-O-Meter" score—is what separates experience from enthusiasm.
Tools should definitely be assistants, not dictators.