daily nerdingThe Pocock books
The Pocock books
Matt Pocock teaches developers to code with AI agents. His advice keeps pointing back to four classic software books. Here they are, idea by idea, in plain English, with what each one means now that an agent writes the code.
Jump to the forty ideas, where to start, or try it with your agent.
Eight signals
The whole page in eight boxes. Each one links to where it's explained.
- 01
Fast code isn't cheap code
Pocock's point: agents write code fast, but a codebase that's hard to change limits how much they can help. The fix is old-fashioned design.
Show me - 02
Four books, one idea
Keep software easy to change. Every idea on this page comes back to that.
Show me - 03
The Pragmatic Programmer: habits
How a good developer works day to day. Own it, fix small mess early, build one thin slice first.
Show me - 04
A Philosophy of Software Design: shape
Small fronts with lots behind them. Hide decisions. Fewer special cases. The shortest of the four.
Show me - 05
Legacy Code: safety
Code without tests is legacy code, even if an agent wrote it this morning. Tests first, then change.
Show me - 06
Domain-Driven Design: words
One shared set of words for the business, in talk and in code. Read the first three chapters.
Show me - 07
Book words are agent words
Tracer bullet, deep module, seam. Short terms the models already know. One precise word replaces a paragraph of instructions.
Show me - 08
You design, the agent types
What's core, where the edges go, when it's good enough. Those calls stay with you.
Show me
Words on this page
Eighteen terms, in plain words. Skip this if you already write code.
- Agent
- An AI that reads and writes code for you, like Claude Code or Codex.
- Codebase
- All the code for one app or project.
- Module
- Any part of the code with a front and a back: a function, a file, a class.
- Interface
- The front of a module. What you call, what you pass in, what you get back.
- Function
- A named piece of code that does one job and can be reused.
- Class
- A template in code that bundles data and actions together, like an Order.
- Dependency
- When one part needs another part to work.
- Refactor
- Change the shape of code without changing what it does.
- Test
- A small program that checks your code does what it should.
- Test-first (TDD)
- Write the test before the code, then write code until it passes.
- Compiler / type checker
- A tool that reads your code and flags mistakes before it runs. TypeScript has one.
- TypeScript
- JavaScript with types added. The code examples on this page use it.
- Domain
- The business area the software is for: bookings, banking, bakeries.
- Domain expert
- Someone who knows the business well. Often not technical at all.
- Model
- A simplified picture of how the business works, used to build the software.
- Legacy code
- On this page, Feathers' meaning: code without tests.
- Glossary file
- A file listing your project's words and what they mean, read by people and agents. Often CONTEXT.md.
- Rules file
- Instructions an agent reads at the start of every session: CLAUDE.md or AGENTS.md.
Why these four, and why now
On Oct 7, 2026, Pocock posted a short joke about his own path with AI coding. In the replies, Peter Jia listed the four books Pocock recommends in his videos and podcasts, with one tip: read only the first three chapters of Domain-Driven Design.
His post, in eight steps · paraphrased
- 1AI can do my job better than me.
- 2Software engineering is dead.
- 3So vibe code everything.
- 4The results are bad, whichever model.
- 5What if I constrain the agent?
- 6Better. How do I go deeper?
- 7Orders twelve software engineering books.
- 8Software engineering is alive.
The point under the joke: agents made writing code cheap, but not good code. Holding them to a good design took the ideas in these books. His post
Where Pocock uses these books
AI Engineer Europe 2026 talk, “Software Fundamentals Matter More Than Ever” (about 18 min)
Watch the talk- PhilosophyOusterhout's definition of complexity, and deep modules as code an agent can use without reading it all.
- PragmaticSoftware entropy, and not outrunning your headlights: feedback speed sets how fast you can safely go.
- DDDUbiquitous language: a shared glossary that makes the agent's plans shorter and closer to what you meant.
The Pragmatic Engineer podcast with Gergely Orosz, Sep 17, 2026
Watch the episode- PragmaticTracer bullets as a “leading word”: say it to an agent and the code gets better. He now reads classic books looking for more words like it.
- PhilosophyTactical vs strategic programming: agents take the tactical work, people keep the strategic part.
His skills repo, mattpocock/skills
See the repo- DDDgrill-with-docs interviews you and writes the domain words into a glossary.
- Philosophycodebase-design aims for deep modules with small interfaces.
- Legacy Codeimplement drives tests at the seams you name. Work is sliced into tracer-bullet tickets.
From the talk page and the episode notes, not a transcript. The episode's book segment starts at 1:34:01. The list of four is Peter Jia's. Pocock's own post says he ordered twelve books and doesn't name them.
The four at a glance
The forty ideas
Pick a book, then click any idea. Each one opens the same way: the idea in plain words, an everyday example with no code, a code example (or what to say to your agent), what it means with AI agents, what to watch out for, and where it is in the book.
Pick a book
Habits · 1999 · 2nd edition 2019 · about 350 pages
Publisher pageThe Pragmatic ProgrammerYour Journey to Mastery, 20th Anniversary Edition
David Thomas and Andrew Hunt
How a good developer thinks and works, day to day. 53 short topics, each one a habit.
What to read
All of it, in any order. Every topic stands on its own.
Who it's for
Anyone who builds software or directs people or agents who do. Coder or not.
10 ideas · click one to open it
01 · Own your work
No excuses. Bring options, not complaints.
The idea
When something goes wrong, say so early and own it. Don't blame the tools, the deadline or the cat. Come with options instead: here's what broke, and here's what we can do about it.
Plain example · no code
A contractor finds rot behind a wall. A bad one says nothing, or blames the last crew. A good one shows you the rot and gives you three ways to fix it, with the cost of each.
Say it to your agent
Before you finish, list anything you skipped, guessed or couldn't test. For each one, give me two options to fix it.
With AI agents
Agents tend to report success. Ask them to report what they didn't do. And you own what you ship, even when an agent typed it.
Watch out
Owning it isn't taking all the blame. It's being first to say what happened and what comes next.
In the book
Topic 2, The Cat Ate My Source Code (Ch. 1)
Read it if you manage people or agents and want fewer surprises.
02 · Fix broken windows
Small mess left alone invites more mess.
The idea
One broken window left unrepaired tells everyone that nobody cares, and the building goes downhill fast. Code works the same way. One ugly hack makes the next one feel fine. Fix small things when you see them, or at least board them up with a note.
Plain example · no code
One dirty plate in the office sink soon becomes ten. Wash the first plate and the sink tends to stay clean.
In code
// Board it up: say what's wrong and what to do. // TODO: this repeats the price rounding in cart.ts. // Merge both into roundPrice() before adding discounts. const total = Math.round(sum * 100) / 100;
With AI agents
Agents copy what they see. If your codebase is full of hacks, the agent treats them as the house style and writes more. Pocock uses this idea, software entropy, in his AI Engineer talk: generating code faster also speeds up the decay.
Watch out
Don't stop every task to polish. Fix it, or write it down where it will be found. A note beats silence.
In the book
Topic 3, Software Entropy (Ch. 1)
Read it if your project feels harder to work on every week.
03 · Don't repeat yourself (DRY)
Every fact lives in one place.
The idea
Each piece of knowledge, like a tax rate, a business rule or a list of options, should be written down once. If it lives in two places, one day someone updates one and forgets the other. DRY is about knowledge, not about two bits of code that happen to look alike.
Plain example · no code
Your opening hours are on your website, your Google listing and your email signature. You change the website and forget the rest. Customers show up to a locked door.
In code
// One fact, two places. They will drift apart. const tax = price * 0.08; // checkout.ts const vat = amount * 0.08; // invoice.ts // One place. export const TAX_RATE = 0.08; // config.ts
With AI agents
Agents often write a new helper when one already exists, because they didn't find it. Tell them where the single source lives, and ask them to search before adding a new one.
Watch out
Two pieces of code that look the same but mean different things aren't duplicates. Merging them glues together things that will change for different reasons.
In the book
Topic 9, DRY: The Evils of Duplication (Ch. 2)
Read it if the same bug keeps coming back in different places.
Same idea in the other books
04 · Orthogonality
Change one part without breaking another.
The idea
Two things are orthogonal when changing one doesn't affect the other. Build parts that each do one job and don't secretly depend on each other. Then you can change, test or replace one part on its own.
Plain example · no code
On a sound mixing desk, each slider controls one thing. If turning up the drums also turned down the vocals, nobody could mix a song.
In code
// Tangled: saving a user also sends an email. function saveUser(u: User) { db.save(u); email.welcome(u); } // Separate: each part does one job. function saveUser(u: User) { db.save(u); } function onSignup(u: User) { saveUser(u); email.welcome(u); }With AI agents
Independent parts let you hand one part to an agent without it needing to understand everything else. Fewer surprises when it changes something.
Watch out
Not everything can be independent. The goal is no hidden links, not zero links.
In the book
Topic 10, Orthogonality (Ch. 2)
Read it if fixing one thing keeps breaking another.
Same idea in the other books
05 · Easier to change (ETC)
The one test for any design choice.
The idea
The 2nd edition boils good design down to one question: does this make the code easier to change later? Good names, small files, tests: they're all good because they pass that test. When you're stuck between two options, pick the one that's easier to undo or change.
Plain example · no code
Furnishing a rented flat, you pick furniture you can move. Not because you know you'll move, but because you might.
In code
// Hard to change: the rule is buried in the screen code. if (user.plan === "pro" && items.length > 10) showDiscount(); // Easier to change: the rule has a name and one home. if (qualifiesForBulkDiscount(user, items)) showDiscount();
With AI agents
Put ETC in your rules file. It gives the agent a simple tiebreaker when it has two ways to do something.
Watch out
ETC doesn't mean building for every possible future. Code built for futures that never come is harder to change, not easier.
In the book
Topic 8, The Essence of Good Design (Ch. 2, 2nd edition only)
Read it if you want one question to ask in every review.
Same idea in the other books
06 · Reversibility
No decision is final. Don't lock yourself in.
The idea
The database, the vendor, the cloud you picked: any of them might change. Keep the big choices behind a thin layer you own, so swapping one out is a small job, not a rewrite.
Plain example · no code
Using an email address on your own domain instead of a free webmail one. If you switch providers, your address stays the same.
In code
// Locked in: vendor calls spread everywhere. await stripe.charges.create({ amount, currency: "usd" }); // Reversible: one thin wrapper you own. export function charge(amount: number) { return stripe.charges.create({ amount, currency: "usd" }); }With AI agents
AI models and tools change every month. Keep the model name, the provider and your prompts in one place, so switching is a one-line change.
Watch out
Don't wrap everything just in case. Wrap the things that are expensive to change and likely to move.
In the book
Topic 11, Reversibility (Ch. 2)
Read it if you're about to pick a vendor, a platform or an AI provider.
Same idea in the other books
07 · Tracer bullets
Build one thin slice that works end to end, then grow it.
The idea
Don't build every part fully before connecting anything. Build a skinny version that goes all the way through, from screen to logic to database and back. It's real code you keep, and you add to it. A prototype is different: it answers one question and gets thrown away.
Plain example · no code
Before opening a restaurant, you serve one dish to a few friends: order, kitchen, table, bill. Then you write the full menu.
In code
// Day 1 tracer: the whole path, nearly empty. // button -> API -> database -> back to the screen app.post("/orders", async (req, res) => { const order = await db.orders.insert({ item: req.body.item }); res.json(order); // no tax, no stock check yet });With AI agents
On the Pragmatic Engineer podcast, Pocock says telling an agent to build with tracer bullets got him better code. Two words the model already knows stand in for a whole plan. His skills slice work into tracer-bullet tickets.
Watch out
A tracer bullet is real code you keep. If you plan to throw it away, call it a prototype, so nobody ships it by mistake.
In the book
Topic 12, Tracer Bullets, and Topic 13, Prototypes and Post-it Notes (Ch. 2)
Read it if big projects stall before anything works.
Same idea in the other books
08 · Don't outrun your headlights
Take steps no bigger than your checks can see.
The idea
Driving at night, you only see as far as your headlights. Go faster than that and you can't stop in time. In software, your headlights are feedback: tests, a preview, a person trying it. Take a small step, check it, then take the next one.
Plain example · no code
Painting a room, you try a small patch of the color and look at it in daylight before doing all four walls.
In code
# A small step, then a check. Every time. # 1. change one thing # 2. run the checks npm run typecheck && npm test # 3. green? commit. red? undo, take a smaller step.
With AI agents
An agent can write code much faster than you can check it. Pocock uses this idea in his AI Engineer talk: how fast you get feedback, not how fast the agent types, sets your safe speed.
Watch out
Small steps aren't slow if the checks are fast. The fix for slow progress is usually faster checks, not bigger steps.
In the book
Topic 27, Don't Outrun Your Headlights (Ch. 4)
Read it if your agent makes huge changes you can't review.
09 · Don't program by coincidence
Know why it works, not just that it works.
The idea
Code that works by luck breaks by luck. If you can't explain why something works, you won't know when it will stop. Write down what each part expects and promises, and stop loudly when those are broken instead of carrying on with bad data.
Plain example · no code
A car that only starts if you jiggle the key a certain way. It works, until someone else borrows it.
In code
function setPrice(cents: number) { // Say what you expect. Stop loudly if it's wrong. if (!Number.isInteger(cents) || cents < 0) { throw new Error("bad price: " + cents); } // ... }With AI agents
Agents sometimes fix a failing test by tweaking things until it passes. Ask the agent to explain why the fix works before you accept it. If it can't, neither of you knows.
Watch out
Stopping loudly is for things that should never happen. Normal problems, like a wrong password, need a friendly message, not a crash.
In the book
Topic 38, Programming by Coincidence (Ch. 7); Topics 23–25 on contracts and crashing early (Ch. 4)
Read it if bugs appear and vanish and nobody knows why.
Same idea in the other books
10 · Good-enough software
Know when to stop. Let the users help decide.
The idea
Perfect never ships. Agree with the people who'll use it how good it needs to be, then stop. Polishing forever is a way of never finding out whether you built the right thing.
Plain example · no code
A rough draft of a speech you read to a friend beats a perfect speech you never finish.
Say it to your agent
Before building, ask me: what's the smallest version I'd be happy to use this week? Build that first. Then list what you left out.
With AI agents
Agents will keep adding features and edge cases if you let them. Set the finish line up front, in writing.
Watch out
Good enough isn't sloppy. Safety, money and people's data still have to be right.
In the book
Topic 5, Good-Enough Software (Ch. 1)
Read it if you keep polishing instead of shipping.
Shape · 2018 · 2nd edition 2021 · about 190 pages
Author's pageA Philosophy of Software Design
John Ousterhout
How to shape code so it stays simple: deep modules, hidden decisions, fewer special cases.
What to read
All of it. It's the shortest of the four.
Who it's for
Anyone who writes code, or reviews the code an agent writes.
10 ideas · click one to open it
01 · Complexity is the enemy
Anything that makes code hard to understand or change.
The idea
Ousterhout defines complexity as anything about how software is built that makes it hard to understand or change. You notice it three ways. A small change needs edits in many places. You have to hold too much in your head. Or you can't even tell what you need to know. That last one is the worst.
Plain example · no code
Moving house means updating the bank, the doctor, the car registration and five apps. Each one is easy. Together they're the problem, and you always forget one.
In code
// One color change = edits in many files. button.style.color = "#b3261a"; // button.ts link.style.color = "#b3261a"; // link.ts // One edit, one place. export const BRAND_RED = "#b3261a"; // theme.ts
With AI agents
Pocock builds his AI Engineer talk on this definition. Agents feel complexity just like people do: more places to edit, more to read first, more ways to miss something.
Watch out
Complexity creeps in a little at a time. No single change looks like the problem, so look at the whole codebase, not just today's change.
In the book
Ch. 2, The Nature of Complexity
Read it if you want words for why a codebase feels heavy.
Same idea in the other books
02 · Two causes: dependencies and obscurity
Hidden links and unclear meaning make code hard.
The idea
Complexity comes from two places. Dependencies: one part can't be understood or changed on its own. Obscurity: something important isn't obvious, like a vague name or a rule nobody wrote down. You can't remove every dependency, but you can make them few and easy to see.
Plain example · no code
A light switch that also turns off the fridge (a dependency), with no label saying so (obscurity).
In code
// Obscure: what is 3? Who else knows? if (user.status === 3) block(user); // Clear: the meaning has a name. const SUSPENDED = 3; if (user.status === SUSPENDED) block(user);
With AI agents
An agent can't ask the person who wrote the code. Anything a new person would find unclear, the agent can't see at all. Names and short comments are cheap fixes.
Watch out
The cure for dependencies isn't hiding them. A dependency you can see is far better than one you can't.
In the book
Ch. 2, The Nature of Complexity
Read it if a change broke something far away and nobody knows why.
03 · Strategic, not tactical
Spend a little time on design every time.
The idea
Tactical programming means getting this feature working as fast as possible. Each shortcut seems fine, but they pile up. Strategic programming means the goal is a good design that also works. Ousterhout suggests spending around 10 to 20 percent of your time on design.
Plain example · no code
A shop that only ever restocks the shelves and never tidies the storeroom. Fine for a month. In a year, nobody can find anything.
Say it to your agent
Once the feature works, do one more pass: what would make the next change here easier? If it's small, do it. If not, add it to the list.
With AI agents
Pocock's view on the Pragmatic Engineer podcast: agents handle the tactical work, which frees people for the strategic part. The book warns about the tactical tornado, the fast coder who leaves a mess behind. An agent with no guidance is exactly that.
Watch out
Strategic doesn't mean months of planning up front. It's a small, steady investment, every time.
In the book
Ch. 3, Working Code Isn't Enough
Read it if you move fast at first, then everything slows down.
Same idea in the other books
04 · Deep modules
Hide lots of work behind a tiny interface.
The idea
A module is any part of the code with a front (how you use it) and a back (how it works). It's deep when the front is small and simple but a lot happens behind it. A shallow module makes you learn a front almost as complicated as the work it saves you.
Plain example · no code
A dishwasher: load it, press one button. A shallow dishwasher would ask you to set the water temperature, spray pressure and drying time every single load.
In code
// Shallow: the caller does the work, in the right order. const f = open(path); writeBytes(f, data); flush(f); close(f); // Deep: one call. Buffering, retries and errors live inside. save(path, data);
With AI agents
An agent can use a deep module from its front alone. Shallow modules make it read five files to do one thing, which uses up its memory and causes mistakes. Deep modules are at the center of Pocock's AI Engineer talk and his codebase-design skill.
Watch out
Lots of small classes isn't automatically clean code. Ousterhout pushes back on that. Deep doesn't mean giant. It means a lot of work for a small interface.
In the book
Ch. 4, Modules Should Be Deep
Read it if your codebase is 100 tiny files that each do almost nothing.
Same idea in the other books
05 · Information hiding
Each part keeps its own secrets.
The idea
Each module should hide a decision, like a file format or how data is stored, so nobody else needs to know it. When two modules know the same secret, that's leakage: change it, and you have to change both. A common trap is splitting code by the order things happen instead of by what each part knows.
Plain example · no code
A restaurant kitchen. You order from the menu. You don't need to know the recipe, the supplier or which chef is on shift.
In code
// Leaky: every caller knows how dates are stored. const d = new Date(row.created_at + "Z"); // Hidden: one place knows the format. const d = readCreatedAt(row);
With AI agents
When secrets are hidden, an agent can change how something works without touching the rest of the codebase. Smaller changes mean smaller reviews.
Watch out
Hiding isn't making things private for its own sake. Hide the decisions that are likely to change.
In the book
Ch. 5, Information Hiding (and Leakage)
Read it if changing one file format means editing ten files.
Same idea in the other books
06 · Somewhat general-purpose
Solve today's need with a simpler, broader tool.
The idea
Don't write a function that only fits this one screen. Don't build for every future either. Aim in between: solve today's problem with an interface general enough to be simpler, and to cover the next need too. Ask: what's the simplest interface that covers everything I need right now?
Plain example · no code
Buying one good kitchen knife instead of a tomato slicer, a bagel cutter and a cheese wire.
In code
// Special-purpose: one function per key. deleteSelectionOnBackspace(); deleteSelectionOnDeleteKey(); // Somewhat general: one simple tool for both. deleteRange(start, end);
With AI agents
Agents tend to write very special-purpose code, a new function for every request. Ask them whether one simpler, more general function would cover both cases.
Watch out
Too general is as bad as too specific. If you can't name a second real use, don't build for it.
In the book
Ch. 6, General-Purpose Modules are Deeper
Read it if you have five functions that are nearly the same.
07 · Different layer, different abstraction
Each layer should add something, not just pass things along.
The idea
Software is built in layers: screens on top of rules on top of storage. Each layer should give you a different, simpler way to think. A warning sign is a function that just hands its inputs to another function of the same shape. It adds a layer without adding anything.
Plain example · no code
A manager who only forwards your emails to their boss, unchanged. You'd be better off emailing the boss directly.
In code
// Pass-through: adds a layer, adds nothing. function getUser(id: string) { return userStore.getUser(id); }With AI agents
Agents love adding layers: a service that calls a repository that calls a client. Ask: what does this layer do that the one below doesn't? If the answer is nothing, remove it.
Watch out
Some thin layers earn their place, like one spot to swap a vendor (see Reversibility). The question is whether it adds anything.
In the book
Ch. 7, Different Layer, Different Abstraction
Read it if following one action means clicking through six files.
08 · Pull complexity down
The builder takes the pain, so the users don't.
The idea
If some complexity can't be avoided, it's better for a module's author to handle it once than for every user of the module to handle it every time. The same goes for errors: often you can define the problem away. Deleting something that's already gone can just succeed instead of throwing an error.
Plain example · no code
A good hotel deals with your bags, your taxi and your late check-out. You don't have to arrange any of it.
In code
// Pushes pain up: every caller must handle "not found". function remove(id: string) { if (!exists(id)) throw new Error("not found"); // ... } // Defines the error away: the goal is "it's gone". function remove(id: string) { if (!exists(id)) return; // already gone, done // ... }With AI agents
Every error a module throws is one more thing an agent must handle correctly everywhere the module is used. Fewer special cases, fewer agent mistakes.
Watch out
Don't hide errors that matter, like a failed payment. Define away the ones where the caller wouldn't do anything different anyway.
In the book
Ch. 8, Pull Complexity Downwards; Ch. 10, Define Errors Out of Existence
Read it if your code is full of error handling that all does the same thing.
Same idea in the other books
09 · Design it twice
Compare two different designs before you pick one.
The idea
Your first idea is rarely your best. Before building, sketch at least two very different approaches and compare them. Which is simpler to use? Which hides more? Which will be easier to change? It takes minutes, and it often turns up a better third option.
Plain example · no code
Before moving the furniture, you sketch two layouts on paper. The second sketch often shows you something the first one missed.
Say it to your agent
Before writing any code, give me two very different designs for this. For each: the interface (function names and inputs), what it hides, and what would be hard to change later. Then recommend one.
With AI agents
This costs an agent seconds, which makes it one of the cheapest quality boosts there is. You read two short designs and pick, instead of reviewing a finished build you didn't want.
Watch out
The two designs have to be truly different, not the same idea twice with new names.
In the book
Ch. 11, Design it Twice
Read it if you always go with your first idea.
Same idea in the other books
10 · Comments say what code can't
Explain the why, write it first, choose precise names.
The idea
Code shows what happens. It can't show why, what the units are, or what a caller must never do. That's what comments are for. Ousterhout suggests writing a module's comment before its code: if it's hard to describe simply, the design is probably wrong. Names should be precise enough that a reader can guess what they mean.
Plain example · no code
A recipe that says “add salt” versus one that says “add salt at the end, or the beans stay hard”. The second one tells you what matters.
In code
// Says nothing new: // add one to count count += 1; // Says what the code can't: // Timeout in milliseconds. 0 means wait forever. timeoutMs: number;
With AI agents
Comments and names are the first things an agent reads. A precise name and a one-line why stop it from guessing, and from rewriting things it shouldn't touch.
Watch out
Comments that repeat the code just go out of date. Only write what the code can't say.
In the book
Ch. 12–15 on comments; Ch. 14, Choosing Names
Read it if people keep using your functions the wrong way.
Same idea in the other books
Safety · 2004 · about 450 pages
O'Reilly pageWorking Effectively with Legacy Code
Michael Feathers
How to change code that has no tests without breaking it: get it under test first, then change it.
What to read
Part I (Ch. 1–5). After that, look up the chapter for the problem you have. Part II is a FAQ.
Who it's for
Anyone changing an app that already exists, including one an agent wrote last month.
10 ideas · click one to open it
01 · Legacy code = code without tests
Age doesn't matter. Tests do.
The idea
Feathers defines legacy code simply: code without tests. Without tests, you can't tell whether a change broke something, so every change is a gamble. By this definition, code an agent wrote this morning with no tests is already legacy code.
Plain example · no code
A house with no blueprints. It might be fine, but before you knock down a wall you have no idea what's inside it.
In code
// Not legacy: a test says what it must do. test("adds tax", () => { expect(withTax(100)).toBe(108); });With AI agents
This line is why the book matters now. Agents write a lot of code fast. Without tests, it's legacy the moment it lands.
Watch out
Tests aren't a box to tick. Tests that check nothing important give you false confidence.
In the book
Preface
Read it if your team is scared to touch some part of the app.
Same idea in the other books
02 · Cover and modify, not edit and pray
Put tests around code before you change it.
The idea
Edit and pray: make the change very carefully and hope. Cover and modify: first wrap the code in tests that will notice any change, then change it with a safety net under you. Being careful doesn't make a change safe. Tests do.
Plain example · no code
A trapeze artist with a net can try a new move. Without one, they'd better never fall.
Say it to your agent
Before changing this function, write tests for what it does now. Run them and show me they pass. Then make the change and run them again.
With AI agents
Agents are confident editors. A safety net turns that confidence into something you can check. Pocock pairs agents with tests and test-first work for the same reason.
Watch out
Getting old code under test is sometimes the hard part. That's what the rest of the book is for.
In the book
Ch. 1, Changing Software; Ch. 2, Working with Feedback
Read it if every release feels like a gamble.
Same idea in the other books
03 · The legacy change recipe
Five steps for changing old code safely.
The idea
Feathers gives a short recipe. Find where the change goes. Find where you can test it. Break whatever stops you testing it. Write the tests. Then make the change and tidy up. Most of the book is help with the third and fourth steps.
Plain example · no code
Rewiring one room: find the circuit, find where to test it, cut power to just that room, test the wires, then rewire.
The recipe
1. Change point: where does the change go? 2. Test point: where can I check it? 3. Break deps: what stops me testing it? 4. Write tests: pin down what it does today. 5. Change: make it, then tidy up.
With AI agents
Give this recipe to an agent as the plan for any change to old code. It stops the agent jumping straight to step 5.
Watch out
Step 3 changes code before there are tests, so do it in tiny, careful moves. The book shows safe ones.
In the book
Ch. 2, Working with Feedback
Read it if you want a checklist for touching old code.
04 · Sensing and separation
The two reasons to cut a dependency.
The idea
You cut a dependency for one of two reasons. Sensing: you can't see what the code did, so you can't check it. Separation: you can't even run the code on its own, because it drags in a database, a network or the whole app. Name which problem you have, and the fix gets clearer.
Plain example · no code
Testing a smoke alarm. Sensing: you need to hear whether it beeps. Separation: you don't set the house on fire to find out. You use a can of test smoke.
In code
// Separation: swap the real mailer for a fake one. class FakeMailer { sent: string[] = []; send(to: string) { this.sent.push(to); } } const mailer = new FakeMailer(); signUp("a@b.com", mailer); // Sensing: now we can see what happened. expect(mailer.sent).toEqual(["a@b.com"]);With AI agents
When an agent says something can't be tested, ask whether it's a sensing problem or a separation problem. That one question points it at the right fix.
Watch out
Fakes can drift away from the real thing. Keep a few tests that use the real one too.
In the book
Ch. 3, Sensing and Separation
Read it if your tests need a live database to run.
05 · Seams
Places to change behavior without editing the code there.
The idea
A seam is a spot where you can swap what the code does without editing that code, like passing in a different object, or pointing to a different file during tests. Every seam has a place where you choose which version to use. Finding seams is how you get stuck code under test.
Plain example · no code
A wall socket is a seam. You can swap a lamp for a phone charger without rewiring the wall.
In code
// No seam: the clock is welded in. function isOpen() { return new Date().getHours() < 17; } // Seam: pass the time in. Tests choose it. function isOpen(now = new Date()) { return now.getHours() < 17; } isOpen(new Date("2026-01-01T18:00")); // falseWith AI agents
Seam is part of Pocock's skills vocabulary: his implement skill drives tests at the seams you named. Naming the seams tells the agent where the tests go.
Watch out
Not every seam is good long-term design. Use them to get tests in, then improve the design.
In the book
Ch. 4, The Seam Model
Read it if you can't test something because it calls the real world.
Same idea in the other books
06 · Characterization tests
Record what the code does now, not what it should do.
The idea
Before changing old code, write tests that capture what it does today, odd bits included. Run the code, see what comes out, and write a test that expects exactly that. Now any change in behavior will show up. Whether the old behavior was right is a separate question.
Plain example · no code
Before renovating, you photograph every room. You're not judging the decor. You just want a record in case something goes missing.
In code
// 1. Write a test you expect to fail. expect(shippingCost("AK", 5)).toBe(0); // 2. Run it. It says the real answer is 23.5. // 3. Lock in what the code actually does. expect(shippingCost("AK", 5)).toBe(23.5);With AI agents
This is a perfect agent job: run the old code with lots of inputs and save the answers as tests. Tell it not to fix anything yet, only record.
Watch out
If you find a bug while doing this, write it down. Don't fix it in the same step. Someone might depend on the bug.
In the book
Ch. 13, I Need to Make a Change, but I Don't Know What Tests to Write
Read it if nobody knows exactly what the old code does.
Same idea in the other books
07 · Sprout and wrap
Put new code somewhere new, and test it there.
The idea
When you can't get old code under test today, don't add more untested code to it. Sprout: write the new logic as a new, tested function and call it from the old code. Wrap: add the new behavior before or after the old code, without touching its insides.
Plain example · no code
Adding a sunroom to an old house, instead of knocking through walls you don't understand.
In code
// Sprout: the new rule is a new, tested function. export function dropDuplicates(items: Item[]) { const seen = new Set<string>(); return items.filter((x) => { if (seen.has(x.id)) return false; seen.add(x.id); return true; }); } // The only change inside the old, untested code: const toPost = dropDuplicates(entries);With AI agents
Ask agents to sprout instead of editing deep inside long, untested functions. Their change becomes small, tested and easy to review.
Watch out
It's a way out, not a home. The old code is still untested. Come back and cover it later.
In the book
Ch. 6, I Don't Have Much Time and I Have to Change It
Read it if you have to ship a change today in code you don't trust.
Same idea in the other books
08 · Dependency-breaking moves
A catalog of small, safe changes that make code testable.
The idea
The last part of the book is a catalog of small moves for code that resists testing. Pull out an interface so you can pass in a fake. Hand a dependency in from outside instead of creating it inside. Override one troublesome method in a test version. Each move is small enough to make safely before tests exist.
Plain example · no code
A mechanic's manual: a list of standard moves, each with steps, for freeing a stuck part without breaking the engine.
In code
// Before: the class builds its own database. class Report { db = new Database(); } // Parameterize Constructor: hand it in. class Report { constructor(private db: Db = new Database()) {} } new Report(fakeDb); // tests use a fakeWith AI agents
These moves have names. Telling an agent to “use Parameterize Constructor here” is exact in a way that “make it testable” isn't.
Watch out
The examples are Java and C++ from 2004. The moves carry over, but the code style is dated.
In the book
Ch. 25, Dependency-Breaking Techniques
Read it if a class drags in half the app when you try to test it.
Same idea in the other books
09 · Effect sketches and pinch points
Trace what a change can reach, then test at the narrow spot.
The idea
Before changing something, sketch what it can affect: which values, which functions, which outputs. Bubbles and arrows on paper are enough. Often many effects flow through one narrow spot, a pinch point. One good test there covers a lot.
Plain example · no code
All the streams in a valley run under one bridge. To measure the water, you stand on the bridge, not at every stream.
An effect sketch
price ──► applyDiscount ──► subtotal ──► invoice.total │ └──► emailReceipt Pinch point: subtotal. One test there covers both.With AI agents
Ask the agent to draw the effect sketch before it changes anything. It's a quick way to see whether it understood what its change can reach.
Watch out
A sketch is a guess. Check it with a test before you trust it.
In the book
Ch. 11, I Need to Make a Change. What Methods Should I Test?; Ch. 12 on pinch points
Read it if you're never sure what a change might break.
10 · Small, safe steps
Tiny changes, checked often. Let the tools catch mistakes.
The idea
Work in steps small enough that if something breaks, you know exactly which step did it. Feathers also suggests leaning on the compiler: make a change that breaks every place needing an update, and use the list of errors as your to-do list.
Plain example · no code
Crossing a stream on stepping stones. Test each stone before you put your weight on it.
In code
// Lean on the compiler: rename the field, // then let every error point to a place to fix. type User = { fullName: string }; // was: name // error: Property 'name' does not exist on type 'User' // error: Property 'name' does not exist on type 'User'With AI agents
Type errors are free feedback for an agent. Pocock leans on types and tests as the agent's feedback loop. Small steps keep each review small too.
Watch out
The compiler only catches what types can see. Changes in behavior still need tests.
In the book
Ch. 23, How Do I Know That I'm Not Breaking Anything?
Read it if big changes keep going wrong in ways you can't trace.
Words · 2003 · about 560 pages
Domain Language pageDomain-Driven DesignTackling Complexity in the Heart of Software
Eric Evans
How to model a business in software, starting with one shared set of words.
What to read
Chapters 1–3 first, as the list says. Then dip into the rest when you need it.
Who it's for
Anyone building software for a business that has its own jargon. Which is most of them.
10 ideas · click one to open it
01 · Focus on the core domain
Spend your best effort where the business is special.
The idea
Every business has a few things that make it different and many that are the same as everyone else's. Put your best people and most design care into the special part, the core domain. Keep the rest simple, or buy it: logins, invoices, emails.
Plain example · no code
A bakery famous for its sourdough perfects the bread. It buys its till, its paper bags and its accounting software off the shelf.
Say it to your agent
What makes this business different is: [your core]. Spend design effort there. For login, payments and email, use the simplest standard option. Don't customize.
With AI agents
Tell the agent which part is core. Otherwise it treats every feature the same and spends as much care on a settings page as on your main product.
Watch out
The core can move as the business changes. Check it again every so often.
In the book
Ch. 15, Distillation (Part IV)
Read it if your team spends weeks on parts customers never notice.
02 · Knowledge crunching
Learn the business by working through it with the experts.
In the first three chapters
The idea
Developers and domain experts, the people who know the business, work through real examples together. Each pass sorts what matters from what doesn't, until a clear model of how the business works comes out. It's a back-and-forth, not one interview.
Plain example · no code
A kitchen designer sits with a family and walks through a normal morning: who's up first, where the coffee is, where the kids drop their bags. The design comes out of that, not out of a form.
Say it to your agent
Interview me about this feature, one question at a time. Use real examples. When my answers conflict, point it out. At the end, sum up the rules you learned.
With AI agents
This is what Pocock's grill skills do: the agent interviews you, one question at a time, until you both understand the same thing. Then it writes the words down.
Watch out
Talking only to managers isn't enough. Talk to the people who do the work every day.
In the book
Ch. 1, Crunching Knowledge
Read it if the software keeps missing what the business actually does.
Same idea in the other books
03 · Ubiquitous language
One shared set of words in talk, docs and code.
In the first three chapters
The idea
Pick one name for each idea in the business and use it everywhere: in meetings, in documents and in the code. If the business says booking, the code says Booking, not Reservation or Order. When the words change, the model has changed, and the code follows.
Plain example · no code
A hospital where everyone means the same thing by “admitted”. If the nurses, the billing team and the computer system each mean something different, mistakes follow.
In code
// Three words for one thing. Which is it? reservation.confirm(); order.cancel(); booking.total; // The business says booking. So does the code. booking.confirm(); booking.cancel(); booking.total;
With AI agents
This is the idea Pocock leans on most. A glossary file gives the agent your words, so plans get shorter and the code matches what you asked for. His grill-with-docs skill writes that glossary as you talk.
Watch out
One language per area. The same word can mean different things in sales and in shipping. That's what bounded contexts are for.
In the book
Ch. 2, Communication and the Use of Language
Read it if your team argues, and it turns out you meant different things.
Same idea in the other books
04 · Model-driven design
The model and the code stay tied together.
In the first three chapters
The idea
The model, your picture of how the business works, shouldn't live only in a diagram. The code should look like the model, so changing one means changing the other. Evans also says the people who design the model should touch the code, so the two don't drift apart.
Plain example · no code
A map that matches the streets. If the city adds a road and nobody updates the map, people get lost.
In code
// Code that reads like the business rule: // "A booking can be cancelled up to 24 hours before." class Booking { canCancel(now: Date) { return hoursUntil(this.start, now) >= 24; } }With AI agents
When the code mirrors the business, you can check an agent's work in plain words: does this match how we said it works? That's a review a non-coder can do.
Watch out
If the diagram and the code disagree, the code is what actually runs. Fix one or the other.
In the book
Ch. 3, Binding Model and Implementation
Read it if your design documents and your app tell different stories.
Same idea in the other books
05 · Bounded contexts
A model only holds inside a clear boundary.
The idea
One model for the whole company never works. Customer means one thing to sales and another to support. Draw clear boundaries, each with its own model and its own words. Inside a boundary, words are exact. Between boundaries, you translate on purpose.
Plain example · no code
“Table” means one thing to a carpenter and another to an accountant. Both are right, in their own workshop.
In code
// sales/customer.ts type Customer = { name: string; leadSource: string }; // support/customer.ts: same person, different model type Customer = { name: string; openTickets: number };With AI agents
Folders that match your contexts give an agent clean edges. The agent working on billing doesn't need the shipping model, and won't get confused by it.
Watch out
Lots of tiny contexts is its own mess. Draw boundaries where the language really changes.
In the book
Ch. 14, Maintaining Model Integrity (Part IV)
Read it if one User table is trying to serve the whole company.
06 · Context maps
Draw how the parts relate, and protect your own.
The idea
Once you have contexts, map how they connect. Do two teams share some code? Does one have to accept whatever the other sends? Evans names these patterns. The most useful is the anti-corruption layer: a translator that keeps another system's messy model out of yours.
Plain example · no code
An interpreter at a meeting. Each side speaks its own language, and the interpreter makes sure nothing gets mangled.
In code
// Anti-corruption layer: translate their shape into ours. function fromOldCrm(raw: OldCrmRow): Customer { return { name: raw.CUST_NM.trim(), email: raw.EMAIL_ADDR }; }With AI agents
When an agent connects to an outside API, ask it to put a translator in between. The rest of your code, and every later agent, only sees your clean shape.
Watch out
Draw the map as things are, not as you wish they were.
In the book
Ch. 14, Maintaining Model Integrity (Part IV)
Read it if another system's odd data keeps leaking into yours.
Same idea in the other books
07 · Building blocks
Entities, value objects, services and modules.
The idea
Evans names the basic pieces. An entity has an identity that lasts, like a customer, even if their name changes. A value object is defined only by its values, like an amount of money, and never changes once made. A service is an action that doesn't belong to one thing, like a transfer between accounts. Modules group related pieces.
Plain example · no code
Your passport is an entity: it's still yours if the photo changes. A $20 bill is a value: any $20 bill will do.
In code
// Entity: identity matters. type Customer = { id: string; name: string }; // Value object: only the values matter. Never changes. type Money = Readonly<{ amount: number; currency: "USD" | "EUR" }>;With AI agents
Models know these words well. “Make Money a value object” is a short, exact instruction.
Watch out
Don't force every piece of code into one of these boxes. They're a vocabulary, not a rulebook.
In the book
Ch. 5, A Model Expressed in Software (Part II)
Read it if you're not sure what should have an ID and what shouldn't.
08 · Aggregates
Group things that must stay consistent, with one way in.
The idea
Some things must change together, like an order and its line items. An aggregate groups them behind one root that the outside world talks to. The root checks the rules, so the group can never be left half-updated. Factories create these groups. Repositories store and fetch them.
Plain example · no code
A bank account. You don't edit the balance directly. You go through the account, which checks the rules: enough money, daily limit.
In code
class Order { // the root: the only way in private lines: Line[] = []; addLine(item: Item, qty: number) { if (this.lines.length >= 50) throw new Error("too many lines"); this.lines.push({ item, qty }); } }With AI agents
One way in means an agent can't accidentally skip a rule by editing the data directly. The rules live in one place it can read.
Watch out
Keep aggregates small. Big ones are slow, and two people changing one at once will clash.
In the book
Ch. 6, The Life Cycle of a Domain Object (Part II)
Read it if your data keeps ending up in states that should be impossible.
Same idea in the other books
09 · Supple design
Code that's easy and safe to change and combine.
The idea
Evans describes design that bends without breaking. Names that say what a thing does, not how. Functions with no hidden side effects. Rules written as checks. He also says to keep the business logic in its own layer, apart from screens and databases, so it's easy to find and change.
Plain example · no code
A good screwdriver does what its name says, doesn't secretly drill holes, and works with any screw of the right size.
In code
// Says what it does, no side effects: const total = cart.totalWith(discount); // just returns a number // Hidden side effects: surprises later. cart.apply(discount); // also saves? emails? who knows
With AI agents
Functions without hidden side effects are easy for an agent to reuse and test. Names that say what they do stop it from guessing.
Watch out
This is something you grow toward. Nobody's code starts out this way.
In the book
Ch. 10, Supple Design (Part III); Ch. 4, Isolating the Domain
Read it if every change comes with a surprise side effect.
Same idea in the other books
10 · Refactoring toward deeper insight
The model gets better as you learn. Change the code to match.
The idea
Your first model is never the best. As you learn the business, you'll suddenly see a simpler way to describe it. When that happens, change the code to match, even though it works today. Distillation keeps the core clear by moving the generic parts out of the way.
Plain example · no code
Learning a new city, you first memorize routes. One day you notice the river runs through the middle, and suddenly every route makes sense.
Say it to your agent
We now call this a subscription, not a recurring order. Rename it everywhere: code, tests and the glossary. Show me the plan before you change anything.
With AI agents
Renaming and reshaping code used to be expensive. With an agent and good tests, acting on a new insight is cheap. Update the glossary first, then the code.
Watch out
Not every new idea is a breakthrough. Wait until the new model clearly explains more with less.
In the book
Part III, Refactoring Toward Deeper Insight (Ch. 8–13); Ch. 15, Distillation
Read it if the code still reflects how you understood the business a year ago.
Same idea in the other books
40 ideas, ten per book. The summaries and examples are ours, not the authors' wording. Chapter numbers are for the editions named on each book. A Philosophy of Software Design uses first-edition numbers. The second edition adds a chapter, so a number may be off by one there.
One idea, four books
Read side by side, the four books keep saying the same few things in different words. Each row is one of those things. Click any box to open it.
- 01
Make change cheap
The goal under all four books. Good design is design that's easy to change.
- 02
Hide the messy part behind a simple front
Small fronts, big backs, clean edges. Each book has its own word for it.
- 03
One fact, one place, one name
Say each thing once, and call it the same thing everywhere.
- 04
Try it small before you commit
A thin slice, a second design, a new tested function, a real example with an expert.
- 05
Know what the code really does
No luck, no guessing. Write down the why, record what it does, keep it matching the business.
- 06
Invest a little every day
Mess builds up quietly. All four say: pay it down as you go, not once a year.
- 07
Guard the borders
Keep outside things, vendors, errors and other systems' models from leaking into your code.
The rows are FakeNerd's reading. None of the authors draws this table, and Feathers never states the third thread as a rule, so that box is empty.
Where to start
Find the line that sounds like you. Each one names what to read first and three ideas to open now.
If you say
“I direct agents. I don't write code.”
Read: The Pragmatic Programmer, Ch. 1–2 (Topics 1–15). Then Domain-Driven Design, Ch. 1–2.
Both are about how to think and how to talk about the work, not syntax. That's most of the job when an agent types.
If you say
“My agent's code is getting tangled.”
Read: A Philosophy of Software Design, Ch. 2–5, then Ch. 10–11.
It gives you the words to say what's wrong (shallow, leaky, too many special cases) and what to ask for instead.
If you say
“I have an old app nobody wants to touch.”
Read: Working Effectively with Legacy Code, Ch. 1–4, then Ch. 13 and Ch. 6.
It's a step-by-step way to get a safety net under code nobody understands, before anyone changes it.
If you say
“I build for a business with lots of its own terms.”
Read: Domain-Driven Design, Ch. 1–3, then Ch. 14.
It's about getting the business's words into the code, and keeping different parts of the business from muddling each other.
If you say
“One book, one weekend.”
Read: A Philosophy of Software Design, cover to cover.
It's the shortest, and its ideas, deep modules most of all, are the ones Pocock leans on most when he talks about agents.
Try it, smallest version first
- 01
Read one chapter tonight
A Philosophy of Software Design, Ch. 4, or The Pragmatic Programmer, Topic 12. Each is short and stands on its own. If you only read one thing, make it one of these.
- 02
Give your agent your words
Make a glossary file in your project with one line per business term. Ask the agent to use only those words. This is ubiquitous language in ten minutes.
FakeNerd starter · CONTEXT.md
# CONTEXT.md — the words we use One line per term. Use these words in chats, docs and code. If a word is missing or wrong, say so and update this file first. ## Terms - Booking: one customer's reserved time slot. Not "reservation", not "order". - Guest: the person who comes in. May not be the one who paid. - Payer: the person whose card is charged. - No-show: a booking where the guest didn't arrive within 15 minutes. ## Words we don't use - "Reservation" (say Booking) - "User" when we mean Guest or Payer ## Areas (each has its own words) - Bookings: everything above - Billing: Invoice, Refund, Payer
- 03
Put the book words in your rules file
Paste this into CLAUDE.md or AGENTS.md. Each line is one idea from this page, written as an instruction.
FakeNerd starter · rules file block
## Design habits (from four classic books) - ETC: when there are two ways, pick the one that's easier to change later. - Tracer bullet first: build one thin slice that works end to end, then grow it. - Deep modules: small, simple interfaces with the work hidden inside. No pass-through layers. - Use the words in CONTEXT.md. One name per idea, in code and in chat. - Old code without tests: write characterization tests first. Change nothing until they pass. - New code in untested areas: sprout a new, tested function instead of editing deep inside. - Before you finish: list what you skipped, guessed or couldn't test.
- 04
Next feature: ask for a tracer bullet
Instead of describing the whole feature, ask for the thinnest slice that works end to end. Check it, then grow it.
FakeNerd starter · tracer bullet
Build this as a tracer bullet. The feature: [what you want] 1. Build the thinnest version that goes all the way through: screen -> logic -> storage -> back to the screen. 2. Leave out everything else. List what you left out. 3. Show me it working before adding anything.
- 05
Before touching old code: record it first
Have the agent write characterization tests, so any change in behavior shows up straight away.
FakeNerd starter · characterization tests
Before changing [file or function], write characterization tests. 1. Run the current code with a range of normal and odd inputs. 2. Write tests that expect exactly what it does today, even if it looks wrong. 3. Don't fix anything yet. List anything that looks like a bug. 4. Show me the tests passing. Then we'll make the change.
- 06
Before anything big: design it twice
Two different designs, compared in plain words. It costs the agent seconds and saves you reviewing the wrong build.
FakeNerd starter · design it twice
Design it twice before writing code. The job: [what this part should do] Give me two very different designs. For each: - the interface: function names, inputs, outputs - what it hides from the rest of the code - what would be hard to change later Then recommend one, in plain words.
Where this fits on FakeNerd
This page is the reading behind two others.
The skills
Matt Pocock's skills
The book ideas turned into agent skills: grill-with-docs (ubiquitous language), codebase-design (deep modules), tracer-bullet tickets, tests at named seams.
The picker
Which skill pack when
Pocock's pack next to Addy Osmani's and pstack. If you want the ideas built in rather than read, start there.
Same advice, different person
Guillermo Rauch's workflow
Vercel's CEO also tells people to learn the concepts, not the syntax, so they can tell an agent what to do and know it's possible.
FakeNerd's take
These are agent instructions in disguise
Each book gives short, exact names to big ideas, and the models learned the same names. “Build a tracer bullet” says in three words what would take a paragraph. That's Pocock's “leading words” idea, and it's why old books pay off now.
Read for the ideas, skip the dated code
Legacy Code (2004) and Domain-Driven Design (2003) use Java and C++ era examples. The ideas have aged far better than the code. Read the reasoning, not the syntax.
Non-coders: start with two
The Pragmatic Programmer's first two chapters and Domain-Driven Design's first two are about thinking and talking, not code. That's most of the job when you direct an agent.
The skill that grows is judgment
Agents type. Deciding what's core, where the edges go, what to test and when it's good enough is still yours. These four books are mostly about those calls.
Attribution
- The books: The Pragmatic Programmer by David Thomas and Andrew Hunt (Addison-Wesley, 2nd edition 2019); A Philosophy of Software Design by John Ousterhout (Yaknyam Press, 2018 and 2021); Working Effectively with Legacy Code by Michael Feathers (Prentice Hall, 2004); Domain-Driven Design by Eric Evans (Addison-Wesley, 2003). The ideas are theirs. Every summary, example and scenario on this page is FakeNerd's, in our own words. Nothing is quoted from the books.
- The list of four, and the tip to read only the first three chapters of Domain-Driven Design: Peter Jia (@PeterJiax) on X, Oct 7, 2026, replying to Matt Pocock's post the same day.
- What Pocock says about each book is from the pages for his AI Engineer Europe 2026 talk and his Pragmatic Engineer episode (Sep 17, 2026), plus his skills repo. We couldn't pull transcripts, so nothing is quoted from him either.
- Chapter pointers: The Pragmatic Programmer topic numbers from the publisher's table of contents (2nd edition). The other three from printed tables of contents. Page counts are rounded.
- The forty “with AI agents” lines, the seven threads, the reading picker, every starter and the takes are FakeNerd's. No affiliate links. Not sponsored by anyone on this page.