AI Engineer Europe 2026

"Software Fundamentals Matter More Than Ever" — Matt Pocock

Read the talk

Why Software Fundamentals Matter More in the Age of AI Coding

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 36 seconds
Why Software Fundamentals Matter More in the Age of AI Coding

Matt Pocock argues that AI-assisted development depends on shared design concepts, precise domain language, fast feedback loops, testable architecture, and sustained human ownership of system design.

From a talk by Matt Pocock

At a glance

Ideas worth remembering

  • Fast code generation does not eliminate the cost of complexity: repeatedly changing software without preserving its overall design can make the codebase harder for both humans and AI to modify. 1:27

  • Develop a shared design concept through sustained questioning before turning the discussion into a requirements document, implementation plan, or agent-ready issues. 4:41

  • Use a documented ubiquitous language so the developer, AI system, and codebase refer to domain concepts consistently throughout planning and implementation. 7:55

  • Combine static types, browser access where appropriate, automated tests, and TDD so the model receives feedback in small increments instead of validating a large implementation only afterward. 10:04

  • Prefer deep modules with simple, testable interfaces; delegate implementation selectively while maintaining closer oversight of critical functionality. 12:09

  • Preserve human strategic ownership by explicitly tracking modules, interfaces, and architectural changes as part of everyday planning and system design. 16:27

Generated code is not the same as a maintainable system

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 187 seconds
Generated code is not the same as a maintainable system

The specs-to-code approach promises that developers can describe an application, generate its implementation, and resolve future problems by revising the specification instead of examining the code. Matt Pocock found that repeated generation produced progressively worse implementations. His objection is not to using AI for development, but to treating the underlying codebase as something that can safely manage itself. 0:19

Drawing on John Ousterhout’s A Philosophy of Software Design and The Pragmatic Programmer, Pocock frames the problem in terms of complexity and software entropy. A poor codebase is difficult to understand or change without introducing bugs, while a good one remains adaptable. When each change is made without considering the overall system, the design degrades incrementally—even if individual requests appear to have been fulfilled. 2:31

That degradation becomes particularly costly with AI because the quality of the existing codebase determines how effectively AI can contribute to it. Pocock’s central claim is that quickly producing code does not make code cheap: difficult-to-change software prevents teams from realizing the benefits of AI-assisted development. The practical implication is that software fundamentals become more valuable as implementation becomes easier to generate. 3:35

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:19 · section reference included

Establish a shared design concept before committing to a plan

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 355 seconds
Establish a shared design concept before committing to a plan

When an AI system builds something different from what its user intended, Pocock interprets the failure as a familiar requirements-gathering problem. The developer and the model do not yet share the same understanding of the intended outcome. Borrowing from Frederick P. Brooks’s The Design of Design, he describes a design concept as the evolving, intangible understanding held between collaborators, rather than a document that can simply be written once and treated as complete. 4:41

His proposed response is a skill called Grill Me, which has the AI repeatedly interview the developer about the plan, explore branches of the design, and resolve dependencies among decisions. Pocock reports that this process can involve dozens of questions and sometimes as many as 100. The resulting discussion can then be converted into a product requirements document or, for smaller changes, directly into issues for an agent to implement. 5:44

Pocock contrasts this approach with the default plan mode in Claude Code, which he personally considers too eager to create a planning artifact and begin implementation. The distinction is not that plans or requirements documents are unnecessary; it is that a durable plan becomes more useful after the human and AI have developed a shared understanding of what the work is supposed to accomplish. 5:44

How it fits togetherShared understanding before implementation

Question every aspect of the plan.

Repeated questioning resolves design decisions before the conversation becomes an actionable artifact.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:41 · section reference included

Give the model the same language used by the codebase

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 501 seconds
Give the model the same language used by the codebase

