...
Back

The Skill That Actually Atrophies

Three different posts this week worried that LLMs are making programmers worse. They are mostly worrying about the wrong skill. Writing code was never the bottleneck — and the thing that replaces it is harder, not easier.

The Skill That Actually Atrophies

The Skill That Actually Atrophies 🧠

Three posts in one week, from three different communities: learning to program in the age of LLMs, keeping the love for coding, the quiet cognitive atrophy of the modern engineer. The genre is now large enough to have conventions.

The worry is usually framed as: if a model writes the code, you never learn to write the code. That framing is tidy and I think it is aimed at the wrong faculty, because producing syntax was never the expensive part of this job.


What does not atrophy, because it never carried the weight

Recalling that Python slices are half-open, that strcpy does not bound, that the flag is -exec and terminates with \;. This is lookup. It was a reference-manual operation before it was a model operation, and moving it from one to the other changes the latency, not the cognition.

Typing out a loop. Knowing the shape of a for-comprehension. Remembering the argument order of a standard-library call. These things feel like programming because they are what programming looks like from outside, and they are the part a model most obviously displaces. They are also the part that was already the least of it.

If your mental model of expertise is "knows the incantations," then yes, that is being eroded, and it mattered less than you thought.


What actually erodes

Something more specific and much harder to notice: the habit of building a causal model before acting.

Watch the difference in how a hard bug gets approached. The unassisted path is slow and structured — form a hypothesis about what could produce this behaviour, find the cheapest experiment that discriminates between hypotheses, run it, update. You get better at this by doing it, and you get better specifically because it is uncomfortable.

The assisted path has a shortcut that feels like progress: describe the symptom, get a plausible cause, apply the suggested fix, see if the symptom goes away. When it works, you have a fixed bug and no model. When it does not work, you describe the new symptom and repeat. This converges surprisingly often, which is exactly what makes it corrosive — the feedback signal rewards the loop.

The cost is invisible until you hit a bug where the plausible cause is wrong. Then you discover you have been navigating by a map someone else drew, and you cannot tell which parts of it were guesses.

I can give a concrete example from our own work this month. A macOS app passed notarization, passed codesign --verify, passed Gatekeeper, and was killed by the kernel the moment it launched. Every plausible cause — corrupted signature, bad certificate, quarantine attribute — was wrong. The actual cause was a restricted entitlement with no provisioning profile to authorise it, and the only way to get there was to stop guessing, read the kernel log, and then build a probe that isolated one variable: sign a trivial binary with only that entitlement and see whether it runs.

That last step is the skill. Not knowing the answer — constructing the experiment that distinguishes between answers.


The other thing that erodes: reading

The second casualty is less discussed and probably larger. As the proportion of code you did not write goes up, the proportion you review goes up with it. Reviewing unfamiliar code well is a distinct skill, and most of us were never formally taught it because most of us wrote most of our own code.

It is also the skill under the most pressure, because reviewing is slow and accepting is fast, and the difference in immediate reward is enormous. A diff that looks right and passes tests is very hard to argue with in the moment.

The specific failure is not "the model wrote a bug." It is "the model wrote something that works for the case I was thinking about," and the case you were not thinking about is precisely the one you needed a second mind for.


A practice that seems to help

Not abstinence. Abstinence arguments lose, because the productivity difference is real and people are not going to give it up for a principle.

What has worked for us is narrower: maintain a standard of explanation, not of authorship.

Before code you did not write goes in, you should be able to say — out loud, to another person — what it does, why this approach rather than an obvious alternative, and what would have to be true for it to be wrong. Not a summary of the diff. A causal account.

If you cannot produce that account, you have not reviewed the code, you have witnessed it. The remedy is not to write it yourself; it is to keep asking until you can explain it, which is a conversation the model is well suited to and which most people skip because the code already works.

This has a useful property: it scales with stakes. For a throwaway script, the standard is trivially met and costs nothing. For the thing that touches production data, meeting it is most of the work, which is the correct distribution of effort and the one that pure speed inverts.


The part that is genuinely better

It is worth saying plainly, because the genre tends not to.

The floor has moved. A person with a clear idea and no professional training can now build something that works, and a large fraction of the historical gatekeeping in this field was about incantations rather than thinking. Losing that gate is good.

And for experienced people, the tedious middle — the boilerplate, the fifth CRUD endpoint, the config file in a syntax you use twice a year — genuinely compresses. Compression there is not cognitive decline; it is the removal of work that was never teaching you anything.

The thing to defend is narrower than "coding." It is the discipline of knowing why something works before you depend on it. That was always the job. It is now the whole job, which is a promotion disguised as a threat.