4.5.18 · D2Software Engineering

Visual walkthrough — Code review — what to look for

2,421 words11 min readBack to topic

Step 1 — What is a "bug," and what does it cost?

WHAT. Imagine a single mistake hiding in your code. Call it a bug. It sits there quietly until someone notices it. The moment of noticing happens at some stage of the pipeline.

WHY stages matter. A bug caught while a human is reading the diff is cheap to fix — you just edit a line before anything ships. The same bug caught after real users hit it is a disaster: now there's an outage, a hotfix, an apology email. Same bug, wildly different price. So the first thing we need is a number for "how much does fixing this bug cost, given where we caught it?"

We name three stages with a counter (just an index, ):

  • — caught at review (a human reads the change before merge)
  • — caught in QA (automated/manual testing after merge)
  • — caught in production (real users already hit it)

PICTURE. Look at the staircase. Each step to the right is one stage later, and the height — the cost — jumps by a fixed multiplier each time, not by a fixed amount. That "multiply, don't add" shape is the whole reason review exists.

Figure — Code review — what to look for

Step 2 — Turning the staircase into a formula

WHAT. We claimed the cost multiplies by each stage. Let's write that down.

  • At : cost (one baseline unit).
  • At : cost (one stage later, so times once).
  • At : cost .

The pattern — multiply by once per stage — is exactly what raising to a power means. is shorthand for " multiplied by itself times."

WHY a power and not, say, (adding)? Because each stage doesn't add a fixed extra cost — it re-scales everything. A production bug isn't "review cost plus a bit"; it's review cost blown up by the whole downstream machine (deploys, users, incident response). Repeated scaling is exponentiation. Using addition here would badly underestimate the pain of late bugs — the exact mistake that makes teams skip review. See Big-O notation for the same "growth shape matters more than the constant" idea in a different setting.

PICTURE. Two curves on the same axes: the straight line "if cost only added" versus the curve "cost multiplies." They start together at and the multiplying curve rockets away. That gap is the danger you're insuring against.

Figure — Code review — what to look for

Step 3 — A change has many bugs, not one

WHAT. One code change (a "diff", the thing you review in Pull requests and Git workflow) rarely holds exactly one bug. Let be the number of hidden bugs it carries — latent meaning "present but not yet noticed."

WHY introduce . We want the cost of reviewing this whole change, so we must total up across all its bugs. is the scale of the risk: a tiny typo-fix might have ; a gnarly 600-line feature might have .

PICTURE. A box labelled "the diff" with several red bug-dots inside it. We're about to ask: of these dots, how many does a reviewer actually catch?

Figure — Code review — what to look for

Step 4 — Reviewers are good, but not perfect: the probability

WHAT. A reviewer doesn't catch every bug — nobody does. So we attach a probability to each bug: the chance the reviewer spots it. is a number between and .

  • → a perfect reviewer catches everything.
  • → the reviewer catches nothing (same as no review).
  • → on average, of every bugs get caught.

WHY probability and not a yes/no? Because "will this reviewer catch this bug?" isn't fixed — it depends on the bug, their focus, the hour. When an outcome is uncertain and we want the average over many tries, probability is the right tool. Multiplying a count by a probability gives an expected count — the long-run average.

So out of bugs:

The term is "the chance of not catching," because caught and not-caught are the only two options and their probabilities must sum to .

PICTURE. The same box of bug-dots, now split by a dashed line: green dots on the "caught at review" side ( of them), red dots leaking out the "escaped to production" side (). A better reviewer slides that dashed line to trap more green.

Figure — Code review — what to look for

Step 5 — Add up the cost with a review

WHAT. Now total the bill when you do review. Two groups of bugs, each with its own price from Step 2:

Term by term:

  • — the caught bugs, each fixed cheaply at review (, so cost ).
  • — the escapees, each hitting production (, so cost ).
  • — the price of the review itself: the reviewer's hours. This is what review costs you.

WHY the "" (expected). Because these are average costs over many changes — probabilities gave us averages, not certainties. just means "expected value," the long-run mean bill.

PICTURE. A stacked bar: a short green block (cheap caught bugs) + a taller amber block (the escapees, expensive) + a thin block on top for . That's your total when you review.

Figure — Code review — what to look for

Step 6 — The cost of skipping review

WHAT. Now the lazy path: no review. With no one reading the diff, every bug sails through to production. That's bugs, each at the price:

