Write the Decision, Not the Code: Notes on Structured Prompt-Driven Development
What Structured Prompt-Driven Development changes, what it doesn’t, and why engineering discipline matters more when an LLM is doing the typing
There’s a familiar cycle in software development. Every couple of years a new practice shows up, somebody gives it a good name, draws a diagram around it, and announces that the way we build software has fundamentally changed. Sometimes they’re even right. Most of the time, though, the “new practice” is an old engineering lesson coming back around in a form we can no longer afford to ignore.
I’ve now spent enough time with Structured Prompt-Driven Development, on my own projects and in consulting work, to have an actual opinion about it, and my conclusion is less dramatic than the name suggests. I don’t mean that as criticism. SPDD doesn’t fundamentally change software engineering. What it changes is how much engineering discipline you need before you let an unreliable, stochastic code generator anywhere near your system. Martin Fowler calls it a “material change in how developers build software,” and sure, you can put it that way – the workflow certainly looks different. But the underlying work is remarkably familiar: understand the problem, model the domain, choose the boundaries, identify the invariants, define what “done” means, implement, verify.
The difference is that an experienced developer used to carry half of this in their head while typing, and the neural network can’t. So now you have to write it down.
SPDD is a containment system for generation, not a new kind of engineering
An LLM will produce an astonishing amount of plausible code very quickly, and “plausible” and “correct for this particular system” are two entirely different standards. The model doesn’t know that this API is consumed by an old mobile client nobody wants to touch. It doesn’t know the strange-looking validation rule exists because of a production incident three years ago, or that the team once agreed (e.g.: in a meeting nobody wrote down) that one service may read a field but must never own it. It sees code, text, and whatever context you managed to put in front of it, and it fills in the gaps. That’s the useful part and the dangerous part at once: it will almost never stop and say “there’s an organizational decision missing here, go resolve it with the responsible humans.” It makes a reasonable guess, writes the code, and presents the result with the calm confidence of someone who is expert-in-class-engineer.
What SPDD actually does is give that guessing process boundaries. It turns “please implement this feature” into something closer to an engineering contract: here’s the intent, here’s the model, here’s where the change belongs, here are the rules, and here’s how we’ll know it worked. That’s genuinely useful. It’s just not magic, and it’s worth being precise about which problem it solves.
The thinking has to move forward, because the model can’t carry it with you.
Developers have always designed while coding, whatever the process document claimed. You start with a rough idea, sketch an interface, the interface feels wrong so you adjust the model, you write a test and suddenly discover that nobody decided what happens when two conditions fire at once. The solution emerges through contact with the system. And by the time the implementation is done, you’ve pulled information from everywhere: documentation, existing code, old incidents, meetings, hallway conversations, naming conventions, half-remembered business rules, and years of experience with similar problems. Almost all of that knowledge is implicit. The LLM has none of it unless you hand it over.
Which means the work developers used to do partly during implementation now has to happen earlier and more explicitly. Before generation starts, someone has to work out the entities, the responsibilities, the boundaries, the quality attributes, the invariants, the edge cases, the acceptance criteria – everything the engineering schools from XP onward have been telling us to do up front for decades, and everything we cheerfully skipped because we could always figure it out at the keyboard. SPDD didn’t invent design-first development; it just made skipping it expensive in a new way, because the machine can’t infer the design you forgot to communicate.
A structured prompt is a temporary transfer of engineering context
People sometimes talk about prompting like it’s a new kind of incantation: find the right phrase, arrange the words correctly, and the machine rewards you with good code. For serious development that’s the least interesting part. The real job is extracting the relevant mental model out of the developer’s head and rebuilding it in a form the model can use. In practice, a useful structured prompt has to cover a surprising amount of ground:
which layer of the system should change;
which APIs may be modified, and which must not be touched;
which domain invariants are non-negotiable;
which architectural conventions apply;
which tests are mandatory and which edge cases matter;
and what a successful result actually looks like.
Even that list is incomplete, because the model also needs the reasons. “Don’t change this API” is an instruction. “Don’t change this API because two external clients upgrade on a six-month release cycle” is engineering context. The second version helps the model make better decisions when it hits something you didn’t explicitly describe – rules tell it where the fence is, reasons tell it why the fence is there, and you want both.
Describe the boundary; don’t dictate every keystroke
There’s a bad version of structured prompting where the developer writes a natural-language transcription of the code they want and asks the model to type it. At that point you haven’t automated implementation – you’ve implemented the feature in English (usually badly) and hired a very expensive autocomplete to translate it. A good prompt locks down the important decisions (what problem is being solved, where the responsibility belongs, what must stay compatible, what may not be violated, how the result will be tested) and leaves the model room to do useful work inside those lines.
This balance is harder than it sounds. Too little detail and the model improvises your architecture for you; too much, and maintaining the prompt becomes more work than maintaining the code. No framework removes this judgment, because the judgment is the job.
Repeatable is not the same as deterministic
One of the honest benefits of SPDD is that the development instruction becomes durable. A good prompt can be stored, versioned, reviewed, reused, and revisited months later. When someone asks why a change was made, you have more than a ticket saying “support enterprise billing” – you have the intended model, the constraints, the chosen approach, and the definition of done. That’s a real improvement over an abandoned chat transcript, or over the developer saying “I remember there was a reason.”
But the word “repeatable” needs a warning label. The same prompt doesn’t necessarily produce the same code; the outcome still depends on the model, its configuration, the surrounding context, the state of the repository, and the ordinary randomness of generation. You can raise the probability of an acceptable result. You can’t turn a stochastic generator into a compiler by adding headings.
Review stops being archaeology
Traditional code review starts too late: the reviewer sees a diff and has to reconstruct the intention from the implementation. Why was this object introduced? Was that behavior deliberate? Is the new API shape a requirement, or just the first thing the author thought of? With a structured prompt the reviewer gets two artifacts:
what the system was supposed to become,
and what the model actually produced;
– and can compare them directly. Did the implementation stay inside the permitted boundary? Were the invariants respected? Did the generated code quietly widen the scope? Is the prompt itself missing a decision?
None of this makes review easy. A large pile of generated code is still a large pile of code, and somebody has to understand it before it ships. But review turns from archaeology into comparison, and that’s worth having.
The real speed shows up in large, coordinated changes
The most obvious productivity win appears when a change has to propagate across many parts of a system. A small adjustment to a well-built prompt can produce coordinated updates to interfaces, implementations, tests, mappings, and documentation across dozens of modules – and with a mature structure and good safeguards in place, the model does the mechanical part far faster than a human moving file by file. This is where the “it only saves typing” jab gets slightly unfair. Sometimes the typing is thirty similar components that each differ in one subtle way. Sometimes it’s the first complete draft of a migration that would take days just to assemble. SPDD makes that kind of work objectively faster.
Notice the condition, though: with a mature structure and good safeguards. Without them, you can generate thirty coordinated mistakes in the time it used to take to make one. Speed multiplies whatever direction you gave it.
Senior engineers can package their judgment; they can’t retire it
There’s an attractive organizational angle here: experienced engineers define the prompt templates, the architectural rules, the checklists, the standard safeguards, and less experienced developers use those assets instead of rediscovering every constraint from scratch. Expertise gets to travel. A strong engineer’s contribution stops being limited to the code they personally write and the reviews they have time for – some of their judgment gets encoded into the machinery that produces future changes. In a large organization, where inconsistency usually hurts more than any individual’s typing speed, that’s worth a lot.
Just be careful with the conclusion. A checklist written by a senior engineer doesn’t turn its user into a senior engineer. Templates cover the known failure modes; they don’t guarantee that the person filling one in will spot the unusual risk, pick the right abstraction, or notice that the task itself rests on a false assumption. You can distribute judgment that already exists, but you can’t template your way out of needing it.
The old loop discovered questions – a confident prompt can bury them
There was a reason developers solved part of the problem during implementation: walking through the solution step by step surfaces questions that never come up in a verbal discussion. You create the object and realize it has two competing owners. You write the test and discover that “cancelled” means three different things depending on who initiated it. You wire up the API and notice the operation can’t actually be made atomic. That familiar “oh – wait, what’s supposed to happen here?” isn’t a process failure; it’s one of the main ways engineering knowledge gets produced.
A badly applied SPDD process can suppress exactly this. The prompt looks complete, the model produces a confident implementation, and the team mistakes fluency for resolved design. The fix isn’t to abandon structured prompts – it’s to treat them as living artifacts. Generate, inspect, find the missing question, update the prompt, generate again. When reality diverges from the instruction, fix the instruction instead of piling up local patches the prompt no longer explains. There’s an interesting side effect here, too: this workflow quietly forces you into the structured problem-solving methods that have existed for decades and that most teams cheerfully ignored. Those methods are getting a second life, because skipping them now has an immediate, visible cost.
You have to speak engineering, not just English
LLMs understand almost any language, which is impressive and inconvenient at the same time. You can describe a task in loose everyday terms and still get code back, which creates the impression that precision is optional (beleive me – it isn’t). If you don’t tell the model that Chain of Responsibility or a Builder Pattern is the right shape here, odds are it won’t reach for them (and those patterns aren’t decoration, they’re ways of localizing change). Localized change means less context the model has to process, and less context means a better chance it implements the modification without wandering off into the rest of the system. If the change belongs in the domain layer and not the transport layer, name the boundary. If the operation must be idempotent, use the word “idempotent” and say over what scope.
Engineering language compresses established ideas. Without it, you’ll spend three paragraphs describing a pattern badly and the model may still miss the point. This isn’t a call to stuff prompts with pattern names for show (e.g.: “use a Builder” is not a substitute for understanding the construction problem) but when a known concept accurately describes your constraint, naming it removes ambiguity. In a strange way, architecture is turning into a token-management strategy. I’m not sure I enjoy that sentence either, but here we are.
You’re going to write more words; sorry
This might be the least glamorous consequence of the whole thing. Someone who has spent ten years expressing decisions through code, ten hours a day, may find it genuinely painful to write specifications, constraints, rationale, and definitions of done before every substantial change. I understand the complaint – prose feels slower than just opening the editor and getting to work. But when the LLM is doing the implementation, the prose stops being paperwork around the real work; the prose is how the real work gets directed. Vague language becomes vaguely-aimed code. An omitted invariant becomes a generated bug. A fuzzy success condition becomes a solution that looks finished because nobody said what finished meant. Nobody is asking developers to become novelists – just to make their decisions legible. That skill was always useful. Now it’s stopping being optional.
So here’s where I land. SPDD reduces the cost of producing code; it doesn’t touch the cost of understanding the system. Someone still has to understand the domain, choose the model, notice the contradiction in the requirements, pick the acceptable trade-off, protect the architecture, and verify that the plausible-looking output is actually correct. The complexity doesn’t disappear – it moves. Some of it moves from implementation into task formulation, some from typing into verification, some from individual memory into versioned artifacts. And a good chunk of it simply becomes visible, because the machine forces us to write down decisions we used to leave implicit. That visibility might be SPDD’s biggest contribution: not a new form of software engineering, but a mechanism that makes undisciplined engineering much harder to hide.
If I had to squeeze the whole episode into one line:
SPDD makes the controlled use of an LLM possible by forcing the engineering work to happen out loud – and the hard engineering itself stays exactly as hard as it ever was. The model can write the code. You still have to write the decision.
That’s my take on SPDD, from someone who’d still rather open the editor than write the spec. Ask me again in a year – half of this may have aged badly, and your codebase will disagree with me somewhere before then. Take what’s useful, leave the rest, and tell me where I’ve got it wrong. See you next time!
Explore more:



