Skip to content

14.7 — Writing, Reviewing and Being Understood

Two engineers propose the same architecture change.

One explains it in a stand-up and a thread. The other writes two pages: here is the problem, here is what it costs us today, here are three options, here is the one I recommend and what it gives up, here is how we would roll it out and how we would reverse it.

The second one gets built. Not because it is better — it is the same proposal — but because it can be read by people who were not in the conversation, argued with in writing, and referred to in six months when someone asks why.

Writing is the highest-leverage skill an engineer can improve, and it is the one most consistently neglected.

1. Why it matters more than it seems

It scales. A conversation reaches the people in it. A document reaches everyone, including people who join next year.

It persists. In two years the only record of why a decision was made is what someone wrote down. Otherwise the answer is "nobody remembers", and the decision gets re-made badly.

It forces clarity. You cannot write a muddled explanation of something you understand, and you cannot write a clear explanation of something you do not. Writing is how you find out which one you are in, and this is the reason to write even when nobody will read it.

It is how influence works beyond your team. Above a certain scope, your effect on a system is mediated entirely by what you write.

2. Design documents

Write one when the decision is expensive to reverse, affects other teams, or you cannot hold the whole thing in your head. Not for every ticket — a document nobody needs is worse than no document, because it trains people to skip them.

The structure that works:

Context and problem. What is happening now and why it is a problem, with evidence. "The nightly job takes 6 hours and the window is 4" beats "the job is slow".

Goals and non-goals. The non-goals are the more valuable half — they stop the review sprawling into everything adjacent, and they record scope decisions that would otherwise be argued about repeatedly.

Proposal. What you will build, with a diagram (Chapter 14.2), enough detail to be argued with and not so much that it is the implementation.

Alternatives considered. This is the most important section in the document. For each: what it was, and why you did not choose it. Without this, a reader's first reaction is "why not just X", and either you have an answer or you have not thought about it. This section is what turns a plan into a decision record.

Trade-offs and risks. What this makes worse, what could go wrong, what you are uncertain about. A document with no downsides reads as a sales pitch and gets less trust, not more.

Rollout and reversal. How it ships incrementally, how you know it is working, and how you undo it.

Open questions. What you want the reader to decide. This is how you get useful comments instead of typo corrections.

Keep it as short as it can be while remaining arguable. Two to five pages is typical. Ten pages gets skimmed, and a skimmed document has not been reviewed.

Architecture decision records are the lightweight form — one page: context, decision, consequences, status. Right for the many smaller decisions that still deserve a written "why": this database, this library, this format. Kept in the repository next to the code, so they are found when the code is. Chapter 11's decision ledgers are the same idea inside a design.

3. Running a proposal

Whatever it is called, the shape is consistent:

Circulate with a deadline. "Comments by Thursday." An open-ended review never converges — people wait to see what others say.

Comment in the document, so context stays with the point.

Name the decision-maker before the discussion starts. Consensus-seeking without a named decider is how a proposal dies quietly, with everyone assuming someone else will conclude it.

Resolve every comment explicitly — accepted and changed, or declined with a reason. Silently ignoring a comment is what makes people stop commenting.

Record the decision and the date in the document itself, and mark it accepted. A document that ends in an unresolved thread is not a decision.

"Disagree and commit" is worth stating explicitly, because it makes disagreement safe: you can say clearly that you think this is wrong, and then support it once decided. Without that norm, people either suppress the objection or keep relitigating.

4. Writing that gets read

Lead with the conclusion. Engineers write chronologically — investigation, then finding — and readers want the answer first. "The nightly job will exceed its window within three weeks. Here is why, and here are the options." Then the detail.

One idea per paragraph, with the point in the first sentence.

Be concrete. "It is slow" is unusable; "p95 went from 200 ms to 3.4 s after the migration" is actionable. Numbers, names and specific behaviours.

Cut hedging. "It might possibly be worth potentially considering" says nothing. State the claim, then state your confidence separately if it matters: "I think X. I am not certain about the failure behaviour under load."

Define jargon on first use, or you have written for the people who already know.

Use structure for scanning — headings, short lists, tables. Most readers scan first and read the parts that matter to them, and a wall of prose defeats that.

Prefer clarity over brevity. A longer sentence that reads straight through beats a compressed one the reader has to unpack twice.

Then calibrate to the audience, which is one question: what do I want them to do?

  • Engineers want mechanism, trade-offs and constraints.
  • Managers want scope, risk, dependencies and timing.
  • Executives want the decision, the cost, the risk and the recommendation — in the first paragraph, with everything else available if they want it.

5. Code review

What it is for: catching defects, spreading knowledge of the system, keeping the codebase coherent, and teaching. It is not a gate to be passed or a demonstration of seniority, and reviews that feel like either produce defensive authors and worse code.

Review in this order, because the expensive problems are at the top:

  1. Does it solve the right problem? The most valuable question, and the one asked least.
  2. Is the approach sound? Architecture, boundaries, coupling (Chapter 9.1).
  3. Is it correct? Edge cases, error handling, concurrency, security (Chapter 8.5).
  4. Is it clear? Will someone understand this in a year.
  5. Style and naming — and most of this should be automated, because a human arguing about formatting is a wasted review.

Automate everything mechanical: formatting, linting, type checks, security scanning. Every automated check frees a human to look at design, which is the only thing they can do that a tool cannot.

Size is the strongest predictor of review quality. Defect detection falls off sharply above a few hundred lines, and by a thousand lines reviewers are approving rather than reviewing. Under about 400 lines is where review actually works — so a large change should be split into a series, or reviewed in a call.

Speed is a courtesy with a real cost. A pull request waiting a day blocks a person and grows stale. Same-day review is a reasonable team norm, and a fast "I looked, here are two questions" beats a thorough review two days later.

