← All articles

Clean vs. Beautiful: Two Theories of Good Code

Two theories of good code are in circulation and they give opposite verdicts. One says quality is objective, economic and rule-based; the other says it is subjective, plural and sometimes rule-breaking. Both are right about different things — and knowing which lens you are holding is what separates a craftsman from a dogmatist.

Brian Kernighan once wrote a regular-expression matcher in about thirty lines of C. It is routinely held up as one of the most beautiful pieces of code ever written, and it deserves the reputation.

Now put it through a code review that applies the clean-code rules faithfully. Is every routine pretty much what you expected? Is it obvious to a casual reader? Almost certainly not. A junior would need an afternoon and a whiteboard.

Two defensible verdicts. One piece of code. Somebody has to be wrong.

Nobody is. There are two theories of code quality in circulation, they answer different questions, and most arguments about code quality are really arguments between two people who each think their question is the only one.

Theory A: clean is an economic argument

The case for clean code is not aesthetic at all. It is about money.

Code is read far more often than it is written — the ratio usually cited is well over ten to one, and nobody who has maintained a long-lived codebase argues with the direction of it. So the dominant cost of software is not typing it, it is understanding and changing what already exists. Everything downstream follows from that one observation:

The only way to go fast, over any horizon longer than a sprint, is to keep the code cheap to change.

Cleanliness is a velocity strategy, not a virtue tax. That framing is what makes the rules arguable rather than sacred: small functions, meaningful names, no duplication, tests. Each is a claim that this costs less over the life of the code, and each can in principle be checked.

It is telling that the term resists direct definition even from the people who champion it. What we have instead is a set of practitioners circling it from different sides — Bjarne Stroustrup on code that "does one thing well," Grady Booch on code that "reads like well-written prose," Ward Cunningham on code where "each routine you read turns out to be pretty much what you expected," Michael Feathers on code that "looks like it was written by someone who cares." No single definition, but a convergence — and the convergence is the argument.

Theory B: beautiful is an aesthetic argument

Ask thirty expert programmers to name the most beautiful code they have ever read, and you will get thirty different answers.

That is not a failure of the question. It is the finding.

Beauty in code is plural and subjective in a way cleanliness deliberately is not. What recurs across those answers are facets rather than rules: concision that only becomes available once you truly understand the problem, an abstraction so well-chosen it unifies a whole system, symmetry where there is nothing left to add and nothing left to remove. Elliotte Rusty Harold ranks it "Correct, Beautiful, Fast — in that order." Yukihiro Matsumoto describes code written to be read, like an essay.

And then there is Michael Feathers — the same practitioner quoted above on code that looks like someone cared — who went on to write an essay titled "Beauty Through Fragility."

Sit with that. One of the people whose definition anchors the clean-code case also argued that some beauty is inseparable from fragility. That is not a contradiction to explain away. It is the whole tension, in one byline.

Where they agree (which is most of the time)

Both prize simplicity, expressiveness, and the absence of duplication. Both hold that code communicates to humans first. Both would reject a 400-line method with four levels of nesting and a variable called tmp2.

For the overwhelming majority of code you will write this year, the two lenses give the same verdict, and the argument is academic. Which is exactly why it is worth knowing where they part — those are the cases where you will actually be confused.

Where they diverge

Count the set bits in a 32-bit integer:

// Beautiful: no branches, no loop. The answer falls out of the bit patterns.
function popcount(x: number): number {
  x = x - ((x >>> 1) & 0x55555555);
  x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
  x = (x + (x >>> 4)) & 0x0f0f0f0f;
  return Math.imul(x, 0x01010101) >>> 24;
}
// Clean: obvious to a casual reader on the first pass.
function popcount(x: number): number {
  let count = 0;
  for (let bit = 0; bit < 32; bit += 1) {
    if ((x >>> bit) & 1) count += 1;
  }
  return count;
}

Both are correct. The first is genuinely beautiful — those magic constants are a divide-and-conquer sum hiding in plain sight, and once you see it you cannot unsee it. It is also, by the clean-code test, not obvious to a casual reader. The second is honest, boring, and runs thirty-two iterations where the first runs five operations — in a loop that virtually no program actually cares about.

So which is better?

The question is malformed. Better for what, and for whom next?

In a hot path inside a bit-manipulation library maintained by people who think in bit patterns, the first one is correct and the second is amateurish. In the billing service, the first is a landmine you have left for someone at 2am and the second is a kindness. Same two functions. The judgement inverts on context that is nowhere in the code.

This is where "fragile but beautiful" stops being a paradox and becomes a category. Whether it is a virtue or a warning depends entirely on who has to change it next — and that is a fact about your team, not about the code.

The failure mode on each side

The pursuit of beauty tips into cleverness: code that impresses its author and baffles its maintainer. The author felt the click of insight; the reader gets a puzzle with no clue attached. That failure is real and common, and it is precisely what the clean-code rules exist to prevent.

The pursuit of cleanliness tips into dogma: rules applied as law, long after anyone remembers the cost argument underneath. A four-line function split into three because "functions should be small," a name lengthened to calculateTotalOrderAmountValue because longer is clearer, an abstraction introduced to satisfy a principle nobody asked about. The rules were compression of an economic argument. Applied without the argument, they are cargo cult.

There is an asymmetry worth naming. Cleanliness gives actionable feedback — "reduce this duplication" is a thing a reviewer can say and an author can do. Beauty does not: "make it more elegant" is not actionable feedback. That asymmetry is why rules win arguments and why they get over-applied. The lens that fits on a checklist is not thereby the more correct one.

The synthesis

Treat them as different altitudes rather than competing theories:

  • Clean is the floor. Correctness, tests, the next reader. You do not go below it, and you do not need taste to enforce it. If you cannot say who will read this and what they will need, you are not ready to be clever.
  • Beauty is the ceiling. The thing you reach for once the floor holds. It is developed taste, not a rule, and taste is what guides the thousands of small decisions no checklist covers.
  • Good enough governs how far up you climb. Quality is a requirements decision. Not every module deserves your best work, and pretending otherwise is its own waste.

Dogmatism, in both directions, is mistaking one of these for an absolute. The rule-follower who cannot say why the rule exists, and the aesthete who ships a beautiful thing nobody else can maintain, are making the same error in opposite directions.

There is one more thing worth saying that has nothing to do with either theory. As Greg Wilson has observed, programmers mostly look at each other's work only when there is a bug to fix. Taste is developed by reading good code on purpose, and almost nobody does it. That is a bigger gap in most engineers' practice than any rule they are getting wrong.

The takeaway

One question, in every code review you give or receive:

Am I applying a rule to reduce cost, or enforcing a taste as if it were a cost?

Both are legitimate. They are not the same act, and they do not carry the same authority. "This duplication will cost us on the next change" is an argument. "I find this cleaner" is a preference — worth saying, worth weighing, and worth labelling as what it is.

Say which one you are doing. The review gets shorter, and it stops being an argument about who has better taste.