jyn opens by rejecting their own answer. After a talk about a bug that took nine months to debug, a friend asked how to build tools so those epics would not be necessary, and they said: prioritize simplicity. The rest of the essay is an explanation of why that answer was empty — “simple” is usually used as a synonym for “small,” and small is a size, not a design property.
The proof is two programs that count word frequencies. A five-stage Unix pipeline is small. A Clojure program is longer. Then the requirement changes slightly — print the counts in original file order — and the pipeline turns into temp files, joins, and opaque sorts, while the Clojure version grows by a few lines.
That is because the pipeline was small but not simple:
- Simplicity comes from Hickey’s root, sim-plex: one braid. Its opposite is coupling, not size — so “write programs that do one thing and do it well” is really a claim about size, not simplicity.
- The braid is
sort | uniq --count. Unix has no equivalent offrequencies, souniqneeds adjacent repeats and aggregation gets tied to ordering. That tie is exactly what makes the reordering change expensive. - Large is not coupled either. Google Drive for Desktop depends on platform file watchers, a streaming sync client, and conflict resolution — and to the user it is simple: pick a folder, stop thinking about it.
- In Rust, a struct couples type-checking to a fixed data representation. You get known-present fields and lose runtime iteration. Clojure decouples them: schema annotations are runtime data, checked by a library, inspectable enough to generate your own docs. Typed Racket gets the split at compile time instead.
- Being small is a resource strategy — a PDP-11, two hours a month, a feature nobody will fund. Being simple is not optional. There is very little advantage to introducing coupling.
The uncomfortable part: decoupling usually means writing the hard thing. SQL and CSS are decoupled because someone spent centuries of person-years on the engines underneath. And the payoff can look backwards — jyn’s coverage pipeline ended up larger after the fix, and simpler, because the hidden dependencies in the dataflow graph were gone.
Worth asking of your own system: what is braided together here that does not need to be?