WHY it's this simple. No review means : nothing caught, nothing costs the cheap , and there's no reviewer bill . Set in Step 5's formula and it collapses exactly to this — a nice consistency check that our two worlds share the same physics.

PICTURE. One tall amber bar — all bugs at full production price, no green savings block at all. Put it next to Step 5's bar and the comparison is the whole argument.

Figure — Code review — what to look for

Step 7 — When is reviewing worth it? Do the algebra

WHAT. Review pays off exactly when reviewing is cheaper than skipping:

Substitute both:

Now isolate (the one knob you can't easily change — the reviewer's time). Move everything that isn't to the right:

Look at the two terms. . The bracket collapsed because . So:

We factored out the common from both terms, leaving . Done.

WHY this form is the good one. Every symbol on the right is a lever you can name:

  • (riskier change) → right side grows → review pays more.
  • (better reviewer) → right side grows → review pays more.
  • (production failures more brutal) → grows fast → review pays much more.

If your change is trivial () or your reviewer is asleep (), the right side shrinks toward and review stops being worth its time — the formula honestly tells you when not to bother.

PICTURE. A balance scale: left pan holds (reviewer time); right pan holds (the disaster you avoid). When the right pan is heavier, review wins.

Figure — Code review — what to look for

Step 8 — Edge and degenerate cases (never skipped)

Every good derivation must survive its extremes. Check the corners:

Case What it means Right side Verdict
change has no bugs never worth — pure overhead
reviewer catches nothing review is theatre; fix your reviewers
late bugs cost the same as early if lateness is free, don't review
, the real world positive, grows with review pays, more so as rises
perfect reviewer , the max biggest possible payoff

WHY these matter. The row is the secret assumption people forget: review only pays because late bugs are dramatically more expensive than early ones. In a world where a production bug cost the same as a review bug (), the whole practice would be pointless. It's the exponential cost, not review magic, that justifies review. This is also why sprawling PRs are dangerous: past ~200–400 lines a reviewer's effective drops, shrinking the right side even though the true is higher — the worst combination. Split them (see Refactoring and Technical debt for why smaller changes stay reviewable).

PICTURE. The right-hand-side value plotted against , with the zero-crossing marked in amber and the steep climb beyond it. Left of the marker: don't review. Right: review harder as grows.

Figure — Code review — what to look for

The one-picture summary

Everything above, compressed: bugs flow out of a change; a reviewer (probability ) diverts of them into the cheap bin and lets leak into the bin; the balance scale weighs your reviewer time against the disaster avoided .

Figure — Code review — what to look for
Recall Feynman retelling — say it like you're 12 (click to reveal)

Pretend every bug is a leak in a boat. If you find a leak while the boat's still on the trailer (), you dab it with glue — easy. If you find it once you're far out at sea (), you're bailing water in a storm — the same leak, but now it costs a hundred times more, because each stage away from shore multiplies the trouble by about ten ().

A code reviewer is a friend who checks the boat on the trailer. They won't spot every leak — maybe out of () — but every one they catch is a hundred-times-cheaper fix. It costs a bit of their time () to look. The rule for "is it worth it?" is just common sense written in math: if the time to check is less than the disaster you'd otherwise face, check. The more leaks the boat has, the sharper your friend's eyes, and the stormier the open sea, the more obviously worth it that check becomes. And if the boat's a bathtub toy with no leaks and the sea is a puddle where leaks cost nothing? Then don't bother — the math says so too.

Recall

The master inequality, and what makes each side move ::: ; right side grows with more bugs , a better reviewer , and costlier late failures . Why exponent and not addition ::: each stage re-scales the whole downstream cost (deploys, users, incidents), and repeated scaling is exactly exponentiation. Why ::: no review means , so every bug reaches production () at price ; set in the review formula and it collapses to this. The one case where review never pays ::: whenever the right side is — i.e. , or , or (late bugs no more expensive than early ones).


Connections

  • Parent: Code review — what to look for — the priority ladder this cost model justifies.
  • Big-O notation — same lesson: the growth shape () dominates the constants.
  • Pull requests and Git workflow — the diff is the unit whose and we modelled.
  • Unit testing — tests raise effective by catching escapees before production.
  • Technical debt · Refactoring — small changes keep high; giant PRs crush it.
  • SQL injection and input validation — a single missed security bug is a high- escapee.