Matt Pocock: Software Engineering Fundamentals Matter More Than Ever in the Age of AI Coding

Good codebases and software fundamentals matter more than ever in the age of AI-assisted coding.
At AI Engineer Europe, TypeScript educator Matt Pocock used hands-on experiments and classic software engineering texts to push back against the "code is cheap" narrative. He argues AI performs brilliantly in well-structured codebases but poorly in messy ones — making good code more valuable than ever. He outlines three AI collaboration failure modes and their fixes: misaligned intent (use a "Grill Me" skill to build a shared Design Concept), communication breakdown (use DDD's Ubiquitous Language to create a shared glossary), and non-working code (use TDD to force the AI to slow down and validate incrementally). The thread running through everything: deep module design, designing interfaces while delegating implementation, and investing in system design every day. Developers should act as strategic architects — and the classic software wisdom they've accumulated is their edge.
At the AI Engineer Europe conference, prominent developer and TypeScript educator Matt Pocock delivered a thought-provoking talk with a concise, counterintuitive core argument: in the age of AI-assisted coding, software engineering fundamentals haven't become obsolete — they matter more than ever.
This directly challenges a popular narrative in developer circles — that "code is cheap." Matt argues this framing is simply wrong. If anything, bad code has never been more expensive than it is today.
The Trouble with the "Specs to Code" Movement
A movement called "Specs to Code" has been gaining traction in the developer community. The idea is simple: describe how your application should work in natural language, hand it off to an AI to generate the code, and if something breaks, don't touch the code — go back and revise the spec, then regenerate. In theory, developers never need to engage with the underlying code at all.
Matt admits he gave this approach a serious try — and found the results deeply frustrating. He discovered that while the first pass of generated code was acceptable, each subsequent iteration made things worse. The more he iterated, the more the code quality degraded, until the whole thing collapsed into chaos.

"I don't think this approach actually works," Matt said bluntly. The idea of letting AI maintain code while humans never look at it simply doesn't hold up in practice.
Turning to the Classics for Answers
To understand why, Matt went back to several foundational software engineering books.
In John Ousterhout's A Philosophy of Software Design, he found a definition of "bad code" — complexity. The book states: complexity is anything in the structure of a software system that makes it hard to understand and modify. In other words, a bad codebase is one that's hard to change. If you can't modify code without introducing bugs, it's bad code.
In The Pragmatic Programmer, he found the concept of software entropy: systems naturally tend toward disorder and decay. Every time you focus only on the immediate change without considering the overall system design, the codebase deteriorates a little more. This perfectly explained what he'd observed in his "Specs to Code" experiment.
The Core Argument: Good Codebases Make AI Shine
Matt's conclusion: good codebases matter more than ever before.
The reasoning is straightforward — AI performs exceptionally well in a well-structured codebase, unlocking enormous productivity gains. In a hard-to-modify codebase, those gains simply don't materialize. So if good codebases matter more, that means software fundamentals matter more. That's the central thesis of the entire talk.
Drawing on his work developing the Claude Code for Real Engineers course, Matt then walked through several common AI collaboration "failure modes" — and how classic software engineering wisdom can help avoid them.
Failure Mode 1: The AI Didn't Build What You Wanted
Many developers have run into this: you have a clear idea in your head, but the AI generates something completely different.
The Pragmatic Programmer points out that nobody really knows exactly what they want. There's a communication barrier between you and the AI. When you talk to an AI, the AI is essentially doing requirements gathering.
Matt also cited Frederick P. Brooks' The Design of Design and the concept of a Design Concept — when multiple people are designing something together, there's an intangible, shared notion of "what are we building" that floats between them. It isn't an artifact; it can't be written into a markdown file. It's the implicit theory behind the thing being built.

He realized the problem was that he and the AI didn't share the same Design Concept. So he developed an extremely simple skill called "Grill Me", with just two lines of instruction:
Interrogate me relentlessly on every aspect of this plan until we reach consensus. Walk through every branch of the design tree one by one, resolving dependencies between decisions as we go.
This unexpectedly went viral on GitHub, with the repository gaining around 13,000 stars. Those few lines prompt the AI to fire 40, 60, even 100 questions at you until it's confident you've reached consensus. It turns the AI into an adversary that constantly challenges your thinking. The resulting conversation can be directly converted into a PRD or a set of issues. Matt considers this superior to Claude Code's default "plan mode," which he finds too eager to generate artifacts — he'd rather establish a shared Design Concept first.
Failure Mode 2: The AI Is Too Verbose and Communication Breaks Down
The second failure mode is an AI that's excessively wordy — using too many words to describe what it's doing, as if you're both talking past each other.
This reminded Matt of collaborating with domain experts. If a microchip specialist asks you to build an application, but you know nothing about microchips, you have to establish a shared language. Otherwise the expert uses jargon you can't follow, and you translate it into code even you don't fully understand.
His solution came from Domain-Driven Design (DDD) and the concept of a Ubiquitous Language — conversations between developers, code expressions, and conversations with domain experts all derive from the same domain model. In practice, this is a markdown file containing a shared glossary between you and the AI.
Matt built a "Ubiquitous Language" skill: scan the codebase, extract terminology, and generate a markdown table of all terms. He keeps this file open at all times, referencing it repeatedly during planning and when grilling the AI. By reading through the AI's reasoning traces, he found this not only improved planning quality but made the AI's thinking more concise — and the final implementation more faithful to the original plan.
Failure Mode 3: The AI Built the Right Thing, But It Doesn't Work
The third scenario: the AI built exactly what you asked for, but it just doesn't run.

The obvious solution is feedback loops: static types (if you're not using TypeScript yet, that's wild), giving the LLM access to a browser (essential for frontend apps), and automated tests.
But Matt noticed that even with these feedback loops in place, LLMs don't use them well — they don't leverage feedback the way an experienced developer would. The AI tends to do too much at once, generating a mountain of code before thinking "oh, I should run a type check" or "I should run a test."
The Pragmatic Programmer has a great metaphor for this — "outrunning your headlights": the rate of feedback is your speed limit. This means you should test as you go, taking small, deliberate steps. And by default, AI is bad at exactly this.
That's why Test-Driven Development (TDD) becomes a critical skill. TDD forces the LLM to slow down: write the test first, make the test pass, then refactor the code to be more elegant and aligned with the design intent.
Good Codebase = Easily Testable Codebase
Matt also acknowledges that testing has always been hard, because writing tests involves a web of interdependent decisions: how large a unit should you test? What should you test? What edge cases matter?
His key insight from years of professional experience: a good codebase is one that's easy to test. This circles back to the central thesis — code structure matters.
Building on Ousterhout's ideas, he advocates for deep modules — modules that hide large amounts of functionality behind simple interfaces — rather than fragmented structures full of many small functions and shallow interfaces.

Matt points out that AI is very good at generating the "many small pieces" style shown above — but this ultimately leaves the AI unable to understand its own code, because it gets lost in a sea of shallow modules and can't grasp how they interact. Deep modules, by contrast, encapsulate complexity behind simple interfaces, making it possible to test at the interface level and much easier for AI to reason about.
Design the Interface, Delegate the Implementation
A principle Matt returns to repeatedly: design the interface, delegate the implementation.
For less critical modules in your application, you can explicitly define the interface and hand the internal implementation off to the AI — testing and validating only from the outside. Of course, you can't do this for sensitive logic involving money or other critical concerns, but for the majority of your application, this approach of "designing the module from the outside" dramatically reduces your cognitive load.
This also means that when working with code and planning changes, you must always maintain a clear mental "map" of the modules in your system. Matt quoted Kent Beck: "invest in the system design every day." The "Specs to Code" approach, by contrast, abandons that investment entirely and lets the system evolve on its own.
Closing Thought: AI Is the Tactical Sergeant, You're the Strategist
Matt closed with a sharp military analogy: if you think of the AI as a tactical sergeant executing code changes, then you must be the person standing behind it, thinking at the strategic level.
And strategic-level thinking is precisely what we've been building for the past twenty years or more through software engineering fundamentals — deep module design, ubiquitous language, TDD, system architecture.
"Code is not cheap. Code matters." That's the message Matt most wanted to leave people with. Developers who feel their skills are being made obsolete by the AI wave might want to reconsider: the timeless wisdom in those classic books is exactly what gives you the leverage to make an outsized contribution in this new era.
Matt Pocock's skills are open-sourced in the GitHub repository Matt Pocock Skills. More content is available at his website aihero.dev.
Related articles

Open-Source Python SDK: Measuring AI Agent Reliability with SRE Principles
Agent Reliability is an open-source Python SDK that applies SRE's SLO and error budget concepts to AI Agent evaluation, with PASS/FAIL/UNKNOWN states, CI assertions, and zero forced dependencies.

MiniMax RefMod: A Complete Guide to Training-Free Reusable Identity Workflows
MiniMax RefMod offers training-free reusable identity workflows for image, video, and audio generation. Includes Runpod template and tutorial for quick setup.

Invalid Source Material Notice
The source material provided lacks substantive information and is unrelated to AI/tech topics, making it impossible to produce a complete professional article.