Tone, which decides whether review is sustainable:

  • Comment on the code, not the person. "This will throw when items is empty", not "you forgot".
  • Ask rather than assert when you are not sure. "What happens if this arrives twice?" invites an answer; "this is wrong" invites defence.
  • Mark trivia as trivia. Prefix optional suggestions — nit: — so the author knows what blocks and what does not.
  • Say what is good. A comment on a clean solution costs ten seconds and changes how the next review is received.
  • Take it to a conversation after two rounds. If a thread has gone back and forth twice, the written channel has failed for that point.

And the author's half, which matters as much:

  • Small pull requests.
  • A description that says what and why, with a link to the ticket or document.
  • Review your own diff first. You will find something, every time.
  • Respond to every comment — changed, or here is why not.
  • Do not take it personally, and do not write comments that invite it.

The anti-patterns to name: the rubber stamp (approved in nine seconds), bikeshedding (twelve comments on naming, none on the concurrency), the drive-by demand for a rewrite of something outside the change, and silence — a pull request with no comments and an approval is not a review.

6. AI-assisted review

Automated reviewers — CodeRabbit and similar — now comment on pull requests as a matter of course, and being precise about their place matters.

What they do well: mechanical issues and common bug patterns, unhandled errors and edge cases, consistency with the surrounding code, a useful summary of a large diff, and being available instantly, which is worth a lot when a human review is hours away.

What they cannot do: know whether this solves the right problem, whether it fits the architecture, whether it matches the business rule, or whether the team decided something different last month. Those are the top two items in section 5's list — the expensive ones.

Two risks worth stating.

Automation bias (Chapter 12.10): a human reviewer who sees an automated approval reviews less carefully. The mitigation is to treat automated comments as another reviewer's opinion, not as a check that passed — and to keep the human review requirement explicit.

And reviewing generated code needs more care, not less. The author has less context on code they did not write line by line, so the usual assumption — that someone thought about each line — does not hold. The reviewer is doing more of the thinking, not less, which is exactly the bottleneck Chapter 14.4 identified.

7. Comments, commits and names

Comments explain why, not what. The code says what. // retry twice: the payment provider returns 502 during their nightly maintenance window is worth keeping; // increment i is noise.

Comment the surprising. If you wrote something non-obvious for a reason, that reason is the comment — otherwise someone will "fix" it. This is where a ponytail:-style marker earns its place: a deliberate simplification with its ceiling named.

Commit messages explain why (Chapter 14.1.2), because git blame is read during an incident.

Names are the documentation people actually read (Chapter 9.1). A well-named function needs no comment; a badly named one is not rescued by a good one.

8. Incidents and status

During an incident, write short and often:

14:02 Checkout failing for ~30% of users. Investigating.
14:11 Cause: payments provider timeouts. Not a deploy.
14:25 Mitigation: retries with backoff deployed. Error rate 30% → 4%.
14:40 Recovered. Provider confirmed resolution. Postmortem Thursday.

Time, impact, cause if known, action, next update. Say "investigating" rather than going quiet — silence makes people ask, which costs the responders time. And give a next-update time, so nobody has to chase.

Escalation is a sentence: what is happening, what you have tried, what you need, and how urgent. "I need help" without those four is a slower path to help.

Status updates lead with the state, not the narrative: on track, at risk, or blocked — then why, then what you need.

9. Meetings, and their absence

The test: could this be a document? A status meeting, a design discussion where the design is not written down, an update to people who are not deciding anything — all of these are documents that were spoken instead.

When a meeting is genuinely right: a decision needing real-time back-and-forth, a disagreement that written exchange has failed to resolve (section 5's two-round rule), and anything with emotional weight — feedback, conflict, bad news. Do not deliver those in writing.

And any meeting worth holding is worth writing down afterwards: decisions, owners, next steps. The people who were not there are the ones who needed the notes, and a decision made in a room with no record will be re-litigated within a month.

Recall

  • Writing scales, persists and forces clarity — you cannot write a clear explanation of something you do not understand, which is why writing is how you find out.
  • A design document: context with evidence, goals and non-goals, proposal, alternatives considered (the section that makes it a decision rather than a plan), trade-offs and risks, rollout and reversal, open questions. Two to five pages; ten gets skimmed. Architecture decision records are the one-page form for smaller decisions.
  • Run a proposal with a deadline, a named decision-maker, every comment resolved explicitly, and the decision recorded in the document. State "disagree and commit" so disagreement is safe.
  • Writing: lead with the conclusion, one idea per paragraph, be concrete with numbers, cut hedging and state confidence separately, define jargon, use structure for scanning, and ask what do I want them to do?
  • Review in order: right problem → sound approach → correct → clear → style, and automate everything mechanical. Defect detection falls off above a few hundred lines — keep changes under ~400. Comment on the code, ask rather than assert, mark nits as nits, and move to a conversation after two rounds.
  • AI reviewers are good at mechanical issues and instant availability, and cannot judge whether it solves the right problem or fits the architecture — the two expensive items. Beware automation bias, and review generated code more carefully, not less.
  • Comments explain why, and especially the surprising; names are the documentation people actually read.
  • Incident updates: time, impact, cause, action, next update time — and never go quiet. Escalate with what is happening, what you tried, what you need, how urgent. If a meeting could be a document, it is one — and any meeting worth holding gets written up for the people who were not there.

Self-test: Which design-document section turns a plan into a decision record? · Why are non-goals valuable? · What happens to review quality above a few hundred lines? · Which two review questions can an automated reviewer not answer? · Why does generated code need more review attention? · What five things belong in an incident update?

Next: 14.8 steps outside the code entirely — how the IT industry is actually structured, where the money comes from, and what the roles nobody explains actually do.