The End of "Clean Code" (Code as a Compile Target)
I still think clean systems are how codebases grow, especially under AI velocity. The literary version of clean is becoming a poor use of scarce human attention.
I loved writing clean code. I still think it is how a system grows without collapsing, especially now that agents can emit a week’s work before lunch. What I am having to admit is that the version of “clean” we argued about in PRs is becoming a worse use of a scarce human.
I Did Not Fall Out of Love With It
I liked the craft: a module with one job, a name that carried the domain, and a seam you could extend without holding the whole graph in your head. That was not merely aesthetics for me. It was how you kept a codebase from turning into a swamp as it grew.
I still believe that, and AI velocity makes it more true rather than less. If a worker can rewrite a folder before you finish coffee, the only thing standing between you and a steadily rotting system is structure: isolation, tests, and interfaces that mean something. Shrugging because nobody reads the code anyway is not agentic engineering; it is giving up the one lever you still have.
What is becoming less pragmatic is the other half of the old religion: treating formatting as morality, extracting abstractions on sight, and spending a senior engineer’s hour debating whether the agent should have used map. Those fights assumed a human would live in the file. On plenty of days now, the next reader is a model working from an allowlist. Spending your attention on small stylistic choices is how you look busy while the factory produces the wrong architecture at scale.
The Literature Version Is What Got Expensive
For twenty years, we fused two ideas and called both “clean.” One was architecture: boundaries, clear responsibilities, and tests you could trust. The other treated code as literature, focusing on line length, poetic names, and linters that failed the build over a trailing comma. Style guides became identity, and a PR that “felt messy” counted as debt even when it was correct.
The literary half does not compound at agent speed. A transformer does not share your feelings about switch versus if; it will emit both in the same afternoon and still pass the suite. You used to open 200 lines and argue about elegance. Now a worker can generate a few thousand lines that already satisfy the checks. Spending four hours on whether they “read well” is a ritual from a job where typing was the bottleneck.
I am disappointed about that. I wanted the daily act of making code beautiful to remain high-leverage work, but it cannot at the volume we are generating. The leverage moved up a level. You still need clean systems, but you cannot personally hand-sand every generated surface while also keeping the factory honest.
Implementation Is Starting to Look Like a Compile Target
TypeScript, Python, and Rust used to sit at the top of the ladder, where intent became executable. The ladder has moved. On many days, those languages are now the compile target of a factory that begins with a spec.
Nobody files a style nit against gcc’s jump instructions. The binary is allowed to be ugly because its job is to run. Verified agent output is drifting into the same category. If the code implements the checklist, respects the boundaries, and survives the suite, arguing about register allocation with the compiler is not a good use of senior engineers.
That is not permission to merge garbage. A tax helper with copy-pasted branches can be acceptable if it is isolated, named well enough to find, and pinned down by tests. It is not acceptable if it smears policy across three layers because “the agent got it working.” An agentic engineer leaves the isolated, tested module alone and spends the hour inspecting a seam that could couple two lifecycles. A slop artist leaves everything alone, including the fuse.
SOLID Was Never About Pretty
Ugly and unstructured are cousins, not twins. You can ship a verbose disaster or a twelve-line miracle that nobody can safely regenerate.
SOLID is having a second life because agents complete patterns, and your architecture provides the pattern. When business rules are smeared across the database, the API, and a React page, the model will invent shortcuts. A payment change might write a vendor secret into the mailer simply because both files mention “customer.” The model did what it was trained to do; you failed to give it walls.
If billing can change without authentication knowing, an agent can work safely in billing. If everything is one clever graph, every prompt creates a blast radius. Dependency inversion used to be a kindness to the next reader; now it also keeps a worker from hard-coding a vendor into the wrong layer while it is “just wiring things up.” That is still clean code, but it is the kind that lets a system grow under velocity rather than the kind that wins a screenshot.
DRY Is Where the Craft Turns Against You
I believed in DRY, and I still believe you should not encode the same business rule in two places. The failure mode was always premature extraction: three similar lines become a helper, the helper becomes a package nobody may touch, and two features that only happened to look alike now share a fate.
Write it twice and wait for the third copy. The rule of three was always the mature version of DRY, and agents make it mandatory because they reuse code aggressively. Ask one to “fix reporting” and it may follow a shared utility into checkout. Friday pages come from false duplication: two shapes that looked identical on Tuesday but represented different business concepts by Thursday.
A careful engineer extracts when the shared meaning is real and tested. A slop artist never extracts, while a literary maximalist extracts because repetition offends the eye. The sustainable middle path keeps logic local and easy to find until the coupling cost becomes obvious, then introduces a seam with a test that pins down the shared meaning.
Isolation Is How Clean Code Survives an Author That Can Rewrite a Folder
The scarce design question is no longer reuse; it is how far a bad edit can travel.
A person mistypes a line in a function; an agent can rewrite an entire directory. If the tax module is hermetic, a hallucinated rate stays there. If tax logic is injected through a bag of services into inventory and sessions, the hallucination travels. The risk profile changed when the author became faster than the reviewer could finish a cup of coffee.
Bulkheads can look ugly to someone raised on elegant graphs: explicit boundaries, duplicated types, and boring modules that do not share a god object. But you are building compartments so one flooded room does not sink the ship. The 2018 instinct was to call duplication a smell. The 2026 instinct, if you still care about growing the system safely, is to ask whether a shared object has become a fuse. That is still craft, even if it no longer looks like a pretty PR.
Spend the Human on the Spec the Machine Cannot Wriggle Out Of
If a chunk of implementation is disposable, the constraints around it cannot be. The suite is the spec the worker cannot dodge. Weak tests produce green garbage at industrial speed, while strong tests tell you the compile target is correct without forcing you to live in every file. TDD stops being a personality and becomes the constraint that lets you treat some implementation as a byproduct. You already understand this relationship from compilers: you do not inspect the assembly unless the tests lie.
Spend the senior hour on edge cases, invariants, and boundaries rather than whether the agent used reduce. If you cannot express what “done” looks like in a check, you do not have a compile target. You have a vibe, and vibes do not scale steadily.
I do miss spending my time and energy on writing great code because it felt a bit like art. But “clean” now describes a system that can absorb a Thursday agent pass without paging you on Friday. Formatting can be a machine problem; structure cannot. People who confuse those two will drown either in slop or in bikesheds. I would rather keep the part I always loved: a system that can still grow.