Excessively verbose or misaligned AI responses can reflect a language gap rather than a purely stylistic problem. Pocock compares the situation to a developer working with a domain expert: if the two parties use different terminology, the developer may translate requirements into code that neither side fully understands. He turns to domain-driven design, or DDD, and its concept of a ubiquitous language to bring conversations, code, and domain concepts into alignment. 6:49

Pocock’s ubiquitous language skill scans a codebase for terminology and produces a Markdown document containing tables of shared terms. Both the developer and the AI can consult that vocabulary during planning and implementation. Based on his reading of the model’s thinking traces, he reports that shared terminology improves planning, makes the model’s reasoning less verbose, and helps implementations stay closer to the intended design; he also notes that he is still exploring DDD rather than presenting himself as having exhausted the subject. 7:55

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

6:49 · section reference included

Make feedback frequent, then design code that can actually be tested

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 770 seconds
Make feedback frequent, then design code that can actually be tested

Even when the AI understands the intended feature, the implementation may still fail. Pocock recommends feedback loops that include static types, browser access for front-end development, and automated tests. His concern is that AI systems often generate large amounts of code before checking whether the result type-checks, passes tests, or behaves correctly in the browser. In that situation, implementation moves faster than the available feedback can reliably guide it. 8:57

His proposed discipline is test-driven development, or TDD: write a test, make it pass, and then refactor while considering the design. This sequence constrains the model to smaller steps, but Pocock emphasizes that testing remains difficult because decisions about unit size, mocking, and which behaviors to verify are interconnected. Broad tests can become flaky, while narrower tests introduce their own dependency and mocking decisions. 10:04

The effectiveness of those feedback loops depends on the architecture underneath them. Pocock argues that deep modules provide substantial functionality behind simple interfaces, whereas shallow modules offer comparatively little functionality through more complicated or fragmented boundaries. A codebase filled with small, interconnected modules can be difficult for an AI system to navigate and understand; clear, deeper boundaries make it easier to locate relevant behavior and test it through a stable interface. 12:09

How it fits togetherSmall-step test-driven development

Specify the next behavior first.

A test guides implementation before refactoring improves the surrounding design.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:57 · section reference included

Own the interfaces, delegate selectively, and invest in design continuously

Selected presentation frame from "Software Fundamentals Matter More Than Ever" — Matt Pocock at 815 seconds
Own the interfaces, delegate selectively, and invest in design continuously

Pocock proposes improving an existing architecture by identifying related pieces of code and gathering them behind deep module boundaries. The resulting modules can be tested through their interfaces, creating an architecture that supports TDD instead of fighting it. He also draws a division of responsibility: humans should exercise substantial control over interface design, while AI can take on more of the implementation inside those boundaries. 13:05

This arrangement also addresses the cognitive fatigue that can accompany faster AI-assisted shipping. Pocock describes treating some deep modules as gray boxes: understand their purpose, design and verify the external interface, and avoid scrutinizing every implementation detail. That delegation has limits. He explicitly warns that more critical areas, such as financial functionality, may require greater attention than less critical application modules. 15:17

The strategy only works if the developer maintains an accurate mental map of the system. Pocock argues that modules and interfaces should become part of the team’s ubiquitous language and appear explicitly in product requirements documents, including descriptions of how those boundaries will change. Drawing on Kent Beck, he presents ongoing investment in system design as the essential counterweight to a specs-to-code process that ignores architecture: AI can act as a capable tactical programmer, but the human must retain strategic ownership of the system. 16:27

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

13:05 · section reference included

