The Most Expensive Code You'll Ever Write Is the Code You Don't Design
AI made writing code trivial — which is why a tangled, undesigned codebase is now the most expensive thing you can own. Matt Pocock's case for why design, not prompting, is still the job.
There's a comfortable story going around right now: AI writes the code, so code is cheap, so we should stop sweating the details and just ship. Specs in, software out. Engineers become product managers. Easy.
It's wrong. And the developer who's convinced me it's wrong is Matt Pocock — the guy behind Total TypeScript and the Claude Code for Real Engineers course. He gave a talk recently called "It Ain't Broke: Why Software Fundamentals Matter More Than Ever," and the argument is one we should internalise as a team.
His line is the one I want us to remember:
Bad code is the most expensive it's ever been.
Not because writing it is hard — AI made that part trivial. Because a tangled, undesigned codebase is now the thing that stops you from capturing everything AI can do for you. The code you skipped designing is the code that ends up costing the most.
The two ways teams get this wrong
Pocock sees engineers fall into one of two traps with AI tools:
Delegate everything. You get excited, you trust the model, you ship and ship and ship. Two weeks later you're sitting in spaghetti so twisted nobody — human or AI — can untangle it.
Delegate nothing. You're nervous about the tool, so you keep doing everything by hand and capture none of the upside.
The teams that win sit in the middle. They use AI heavily, but they stay the architect.
Why "specs to code" falls apart
Pocock tried the pure specs-to-code workflow himself. Iteration one was passable. Iteration two was worse. Iteration three was garbage. The model wasn't getting dumber — the codebase was getting harder for the model to reason about, and his specs were too thin to carry the design.
Three failure modes show up over and over:
- The AI is too verbose — it produces walls of code and explanation when you wanted a scalpel.
- The AI builds things that don't work because the spec was ambiguous and there was no shared vocabulary to anchor it.
- The AI does way too much — gold-plating, scope creep, three abstractions where one would do.
None of that is a prompting problem. It's a design problem.
The fixes are all 20+ years old
This is the part of the talk I love. His prescription is just classic software engineering, applied with intention:
- Build a ubiquitous language first. Borrowed from Domain-Driven Design. Before you let the agent write a line, get aligned on what the nouns and verbs of the system actually mean. Pocock uses a "grill me" prompt — he asks the model to interrogate him about the domain until they share a vocabulary. Cheap to do, transforms what comes out the other end.
- Use TDD as your workflow with the agent. Write the test, make it pass, refactor. It sounds old-school but it's the single best way to keep an AI agent inside what Pocock calls its "headlight range" — small, deliberate steps where the feedback loop is tight and mistakes surface immediately. The rate of feedback is your speed limit.
- Build deep modules, not shallow ones. This is from Ousterhout's A Philosophy of Software Design. A deep module hides a lot of functionality behind a simple interface. A shallow module exposes its complexity through a sprawl of tiny, interdependent files. Here's the kicker: AI agents are particularly bad in shallow-module codebases. They can't hold the sprawl in context, they miss dependencies, and they make confidently wrong edits. Deep modules aren't just good for humans anymore — they're now a precondition for AI to be useful.
- Remember that good codebases are easy to test. And testable codebases give AI the fast feedback it needs to actually help. So architecture quality and AI productivity aren't separate concerns. They're the same concern.
What this means for us
A few things I'd like us to take from this:
We should keep treating design, naming, and module boundaries as senior work — not chores to skip because "the AI will figure it out." It won't, and the cost of pretending it will compounds fast.
When we use Claude Code or similar tools, the right mental model is strategic architect + tactical implementer. We own the shape of the system, the language of the domain, and the test that defines "done." The agent fills in the middle.
And if a part of our codebase has gone shallow — lots of small files, leaky interfaces, tests that are painful to write — that's now a higher-priority refactor than it used to be. It's actively slowing down our AI tooling, not just our humans.
TL;DR
The way we type code has changed. The job hasn't. Design is still the work.
Reference: Matt Pocock — "It Ain't Broke: Why Software Fundamentals Matter More Than Ever" (talk)