“If you think good architecture is expensive, try bad architecture.”
(—Brian Foote and Joseph Yoder)
👋 Hello, this is Valentina with the free edition of the Optivem Journal. I help Engineering Leaders & Senior Software Developers apply TDD in Legacy Code.
Bad Architecture Is Expensive
The “shortcut” decisions another developer made six months ago are now your daily headache.
Meetings start to revolve around workarounds. Every new feature is debated: “Is it safe? Will it break something else?”
And the pressure builds quietly.
Bad architecture doesn’t scream. It doesn’t send warning emails. It grows in the background.
It spreads through the system like rot.
Every service is tightly coupled. Every module is dependent on another. Every boundary unclear.
“If you think good architecture is expensive, try bad architecture.”
— Brian Foote & Joseph Yoder
So You Decide to Fix It
You’ve had enough. You start redesigning. You decouple the modules. You clean up the boundaries. You refactor the mess left behind by someone else.
And then everything breaks.
Regression bugs everywhere. Features that worked yesterday are failing today. QA is overwhelmed. Stakeholders are asking what happened. Your manager wants answers.
And suddenly, you’re the problem. The person who tried to improve the system is now the one everyone blames for breaking it.
What Went Wrong?
It wasn’t the refactoring. It was what you didn’t have before you started.
Half your unit tests broke — not because the behavior changed, but because they were coupled to the old structure. The other half still passed, but it didn’t matter. Bugs were slipping through anyway, in the gaps between units that no test ever covered.
Your unit tests couldn’t tell you whether the system still worked. They were never designed to. Because unit tests only tell you if individual units of behavior work. They do NOT tell you if the system as a whole works.
Now QA has to catch everything. You push a change, they find a bug, you fix it, they test again—a loop that never ends. It’s slow, it’s expensive, it’s frustrating… and code still ships with bugs.
Your System’s Real Safety Net
This is exactly where acceptance tests change the game.
Acceptance tests don’t care about internal structure. They test what the system does from the outside — the behavior your users and stakeholders actually depend on.
Redesign your modules? Acceptance tests should still pass.
Split a monolith into microservices? Acceptance tests should still pass.
Switch from SQL to NoSQL? Acceptance tests should still pass.
In any System Redesign, Acceptance Tests should still pass, because we expect the system's black-box behavior NOT to change.
They’re the one safety net that survives architectural change.
The Right Sequence
Bad architecture and missing acceptance tests are an invisible tax. And the people paying for it are the ones writing, testing, and maintaining the code every day.
The fix isn’t to stop improving your architecture. It’s to change the order:
First, write acceptance tests around what the system does today. Lock in the behavior.
Then redesign the architecture, knowing that if something breaks, you’ll see it immediately — not three sprints later in production.
Acceptance tests first. Architecture second. That’s the sequence that actually works.
See It in Practice
Want to see how acceptance tests can save you time, frustration, and endless bug loops? I’m running a hands-on Acceptance Tests Workshop on May 27–28 (4 hours).
Limited spots. Register now with the early bird discount - €100 off with code EARLYBIRD100


Good tests & architecture makes life easier for everyone.