While I'm content with my definition of 'good code', I don't think I've paid enough attention to the motivation behind all this. I said at the top of the explanation that the best way to go about understanding a piece of code is to go and ask the people what wrote it, and then extruded this whole framework of theories and texts and consistencies on the assumption that the original authors weren't and would never be available to ask.
Most of the time in my experience, the original author is me; specifically the 'me' of some months prior. That person had their own programs, their own ideas, their own hopes and dreams, their own theories; they likely intended to pass these theories on to me, but I can't find them. Like all my inextricably human processes, my program theories are in my head, and there's little purchase to be found in my head. My theories will therefore rot; they are survived only by code, and perhaps a sprinkling of useless comments devoid of all meaning as are snippets of sentences caught as one flicks through radio stations (or a TikTok feed; who cares). Code rots too, but does so far less quickly than its parent theory will (and yet far more quickly than most people ever seem to realise). I do myself a favour by writing good code even for an audience of just me, because 'just me' is some clueless sap half a year from now who knows and cares for nothing in the way I do. He will doubt my genius, and I doomed to write code for him.
As it happens, this practice carries well into industry, where a confluence of ignorance and arrogance produces myriad codebases that outlive the contracts of their authors, who themselves may be neither ignorant nor arrogant. When a worker leaves a company they necessarily take all their theories with them, and when a worker is overworked and undervalued their theories will rot with unmatched vim. However, a company with a solid density of good programmers will still produce good code, so this catalysed amnesia isn't as destructive to the programs as it is to the workers. A good new hire may be denied the opportunity to theory-build with peers, but enough good code affords a consistent uncompression, and that may be all they need to be productive. Good programmers are incentivised to write good code for their own sake: it's a more rewarding, fulfilling experience, and it makes their coworkers like them more. It makes their job easier in the long run; it also makes them more replaceable. There is a serious tension here between the personal desire to do a good job and the vulnerability exposed by doing so, and thus begat a whole paradigm of skills related to 'irreplaceability' and 'self-promotion' and 'generalism' and other things that fuck me right off.
The nub here is that more good code affords managers more fungibility of their programmers, which is great news for a software development industry has been optimising for fungibility of developers for a long while in a process described beautifully in Baldur Bjarnason's article on "the labour arbitrage theory of dev tool popularity". The focus there is less on code than it is on frameworks, specifically those like Rails and React (yes; it's a framework; stop wasting my time and yours; this is why we have the duck test) which allow incredible adoption speed with speedy compression and uncompression, but what of the corresponding theories? I believe these frameworks are very good at shaping and guiding the theory-building process, but I claim that their guidance is often unproductive or incomplete. It's very easy to do a small fix in a React application with minimal theory-building because of how trivially the immediate code uncompresses into something; it's harder to claim the theory is consistent because relatively little work is required to verify it.
Another way to put this borrows from Iris Meredith's framework on the relative depths of different languages/frameworks: React, by virtue of being a shallow framework, encourages "shallow theory-building" where code trivially uncompresses into a theory that's consistent enough locally but woefully inconsistent with respect to the codebase as a whole. This allows programmers to write "good code" from one perspective and still end up with sprawling, decayed programs that keep on hobbling along despite the physical impossibility of it all; it also allows those programmers to continue writing React code without their brains' regressing to lesser soups.
The respite for good programmers used to be that these chaoses of code would find themselves root-bound eventually; progress would stop and panic would set in; and the pause wouldn't stop the flowers for wilting and the leaves from yellowing. Good programmers would eventually be required, and their good theories would be one of multiple necessary medicines for recovery. All of this, however, relied on the idea that the dying plant was worth saving; or, more accurately, that replacing it was going to be more work than looking after it.
Then LLMs arrived, and all the awful people of the world wondered if, finally, the cost of a new codebase extruded by some bro with a chatbox would compete with the costs of talented workers who know how hard the work really is. My opinion is that no, of course it won't, but we're still firmly in the 'sowing' stage of this grand, soulless, bafflingly cruel experiment, and we are doomed to work out how to be good programmers in the meantime. LLMs that read and write code are necessarily doing the compression and uncompression of their own theories, but their theories are not those of programmers. The programmers themselves may need no theories at all beyond whatever allows them to communicate with the LLMs and verify output, and these will be very shallow theories indeed. What it means for an LLM to 'uncompress' code may be wildly different to what it means for a human to do the same, and so there are no grounds to assume any substantial overlap between "good code" for LLMs and "good code" for humans. The notion of "good code" becomes wildly confused, and this can only mean incredible new records for rates of program decay. The dream outcomes here for LLM promoter types are that the increased rates of program decay are offset by faster and cheaper uncompression; and that increased rates of program collapse are offset by faster and cheaper rewrites.
I was only ever vaguely aware of the era where an expensive good like a washing machine was something you kept for as long as you could, and that meant needing to repair it sometimes (or, by the noughties, needing to have it repaired by an expert). Replacement was an option, but it was a more expensive and time-consuming option, considered earnestly only after an expert had given the signal; where I grew up the signal was delivered by removing gloves, standing up, exhaling some vocable, and lightly cocking your head; perfunctory conversation would follow but the crucial information had been communicated far more precisely than English allows. Whatever its flaws, I prefer that system to the one I have now where to call out a repair costs half as much as a new machine, and the machines are everywhere, and they're mostly crap. And yet, despite being mostly crap they're also so much more complicated now, and such complication only frustrates the task of repair, so repair becomes more and more impractical with time too.
I worry that the same change is now due for software. We now have a tool that spits out code at an incredible clip, so the market is flooded with software. We know that this software is harder to repair than it was before, so the experts will become less useful and less prevalent. Finally, we know that the ubiquity of software makes replacement relatively cheaper, so the demand for experts will also decline. An industry of repair workers will be ravaged, and the benefit received in exchange is worse software for all. History also tells us we won't save any money either. I don't expect this change to be sustainable at all, but the changes to washing machine repair aren't sustainable either: collapse takes time, and will do damage during all of that time.
I worry as well that all of this reads as though we programmers "did this to ourselves" by rapidly adopting shallow frameworks, building shallow theories, writing code that at best sort of runs and sort of works, and other petty crimes of that sort. I find that conclusion neither true nor helpful in the macro sense (the real crime was the lack of solidarity common to so many of them — you must join at least one union to ride!) but it might be helpful for an individual (or perhaps a tech team) to ponder whether it's true for them; to ponder why their code should be good. I know why I want my code to be good, and I know what good code is for me, and those juicy crumpets of knowledge reveal "agentic programming" to be a very blunt tool indeed for my purposes. But a tech team may decide, rightly or wrongly, or just neutrally, that their code doesn't actually need to be all that good; that there's a limit to how much they're willing to invest given other competing priorities. And that's fine, provided everyone involved knows where the quality bar is today and where it ought to be tomorrow; but what if they don't know? What good is an LLM to a programmer who's flying blind?
Perhaps my conclusion here is that code should be good because it invites the programmer to ponder what it means to write good code. It invites them to think in terms of theories, and it invites them to prioritise theory-building as a process either individually or within their team. It invites them to care. Code should be good so that we know when it's bad. Code should be good so that software can be good; so that it can be good in and of itself; so that understanding and using it is a more sound choice than replacing it. Code should be good so that programmers stop believing LLMs can write it.