Read the complete timestamped transcript
  1. 0:00

    [upbeat music] Hello, everyone.

  2. 0:15

    Having a good conference so far? Yeah. Are you having a good conference so far? Yeah. [cheers] Good. Wonderful.

  3. 0:22

    I have a message for you that I hope will be, um, a comforting message for folks who believe that, uh, their skill set is no longer worth anything in this new age, which is I believe that software fundamentals matter now more than they actually ever have.

  4. 0:39

    And I'm a teacher, and I've been recently teaching a course called Claude Code for Real Engineers. Nice and provocative. And in the process of kind of working on this course, I had to come up with a curriculum about AI coding, which is a bit of a nightmare because things are changing all the time, right?

  5. 1:00

    AI is a whole new paradigm. We need to chuck out all of the old rules, surely, so that we can bring in the new stuff.

  6. 1:08

    And there's a kind of movement that has come up around this, which is the specs-to-code movement, and the specs-to-code movement says that, okay, you can write a specification about how an application is supposed to work, then you can use AI to turn it into code.

  7. 1:23

    If there's a problem with the application, you then go back to the spec. You don't really look at the code. You just change the spec, you run the compiler again, and you end up with more code.

  8. 1:34

    Raise your hand if you've heard of that.

  9. 1:37

    Keep your hand raised if you've tried it. Okay. I've tried it too. You can put your hands down. And what I noticed was I would run it, and I would try not to look at the code,

  10. 1:48

    but I would look at the code, and I realized I would get code out first of all, and then I would run it, and I would get worse code, and I did it again, I got even worse code, and I got it again.

  11. 1:58

    I kept running the compiler, kept running the compiler, and I would just end up with garbage. [scoffs]

  12. 2:03

    You know, raise your hand if that's happened to you. Yes. I don't think this works. The idea that we can just ignore the code and just have the code, let it manage itself, is just sort of vibe coding by another name.

  13. 2:16

    And I didn't believe that back then. I thought, "Okay, how do I fix the compiler? How do I make it so that it doesn't produce bad code each time or worse code?"

  14. 2:25

    And so I thought, "Okay, I need to explain to the LLM in English what a good code base looks like." Let me dig out one of my old favorite books, which is A Philosophy of Software Design by John Ousterhout.

  15. 2:37

    Go on Amazon, get it. Um, and he has a definition for what bad code looks like. He calls it complex code. Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system, right?

  16. 2:53

    So a, a bad code base is a code base that's hard to change. If you can't change a code base without causing bugs, then it's a bad code base.

  17. 3:01

    Good code bases are easy to change. So I thought, "Ooh, that was good. Let's try another book. Let's try The Pragmatic Programmer." Go on Amazon, get it.

  18. 3:10

    They have a whole chapter on something called software entropy, and this is exactly what I was seeing. Entropy is the idea that things tend towards, um, disaster and, uh, floating away from each other and collapse, and this is exactly how most software systems behave too, is that every time you make a change to a code base, if

  19. 3:28

    you're only thinking about that change, not thinking about the design of the whole system, your code base is gonna get worse and worse and worse, and that's what I was seeing.

  20. 3:37

    Everything inside the specs to code idea that you just run the compiler again and again was making worse code. Now, there's an idea that sort of drives the specs to code movement, which is that code is cheap.

  21. 3:50

    Raise your hand if you've heard that phrase before, that code is cheap. Yeah.

  22. 3:55

    Well, I don't think this is right. I think code is not cheap. In fact, bad code is the most expensive it's ever been because if you have a code base that's hard to change, you're not able to take all of the bounty that AI can offer 'cause AI in a good code base actually does really, really well.

  23. 4:15

    And this means good code bases matter more than ever, which means software fundamentals matter more than ever. That's the thesis of this talk.

  24. 4:22

    So let's actually get into practical stuff. I'm gonna talk about different failure modes that you may have experienced or you may not have experienced yet with AI and how you can avoid them by just going back to old books and looking at good software practices.

  25. 4:34

    Sound good? So the first one is that the AI didn't do what I wanted. You know? I, I thought I had a good idea in my head, and the AI just did something totally different, or it did some, uh, like specs that I...

  26. 4:47

    You know, it just made something I didn't want. Raise your hand if you've hit this mode.

  27. 4:51

    Cool. Okay. Well, this is what they say in The Pragmatic Programmer, is that no one knows exactly what they want. It's that you and the AI, there is a communication barrier there, right?

  28. 5:04

    And so when you're talking to the AI, that's kind of like the AI doing its requirements gathering. It's basically t- working out from you what it is that you need.

  29. 5:12

    And I realized that there was another book, Frederick P. Brooks, The Design of Design, and it talks about this idea called the design concept. It's that when you have more than one person designing something together, you have this idea sort of floating between you, this ephemeral idea of the thing that you're building, and that thing that you're

  30. 5:32

    building or the idea of it is called the design concept. It's not an asset. It's not something you can put in a markdown file. It is the invisible sort of theory of what you're building.

  31. 5:44

    And so I thought, "Okay, that's what's going on. Me and the AI don't share a design concept." So I came up with a skill. This skill is very, very simple.

  32. 5:53

    It's called Grill Me, and it looks like this. Interview me relentlessly about every ax- aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, which is another thing from Frederick P.

  33. 6:06

    Brooks, resolving dependencies between decisions one by one. This skill is like, uh, the repo containing this skill has, like, thirteen thousand stars or something. Like, it just went nuts, went viral.

  34. 6:17

    People love this thing. It-- these couple of lines means the AI asks you, like, forty questions, sixty questions. I've had it ask, uh, people a hundred questions before it's satisfied they've reached a shared understanding.

  35. 6:29

    And it means it turns the a-AI into a kind of adversary, where it's just continually pinging you ideas and trying to reach a shared understanding. And that means that the conversation that you then generate, you can take that and turn it into a product requirements document or something.

  36. 6:45

    Or if it's a small change, you can just, uh, do, uh, turn it directly into issues.

  37. 6:52

    And then your AFK agent will then pick it up. And don't at me on this, but I personally believe this is better than the default plan mode in the, the tool that I use, which is called Claude Code.

  38. 7:04

    Plan mode is extremely eager to create an asset. It really wants to, uh, just create a plan and start working. Whereas I think it's a lot nicer to reach a shared design concept first.

  39. 7:18

    So that's tip number one. Now, failure mode number two is that the AI is just way too verbose. It's like you're almost talking across purposes with the AI. Raise your hand if you, uh, feel this, if you ever experienced that failure mode.

  40. 7:32

    Yeah. It's kind of like the AI is, like, talking, just using too many words to try to communicate what it's doing. It's not like you're talking, uh, using the same language.

  41. 7:42

    And this to me felt very, very familiar, right? If you've ever been a developer for a long time and you've worked with, let's say, domain experts, someone building an application, um, let's say the domain expert wants you to build something on, uh, I don't know, microchips.

  42. 7:55

    You have no idea what microchips are. You need to establish some kind of shared language, right? Because otherwise they're gonna be using terms you don't understand. You're gonna be translating that into code that maybe you don't even understand, and certainly the domain expert won't.

  43. 8:07

    And so there's this kind of language gap between you and the domain expert. And so I went back to domain-driven design, DDD. This is something I'm still kind of on the edge of exploring, but everything I'm reading about DDD is just music to my ears.

  44. 8:24

    I freaking love it. And DDD has a concept of a ubiquitous language.

  45. 8:30

    With a ubiquitous language, conversations among developers and expressions of the code and conversations with domain experts are all derived from the same domain model. It's essentially a markdown file full of a list of terms that you and the AI have in common, and you really focus on those terms, and you really make sure that they're aligned with

  46. 8:48

    what it actually means, and you use them all the time in the code, when you're talking about the code, when you're talking to domain experts, or in our case, when you're talking with AI.

  47. 8:57

    So I made a skill. This skill is the ubiquitous language skill. Basically just scans your code base, looks for terminology, and then, um, creates a markdown file. Creates the ubiquitous language markdown file, a bunch of markdown tables with all of the terminology.

  48. 9:14

    And this, then I pass it to the AI, and I'm able to read it too, and I actually have it open all the time when I'm grilling with the AI and planning and that.

  49. 9:23

    And what I noticed by reading the thinking traces of the AI, it not only improves the planning, but it allows the AI to think in a less verbose way, and actually means that the implementation is more aligned with what you actually planned.

  50. 9:37

    So this has absolutely been a powerhouse. It's, I mean, unbelievably good. So that's tip number two: create a shared language with the AI. So okay. Let's imagine that you've aligned with the AI.

  51. 9:49

    You know what it is you're supposed to be building. The AI has built the right thing, but it doesn't work. Raise your hands if that's happened to you.

  52. 9:57

    Yep. Just doesn't work. Well, there's an obvious thing that we can do to make that better, which is we can use feedback loops. We can use, um, static types, you know, if you're not using TypeScript, uh, that's crazy.

  53. 10:10

    Uh, if you're not using, uh, if you're building a front-end app and you're not giving it the LLM access to the browser, so it can look around, absolutely needs that.

  54. 10:19

    And you obviously also need automated tests. And one sort of thing I notice here is that even with these feedback loops, the LLM doesn't use them very well. It doesn't kind of like get the most out of its feedback loops in the way that a veteran developer would.

  55. 10:36

    And so it does... What it tends to do is just does way too much at once. It will produce, like, huge amounts of code and then think, "Oh, I should probably type check that actually," or, "I should, uh, you know, maybe check a test on that or maybe do something like that."

  56. 10:50

    And this, in The Pragmatic Programmer, they describe as outrunning your headlights, as essentially driving too fast because the rate of feedback is your speed limit. The rate of feedback is your speed limit, which means that you should be testing as you go, taking small, deliberate steps.

  57. 11:08

    And the AI by default is really not very good at that. So skill number three is TDD. You should be using test-driven development because TDD forces the LLM to really take small steps.

  58. 11:23

    You create a test first, you make that test pass, and then you refactor the code to make it nicer and consider the design.

  59. 11:32

    The issue here is that testing is really hard. Testing has always been hard. And the reason for that

  60. 11:41

    is there are a ton of different decisions you need to make when you write a test. You need to figure out how big a unit do you want to test.

  61. 11:50

    You need to figure out what to mock. You need to figure out what behaviors do you even want to test in the first place. And all of these decisions are dependent.

  62. 11:57

    So if you are testing a really big unit, like an entire, uh, massive application, then it might be quite flaky. You might not wanna test that many behaviors. You know, if you only test this unit, you need to mock this unit.

  63. 12:09

    You know, it's all interlinked. And I've been thinking about this for years, for my entire development career.

  64. 12:15

    And what we notice is that good codebases are easy codebases to test, right? So here we're starting to get back to the idea of code being important, is that the better your codebase is, the better your feedback loops are because you're able to, um,

  65. 12:31

    give better feedback to the LLM, it produces better code.

  66. 12:35

    And so I thought, what does a good codebase, what does a testable codebase look like? Again, we go to John Ousterhout. He talks about having deep modules in your codebase.

  67. 12:46

    Not shallow modules, not lots of modules that expose like kind of, um, lots of functions. They should be relatively few large, deep modules with simple interfaces. Let's compare them quickly.

  68. 12:59

    Deep modules, lots of functionality hidden behind a simple interface, hiding the complexity. You can look inside the deep module if you want to, but you don't need to. You can just use the interface.

  69. 13:09

    Shallow modules, not much functionality, complex interface. And I'll just wait for you to take the photos.

  70. 13:18

    Shallow modules in a codebase kind of look like this, where you have a ton of different tiny little blobs that the AI has to walk through and navigate, and this is really hard for the AI to explore, actually.

  71. 13:31

    And so often what you'll see is if you have a codebase like this, which AI is really good at creating codebases like this, is that you'll have a situation where AI doesn't understand what your code is doing.

  72. 13:41

    It will attempt to explore the code, but because it's poorly laid out and filled with shallow modules, it doesn't maybe get to the right module in time, or doesn't understand all the dependencies, all that stuff.

  73. 13:51

    It doesn't understand your code. And so what does a codebase full of deep modules look like? Well, it looks like this,

  74. 14:00

    where it's the same code, but it's just structured inside boundaries where you have these interfaces on the top.

  75. 14:08

    And these interfaces, you should probably have a lot of control over them and design them really well. Otherwise, you know, AI might mess up the design. But the implementation, you can kind of leave that to the AI a bit.

  76. 14:21

    So how do you turn a codebase that looks like this into a codebase that looks like that? Well, I've got a skill for that. Improve codebase architecture. Turns out this is not-- It, it's quite complicated to do this, but it's a s- like a set of steps that you can reusably do again and again.

  77. 14:40

    You just sort of explore the codebase, look for opportunities where there's code that's kind of lo- um, related, and wrap all of that in a deep module.

  78. 14:50

    And this is a testable codebase because the boundaries around this code are so, so simple. You test at the interface, you verify using that interface, and you're good to go.

  79. 15:00

    And so this is a codebase that rewards TDD.

  80. 15:04

    But how about failure mode number six, which is your... Okay, let's say your feedback loops are working. Let's say that things are kicking into gear. You're able to ship more code than you ever have before, but your brain can't keep up,

  81. 15:16

    right? Uh, raise your hand if you felt more tired than you have ever before in your development career. Yeah, me too. It's knackering. And I think that this is a codebase that actually makes it harder for your brain because you, as well as the AI, need to keep all of that information in your head.

  82. 15:34

    Whereas this, not only is it simpler for you to read and understand, it also means you can kind of treat these modules or these deep modules as gray boxes.

  83. 15:47

    You can kind of say, "Okay, I'm gonna just design the interface, but I'm not gonna worry too much or not review the implementation too much." You can do this obviously with, uh, things that are less critical in your application.

  84. 16:00

    Can't do this with, uh, you know, various things like, uh, uh, finance or whatever. But in many, many modules in your app, you don't need to think about the implementation too much as long as you have a testable boundary outside the module, and as long as you understand its purpose and can design it from the outside.

  85. 16:15

    I have found this has really saved my brain because I can just go, "Okay, the AI, I'll let you handle what's inside the big blob. I'm just gonna test from the outside and verify it."

  86. 16:26

    So that's tip number five: Design the interface, delegate the implementation.

  87. 16:32

    But this means that whenever we're touching the code, whenever we're planning stuff, we need to think about and be aware of the modules in our application. We need to know that map really well.

  88. 16:42

    It needs to be part of our ubiquitous language. We need to build it into our planning skills as well. So my write-a-PRD, inside the PRD, I'm specific about the module changes and the interfaces inside those modules, how they're being modified.

  89. 16:55

    I'm thinking about them all the time. And this comes from Kent Beck: Invest in the design of the system every day. And this is the core of it, right?

  90. 17:04

    Because specs-to-code, we are not investing in the design of the system. We are divesting from it. We're getting rid of that. Whereas this, I think, is absolutely key.

  91. 17:16

    And so code is not cheap. That's the message I want you to take away. Code is important. And if we think about AI as a really great on-the-ground programmer, a kind of tactical programmer, a sergeant on the ground making the code changes, you need someone above that.

  92. 17:35

    You need someone thinking on the strategic level, and that's you. And that requires software fundamental skills that we've been using for twenty years, for m- longer.

  93. 17:46

    Now, if you are interested in any of the skills I put up here, it's in the GitHub repo [REDACTED:username]. And if you're interested in the training that I do or, uh, any free stuff, I'm on YouTube, I'm on Twitter, but I'm also at aihero.dev, where I have a newsletter that you can check out.

  94. 18:01

    Thank you so much. I hope that this gives you confidence in this new AI age- [audience clapping] that you can actually make a good impact. Thank you. [outro music]