AI-assisted engineering: using the tools with judgment
AI tools made building software dramatically faster and made bad software dramatically faster too. The difference between the two outcomes is not the model. It is what a person decides to review, reject and rewrite.
Where the speed is real
AI assistance is genuinely transformative on work that is well-specified, patterned and verifiable. It is unreliable exactly where software is hardest: unstated intent and system-wide consequence.
| Strong | Weak |
|---|---|
| Scaffolding screens, forms, routes and tests | Deciding what should exist at all |
| Translating a clear spec into a first implementation | Holding a whole system in mind while changing one part |
| Boilerplate, migrations, types, adapters | Data modelling that will still fit in two years |
| Explaining unfamiliar code and libraries | Security, permissions and money-handling logic |
| Mechanical refactors with a test suite behind them | Knowing when the requirement itself is wrong |
Read the two columns as an instruction about sequencing. Do the thinking that belongs to the weak column yourself, first, then let the tools sprint through the strong column.
The costs that arrive later
- Plausible wrongness. Output that reads correctly and fails on the case you did not think of. Bugs from confident code are slower to find than bugs from obviously rough code.
- Duplication. Ask three times, get three near-identical helpers. Nothing is broken, and in six months nobody knows which one is authoritative.
- Convention drift. Each generation picks a defensible pattern. Twelve defensible patterns in one codebase is worse than one mediocre pattern used consistently.
- Comprehension debt. Code nobody has read is code nobody can safely change. This is the real debt, more than any structural issue.
- Sameness. Generated interfaces converge. If the tools write your product front to back, it looks like everyone else's.
The question is never whether the code was written by a model. It is whether someone understands it well enough to change it next quarter.
The working practice
- 01
Own the shape before generating
Data model, boundaries, naming and the file layout are decisions with long consequences. Make them yourself, write them down, and let the tools work inside them.
- 02
Constrain hard, in writing
State the stack, the patterns, the components to reuse and the things never to touch. Most poor output is an under-specified request rather than a model failure.
- 03
Small units, verified
One coherent change at a time, checked immediately: types, tests, then the actual screen in a browser. Large unverified batches are where the day disappears.
- 04
Read every line you keep
Not skim. If a line is unclear, either understand it or delete it. Merging code you do not understand is the moment quality is decided.
- 05
Hand-work the moments that matter
The core interaction, the timing, the empty states, the one screen people live in. Generated code is a fine floor and a poor ceiling.
What to review with extra suspicion
- Anything touching permissions, ownership or row-level access rules.
- Anything handling money, quantities, rounding, currency or tax.
- Error paths and retries, which are usually written optimistically or not at all.
- Input validation on the server, not only in the form.
- Migrations, deletions and anything that runs once against real data.
- Dependencies added along the way. Every new package is a decision someone should have made deliberately.
A short automated gate helps more than any amount of discipline: types checked, linted, tests run, and the page opened for real on every change. Cheap gates keep fast generation honest.
Keeping an AI-built codebase maintainable
- One way to do each thing, documented in a short file the tools are told to follow.
- Design tokens and shared components rather than repeated inline styling, so a change lands once.
- Periodic consolidation passes: find the duplicated helpers, choose the good one, delete the rest.
- Names that describe the domain, not the implementation. Naming is where a model has the least context and you have the most.
- A rough architecture note kept current, so the next person, or the next model, starts oriented.
None of this is new engineering advice. What changed is the pace: output arrives faster than review, so the practices that used to be optional now decide whether the codebase survives its first year.
Why this favours very small teams
The bottleneck moved. It used to be typing speed and headcount; it is now judgment and coherence. One experienced person who designs and builds can now produce, in weeks, what needed a small team and several handoffs.
That only holds while one person still holds the whole thing in mind: the strategy, the interaction detail, the data model, the deployment. The advantage is not the tooling, which everyone has. It is the absence of handoffs and the presence of someone accountable for the result.