technology

The Machine Kept the Code

I own a shelf of C++ books that never quite paid off. In my twenties I worked through them with a kind of stubborn resentment, because I came out of visual communication and what I actually wanted was interaction. Something on the screen that responded when you moved the mouse, and responded the way I had imagined it would. Code was the toll I paid to get there. I would spend an evening chasing a null pointer dangling somewhere I hadn’t thought to look, and the thing still didn’t move.

I was mediocre at it. Not in the way people say that on LinkedIn, as a setup for a reveal. I read the books and kept shipping the same class of bug for years.

Last Christmas I was sick in bed with an iPad and built a pen plotter toolchain in Rust, a language I can follow at a beginner-to-intermediate level and had never built anything serious in. Twelve thousand lines across half a dozen crates, written over about twelve days. I described what I wanted, Claude wrote it, I read the diffs on GitHub in a browser without ever compiling anything, and eventually the AxiDraw drew a clean rectangle on paper. I was as happy about that rectangle as I have been about any piece of software.

At the time I called it a holiday experiment. Six months later I think it was the shape of my job arriving early, and I mostly missed it while it was happening. The part I didn’t write down: I stopped reading the code because it was better than mine.

Every generation hands the layer below to a machine

Nobody writes machine code anymore, and nobody has in a long time. The assembler took that level, C wrapped the assembler, PHP wrapped all of it, and each generation handed the layer below to a machine and stopped looking down. The pattern is old and boring and it has finally reached the rung I personally stood on. What I used to call “our code” is now the thing the agent emits.

John Maeda made this argument recently and made it well. His version: coding agents are moving programming up a level of abstraction the way compilers once did, so the interesting question is whether we can bring enough judgment and clarity to the layer above. He reaches back to SICP, the MIT course built entirely around abstraction, and to Dijkstra, who watched high-level languages arrive and noticed that programmers immediately began producing incomprehensible code at a grander scale. Compiler slop. Nothing new under the sun.

The essay is titled Abstraction Is All You Need, which is a good joke and, I think, one word off.

Scaffolding covered in protective netting with visible diagonal bracing patterns.
The building is still there. You just can't see it.

Complexity doesn’t move up with you

Maeda says abstraction “does not eliminate difficulty,” it relocates it upward, from mechanical execution to judgment and responsibility. That is a comforting story, because difficulty is effort, and effort can be redirected somewhere nobler. You climb, the hard work climbs with you, everybody wins.

But the thing abstraction hides is complexity, and complexity doesn’t relocate. It stays exactly where it was, with a lid on it.

My plotter taught me this on December 31st. The AxiDraw moves in relative commands: left ten millimetres, down five. My motion planner was calculating those distances slightly differently than the hardware expected, and the errors accumulated. Everything looked fine for a few hundred strokes. Then the lines began to overlap and the map of Hamburg I was drawing slid quietly off itself. Fixing it meant going down into stepper positions, junction deviation and trapezoidal velocity profiles, which is precisely the layer the abstraction had promised I would never need to visit.

The complexity didn’t move up with me. It sat in the motion planner and waited three hundred strokes to introduce itself.

Joel Spolsky wrote the definitive version of this in 2002, long before any of us were prompting anything: every non-trivial abstraction leaks. You stay dry for a while and then a drop lands on your keyboard. Abstraction is a bet that the hidden layer stays quiet. It ships the complexity forward in time and hands the bill to a version of you who has forgotten where it lives.

The artifact moved

So if I’m not reading the code, and the complexity is still down there, what exactly am I doing all day.

I write specs. I argue about them with the AI until the intent is actually sharp. The agent builds. I run the thing and judge whether it behaves the way I meant, which for a plotter means watching a pen move across paper. Then I curate what we learned into memory files, decision records, a slowly accumulating graph of what this application is and why it is that way.

That last pile is what I read. Not the code. The specs, the decisions, the record of what was tried and rejected. When I come back to a project after four weeks, or when a colleague joins, or when a fresh agent starts a session with no idea what any of this is for, the markdown is the thing that carries the knowledge across. It has left my head and it lives in files, available to me, to my team, and to the machines.

For roughly seventy years the source file was the one document that humans and machines both read. It has split in two. The machine kept the code. We kept the prose.

Which is why I think Maeda picks the wrong ancestor for his argument. He cites SICP, and SICP’s founding principle is that programs get written for people to read and only incidentally for machines to run. An essay blessing code that nobody reads is a strange place to plant that flag. The principle survives, though. It just moved off the code and onto the markdown. The writing-for-humans layer is still sacred. It’s simply somewhere else now, and the sooner we treat it as the actual artifact, the sooner we start maintaining it like one.

The drift bug makes the case better than the theory does. That bug is invisible in code I don’t read. It is perfectly visible in a decision record that says we track actual stepper position, because relative commands accumulate error. The markdown is where the hidden complexity comes back up for air.

This shows up at work more than it ever did in bed with a plotter. A spec in plain language can be read by the designer, the project manager, the client who has to approve the thing. None of them was ever going to review a pull request. All of them can argue with a paragraph describing what the system is supposed to do, and at Factorial they now do. They understand the concepts perfectly well. The artifact has finally arrived in a format that holds concepts instead of syntax.

Code had a readership of three people on the team. The prose has everybody.

Two things that could be wrong

I want to be honest about where this could fall apart, because I’ve watched enough of these arguments get made triumphantly by people with nothing at stake.

The first: I can get away with not reading the code because I read the result expertly. Twenty years of computational design means I know what a correct plot looks like, I recognise a wrong curve immediately, and the codebase had comprehensive tests and a well-documented problem domain to lean on. Someone without that eye isn’t standing one level up. They’re standing in the dark holding a diff they can’t evaluate. Judgment of behaviour is the only thing keeping a human on the top rung at all, and it isn’t evenly distributed.

The second is older and sharper. In 1985 Peter Naur argued that the real artifact of programming was never the source code, it was the theory in the programmer’s head: the mental model of why the system is shaped this way. Code was only ever a shadow of that theory, and when the theory dies the program is dead even if the source compiles fine. My whole answer to Naur is that the theory now lives in the files. Externalised, queryable, shared with my team and my agents.

That is a genuine bet and I don’t know yet whether it holds. A spec is not a mental model. A knowledge graph is a map, and the map has never been the territory. An auto-generated pile of decision records that nobody tends is just slop wearing a spec’s clothes. Everything I’m describing works only as long as somebody curates the prose with the care we used to reserve for the code.

Snow-covered ground with tire and footprint impressions alongside a metal barrier.
Everyone who walked here has left. The tracks are the document.

Nostalgia for a reader who already left

Which brings me back to slop, the word that started all of this.

Slop is a reader’s complaint. You can only call something slop if you were going to read it and it let you down. Code that no human reads can’t be slop. It can only fail to run, and that failure shows up in the behaviour, on the paper, in the drift.

What can be slop now is the spec. The lazy decision record. The memory file nobody pruned. That’s the layer we actually read, and that’s where the rot will do damage.

I never wanted to read code. I wanted things to move. They move now, and what is left on my desk is prose: specs, decisions, a memory file I prune on Fridays. The reader everybody is worried about didn’t disappear. He switched documents.

What sits in those documents is a surrogate for thinking I used to do in my head, and I notice that I trust it more than I trust my memory. Markdown is a strange resting place for that. Plain text in a folder, a format older than most of my career, holding the theory of a system a machine wrote and nobody reads.

It won’t stay there. Every level in this piece looked permanent to the people standing on it, right up until somebody handed it down to a machine and climbed. I have no idea what sits above prose. I would like to still be the one reading it.