Code Is Read Far More Than It Is Written

Every line of code is written once and read dozens of times. The economics are lopsided, and once you see them, you never optimize for the writer again.

1 writes10 read
Tom
Academic Professor of Software Heuristics
Dec 4, 2025
6 min read

Years ago, a student of mine solved an assignment in a single line. It was a gorgeous line — a reduce inside a comprehension inside a ternary, the kind of thing you frame and hang on the wall. He was beaming. So I asked him to explain it to the class, and I watched him spend four minutes re-deriving his own logic, out loud, with increasing alarm. He had written it twenty hours earlier.

That afternoon taught him — and re-taught me — the most lopsided economic fact in our profession: code is written once and read many, many times. The writer pays a cost once. Every future reader pays a cost forever. And "future readers" includes the most important stranger you will ever work with: yourself, six months from now, at 11 p.m., during an incident.

The ledger nobody keeps

We are meticulous about some costs. We benchmark hot loops. We argue about milliseconds in the request path. But almost nobody keeps a ledger of reading costs — the accumulated minutes that every engineer who touches a file spends reconstructing what it does and why.

Think about the lifecycle of a typical line of production code. Someone writes it. A reviewer reads it. A teammate reads it while building the adjacent feature. Someone reads it during a debugging session, then again during the postmortem. A new hire reads it while onboarding. An AI assistant ingests it as context and — here's the modern twist — reproduces its style in a hundred new places. The write happened once. The reads never stop.

Hal Abelson and Gerald Sussman put it best in the preface to Structure and Interpretation of Computer Programs: "Programs must be written for people to read, and only incidentally for machines to execute." That sentence is over forty years old and it has only become more true, because our systems have grown while our working memory has not.

Clever is a cost center

I want to be precise here, because "don't be clever" is often heard as "don't be smart," and that's not the lesson. Cleverness in the design — a data structure that makes a whole class of bugs impossible, an invariant that simplifies everything downstream — is wonderful. What's expensive is cleverness in the expression: compressed logic, exploited language trivia, implicit behavior that only makes sense if you were present at the moment of writing.

Brian Kernighan gave us the canonical warning: "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." I'd extend the professor's corollary: reviewing clever code is also harder than writing it, and reviewing is where most of your team's collective judgment gets applied. Clever code doesn't just cost you debugging time later; it degrades the quality of the review it receives today, because a reviewer who is spending all their attention on decoding syntax has none left for questioning the design.

There's a status economy at play, too, and it's worth naming. Clever code feels like a display of skill. But in a healthy team, the flex is inverted: the most senior engineers I know write the most boring-looking code, because they've internalized that boring is what mastery looks like when it's optimizing for the right variable.

Readability as compound interest

Here is where the economics get interesting. Readability doesn't just save time linearly — it compounds.

Readable code gets reviewed more thoroughly, so fewer bugs land. Fewer bugs mean fewer emergency reads under pressure — and code read under pressure is code modified under pressure, which is how hacks are born. Readable code invites small improvements, because the cost of understanding it is low enough that a passing engineer will actually fix the thing they noticed. Unreadable code repels those same improvements; people route around it, adding shims and wrappers, and the module calcifies into what teams eventually call "the haunted forest" — the place nobody goes.

Each effect feeds the next. A codebase that is 10% easier to read isn't 10% cheaper to maintain; over years and dozens of contributors, the gap widens the way compound interest widens. Legibility is the interest rate on your entire codebase.

And there's a new compounding channel worth taking seriously: your code is now training material for your tools. AI assistants complete code in the style of the surrounding file. Clear names, consistent patterns, and honest structure get amplified; muddle gets amplified too. Your codebase has become a prompt. Write it accordingly.

What optimizing for the reader actually looks like

Let me make this concrete, because "write readable code" is advice the way "be healthy" is advice.

Name the intermediate ideas. The one-liner my student wrote wasn't wrong; it was unlabeled. Three well-named variables would have turned four minutes of decoding into ten seconds of reading:

eligible = [u for u in users if u.verified and not u.suspended]
by_tenure = sorted(eligible, key=lambda u: u.joined_at)
return by_tenure[:seats_available]

Nothing clever happened here. That's the point. The names carry the reasoning so the reader doesn't have to.

Write for the reader's questions, not the writer's journey. Readers arrive asking "what does this do and can I trust it?" — not "what order did the author think of things in?" Structure functions so the headline behavior is visible first and the exceptional cases are clearly fenced off.

Spend comments on why, not what. The code already says what. The invariant you're protecting, the vendor quirk you're working around, the alternative you rejected — that context lives nowhere else, and it's exactly what the 11 p.m. reader is desperate for.

Let the review be the test. If your reviewer asks "wait, what does this part do?", the correct response is rarely a reply comment. It's a rename, an extraction, or a comment in the code — because the next reader will have the same question and won't have you on hand to answer it.

Homework

A few exercises, in the spirit of the seminar:

  1. Reread something you wrote six months ago. Time yourself. Wherever you stumble, your past self was optimizing for the writer. Fix one of those spots.
  2. In your next PR, count the questions. Every reviewer question about mechanics (not design) is a readability defect. Fix it in the code, not in the comment thread.
  3. Try the one-week rule. Before merging something you're proud of for its compactness, ask: will I be able to explain this, cold, in a week? If you hesitate, expand it.
  4. Praise boring code out loud. Culture follows what gets celebrated. When a teammate ships something so clear it looks easy, say so — in the review, where everyone can see it.

The machine will happily execute anything. The humans are the ones you're writing for — and they, unlike the machine, are billing you by the minute.

readabilitymaintainabilitycode-revieweconomics
Written by
Tom
Academic Professor of Software Heuristics · Firetrail review team
More Principles