First published on my blog: http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/
Intro: Why the Knife in the Sink Matters
A cluttered kitchen doesn’t happen all at once.
It starts with one knife left in the sink. One jar not put back. A cutting board with a little oil on it. Nobody panics. Nothing’s “broken.”
But over the next few hours—or days—something shifts.
You can’t find the clean spatula. The counter is sticky.
Cooking becomes frustrating.
And the worst part? You don’t notice the mess until it’s already changed how you behave.
- You stop wiping.
- You stop putting things back.
- You start contributing to the chaos.
That’s the hidden cost of inconsistency: it doesn’t just create disorder.
It lowers the standard of care —until disorder becomes the default.
Codebases rot the same way.
- It’s rarely one big refactor gone wrong or some infamous PR.
- It’s a hardcoded string here, a missing test there.
- A “temporary” workaround that never gets revisited.
- A helper class that quietly becomes a dumping ground.
CI is green. Static analysis doesn’t complain.
But somehow, everything feels heavier than it used to.
This post is about that slow drift—and how to stop it.
Not with heroic rewrites. Not with prettier configs or PSR-12 debates.
But with a deeper understanding of what consistency really is, why it matters more than perfection , and how to build codebases that clean themselves—file by file, day by day.
Because the same principle that keeps kitchens functional over time applies to software:
Mess invites mess.
But more powerfully: order invites more order.
When everything has a place, it tends to stay in place.
1. Mess Invites Mess, But Order Invites More Order
Leave a knife in the sink, and somehow it gives everyone else permission.
A spoon shows up. Then a pan.
And by the end of the day, no one wants to clean—because now it’s a mess.
But if the counter is clear, the sink is empty, and everything’s where it belongs?
People wipe up right after chopping.
They put the spices back without being asked.
The environment sets the standard.
Not rules. Not motivation. Just what’s already true.
Code works the same way.
You open a file where everything is named clearly, small functions are composed intentionally, and the layout flows like it was built on rails—what do you do?
You match the tone. You respect the structure. You add with care.
But if you open a file that’s messy—unstructured, inconsistent, unpredictable—you patch it with a workaround. Or worse, you walk away.
Not because you’re lazy, but because the code is already signaling that quality isn’t expected here.
Consistency Sets the Behavioral Baseline
Mess doesn’t just grow because things break.
Mess grows because people adapt downward.
Even a “minor” inconsistency can cause disproportionate damage:
A misnamed method signals that naming isn’t important.
A missing test tells new devs testing is optional.
One file ignoring the service structure invites others to do the same.
It’s not about enforcement.
It’s about momentum.
A consistent codebase isn’t perfect—it’s predictable.
And predictability reduces friction for every contributor.
Real-World Parallel: The Clean Kitchen Effect
Behavioral psychology has a name for this: environmental priming.
People unconsciously mirror the standards around them.
In one study, a clean hallway with lemon-scented cleaner in the air made people more likely to pick up litter.
In another, visible disorder led to higher rates of dishonesty and vandalism.
Why?
Because humans tune their behavior to what seems “normal.”
And codebases are no different.
In Practice
In well-maintained projects:
New contributors write better code without being told.
Code reviews focus on logic, not formatting or structure.
Team velocity increases—not because of speed, but because of reduced friction.
In messy ones:
People hesitate to touch files.
Reviews become emotional minefields.
Every fix feels like pushing through mud.
So if you want better code without preaching or micromanaging?
Don’t write a new rule.
Write one clean, consistent file. And make it the new normal.
That’s how kitchens stay clean.
That’s how codebases stay maintainable.
2. Clean ≠ Structured. Structure = Predictable.
From a distance, the kitchen looks fine.
Counters wiped. No visible clutter. The sink is empty.
But then you open a drawer and find three different can openers.
The fridge is overstuffed with expired ingredients.
The spice rack is alphabetical—except for the one jar you need.
It’s not dirty. But it’s disorganized. And suddenly, something as simple as boiling pasta feels… harder than it should.
Codebases can fool you the same way.
Visual Cleanliness Hides Structural Rot
Developers often confuse style consistency with structural integrity.
“We’re following PSR-12—we’re good.”
But the real friction doesn’t come from indentation.
It comes from behavioral inconsistency :
A function mutates state but reads like it doesn’t.
A service mixes validation and persistence in the same method.
Ten files named
Helper.php
doing wildly different things.
Structure Creates Trust
When structure is consistent:
You can guess functionality from a filename.
You know where to add logic without asking.
You focus on what needs to change—not how to fit it in.
When structure is inconsistent:
Every file becomes an investigation.
Every change feels like a guess.
Every review becomes a negotiation.
Cognitive Load Theory: Death by Paper Cuts
Humans can only juggle 4–7 items in working memory at a time.
Every inconsistency:
Forces a context switch.
Introduces a new mental rule.
Steals attention from the actual problem.
Even if you never say it out loud, your brain reacts:
“Wait… how does this one work again?”
That hesitation is the real tax on team velocity.
Not slow builds.
Not flaky tests.
Just devs wasting brainpower navigating inconsistency.
Back to the Kitchen
Imagine:
Every time you cook, you spend 3 minutes looking for a pan.
You burn dishes because spices are mislabeled.
You break a plate trying to cram it into the wrong cabinet.
Eventually, nobody wants to cook.
Not because they can’t.
But because the system stopped helping.
In Practice
Here’s what actually helps:
Stop obsessing over formatting. Start enforcing structure.
Codify naming rules, error-handling patterns, return type expectations.
Maintain one golden file per feature type—let code teach code.
Use tools like Rector and PHPStan not just for correctness, but for design drift.
Anyone can clean a file.
But only structure makes it stay clean the next day.
Structured systems aren’t pretty.
They’re repeatable.
3. Consistency as Workflow, Not Willpower
Nobody wants to scrub a greasy pan.
But wiping the counter after slicing onions? Easy.
Tossing a sponge in the dishwasher? Automatic.
Taking out the trash because the bin is right there? Obvious.
Clean kitchens stay clean not alone through motivation—
but through systems that make the right action frictionless.
Stop Relying on Memory and Good Intentions
Developers love to say:
“Always write tests.”
“Stick to the architecture.”
“No more fat controllers.”
And for a week, it works.
Until someone’s tired.
Or new.
Or didn’t know the rule existed.
Then entropy wins—because you bet the house on willpower.
Ritual Beats Resolution
The teams that stay consistent aren’t more disciplined.
They’ve just made quality the path of least resistance.
They don’t debate style in every PR.
They don’t forget to test.
They don’t wonder where a new file belongs.
Why?
Because the workflow remembers for them.
Make Quality Automatic
Good teams embed consistency into the process:
Pre-commit hooks
CI pipelines that validate behavior, not just syntax
Code generators and file stubs
“Golden” examples in-repo
Micro-rituals in code review
The Kitchen Analogy Again
Want people to compost?
Don’t hide the bin in a closet.
Put a small, open one next to the cutting board.
Same principle in code:
If you want consistency, design the workflow
so that the right choice is the easiest one.
In Practice
Ask your team:
What do we correct in every PR?
What decisions keep getting re-explained?
What slows us down the most often?
Then build automation or scaffolding to solve just that.
Start with friction hotspots.
You’re not building bureaucracy.
You’re removing ambiguity.
Every time the system answers a question,
that’s one less decision the developer has to make.
Consistency doesn’t come from preaching.
It comes from design.
Design your workflow to default to quality.
Then watch the team rise to meet it.
4. Design for the Future, Not the Fix
There’s a kitchen that looks spotless—today.
But the trash can is too far from the prep station.
The knives are in the same drawer as the ladles.
There’s no counter near the stove.
Cooking technically works.
But every step is awkward. Every movement inefficient.
Eventually, people stop using it—not because it’s messy, but because it’s exhausting.
Codebases Rot the Same Way
They don’t collapse from mess.
They degrade from accumulated friction :
Logic split between controller, service, and a random helper.
Naming that hides purpose (
ServiceHandler
,ThingManager
).Features wedged into whatever file felt “close enough.”
You can still add features.
You can still ship.
But every change feels like surgery—because the architecture doesn’t support the work.
Good Architecture Is Predictable
A good system isn’t one where code just works.
It’s one where new code fits.
If you can’t tell where the next feature goes,
you don’t have architecture—you have coincidence.
Architecture = Consistency at Scale
At the local level, consistency is about naming and formatting.
At the system level, it’s about boundaries and repeatability :
Controllers control. Services do business logic.
Every feature follows the same shape.
Domain logic lives with the domain—not scattered across folders.
Folder structure maps to business concerns, not technical artifacts.
What This Looks Like in Practice
Most Systems Drift by Default
Architecture rarely dies from bad decisions.
It dies from unopposed ones :
A shortcut nobody reverts.
A pattern nobody questions.
A new dev copying a bad file because “that’s how it was done.”
If nothing enforces the rules, there are no rules.
Architecture Is Operational Psychology
It should tell your team:
Where things go
What “right” looks like
How to move safely and fast
If it doesn’t, your devs will guess.
And every guess will pull your system further apart.
Design not for what’s urgent.
Design for what’s needed.
Make your architecture answer questions before they’re asked.
Make it obvious where new work belongs.
If you don’t, the next “fix” will be a wedge.
And ten wedges later, you’re back in kitchen hell.
5. Consistency Isn’t Control. It’s Clarity.
“Don’t tell me how to code.”
We’ve all heard it.
Some of us have said it.
Because too often, consistency feels like micromanagement —
Like senior devs enforcing their quirks instead of team standards.
But that’s the wrong frame.
Real consistency isn’t about control.
It’s about removing guesswork.
The Right Kind of Freedom
In a well-designed kitchen:
You don’t need to ask where the knife goes.
You don’t need a manual to find the trash.
You just move—freely, fluidly, confidently.
That’s not restriction. That’s clarity.
And clarity is what brings developers into a productive flow.
Predictability = Velocity
When a developer opens a new module and can instantly tell:
Where logic lives
How errors are handled
What a test should look like
They’re not slowed down.
They’re unlocked.
No waiting on context.
No decoding inconsistent patterns.
Just building, fast—and safely.
What Consistency Really Gives You
This isn’t about obedience.
It’s about shared expectations.
The structure does the explaining.
The docs just reinforce the why.
The Wrong Kind of Freedom Slows Teams Down
“Just do what you think is best” sounds supportive.
But it opens the door to chaos:
Someone rewrites a module in a new paradigm.
Another adds raw SQL into a system using Doctrine.
A test is written in a completely different pattern.
Now everyone is “free”—and everyone is misaligned.
Velocity drops.
Reviews turn into rework.
Nobody trusts anything.
Teams Scale on Predictability, Not Talent
The best teams aren’t made of superstars.
They’re made of people who can move independently and still produce code that fits together.
That only works when the system defines consistency as clarity , not constraint.
Clarity makes creativity possible.
Predictability enables flow.
Shared structure builds trust.
That’s what real consistency gives you.
Not control— coherence.
Conclusion – Make Order the Default
Kitchens don’t stay clean because someone yells.
They stay clean because the system makes care easy :
The trash is close.
The knives are where you expect.
The dishwasher has a rhythm.
No micromanagement.
No friction.
Just design that encourages discipline.
Codebases Work the Same Way
You don’t need perfect code.
You need a foundation that:
Makes the right thing obvious
Makes the wrong thing feel weird
Makes improvement the path of least resistance
Mess invites mess.
But more importantly: order invites order.
When that order exists:
Developers contribute with confidence
Refactors happen in flow
New features fit in like they belonged from day one
Not because your team is better.
But because your system is smarter.
What You Can Do Today
Start small. But start with purpose.
Touch a file? Leave it cleaner than you found it.
Write a new service? Copy the best one —your template of excellence—not the most recent hack.
Add a pre-commit hook that blocks architectural drift , not just formatting violations.
Pick one “golden” module. Let it define what “done right” looks like.
Then build forward from that standard— consistently.
Turn your golden module into a scaffold.
Generate code that already follows the rules.
Automate structure, not just syntax.
Example:
make create:datatable InvoiceTable
Now every new DataTable starts clean, typed, and consistent—before anyone touches a line.
That’s how you scale quality.
Not by working harder. But by making the right thing the easiest thing.