Towards Understandable Software — Anna Liberty
Towards Understandable Software
Why programming sucks and how to fix it
2026-03-07 · 13 min · #computing
Programming sucks. Code sucks. It's hard to read, hard to test, and hard to maintain. Only a handful of people can understand any particular software project. These are major problems. I'm here to explain how we can fix them.
LLMs aren't the Model
Large Language Models (LLMs) are becoming an important part of industry software development. Even experts with years of experience are using LLM agents to test, debug, and even write code. Now that many LLMs are capable of integrating with their environments, some of their logistical problems have been mitigated.
Non-programmers have also turned to LLMs. Programming can be unapproachable. Many people have no clue where to start and, even if they did, have no desire to learn the fine details of the syntax and libraries of any particular language. I regularly see people with little programming knowledge use LLMs to write them anything from simple personal scripts to tools for processing scientific data.
I don't believe this is the result of LLMs being incredible at programming. Almost everyone in the field has seen the results of a session of vibecoding. Even if the tests pass, the resulting code is usually atrocious.
No, I believe programmers and non-programmers alike have turned to LLMs because programming sucks. There are so many conflicting software stacks, endless boilerplate, and annoying libraries. The work of the average software developer has been reduced to gluing libraries together rather than developing interesting code.
But the fact that programming sucks doesn't make LLMs suck any less. The major problems with them persist. They still are environmentally destructive, fundamentally based on stolen code, produce inconsistent code, and instill dependency. Overall, LLMs make programming worse than it has been before, despite their promise. We deserve better than current programming paradigms, but we also deserve better than LLMs.
We Can do Better
We don't have to give up automation if we give up LLMs. We don't have to give up high levels of abstraction if we give up LLMs. We don't have to give up human-friendly interfaces if we give up LLMs.
The benefits promised by LLMs may not outweigh their costs, but we don't have to give up those benefits. We can have predictable, high-level, testable systems that make software more maintainable. We don't even have to give up using natural language to communicate with machines. We just have to take a different approach.
Instead of tackling the problem of writing code, we should tackle the software stack underlying the code. Instead of making it easier to generate endless amounts of code, we should eliminate the need to write it at all. We should embrace the layers of abstraction that have led us to higher and higher level languages. When the urge to automate one layer of abstraction emerges, we should instead abstract it away.
The prevalence of LLMs in programming has shown us we need a different approach to programming. The urge to automate the process of writing code has shown us we need to abstract the need to write code at all. We need another layer of abstraction that allows us to think about software even to the ways humans—not computers—naturally think.
Document the Yak
The first and most important step of making software understandable is documentation. If we want software to be understandable to other humans, the least we can do is explain it to them.
Programmers already know that documentation is important, but for the most part we see it as something to tack onto the code afterward. We write the code, and then maybe add doc-comments to explain what outwardly facing functions do. If our users are lucky, we'll even write usage examples.
I propose we flip this. Instead of writing the code first and tacking on documentation, we write the documentation first and tack on the code. We tell humans what our program does and then we tell the computer what it is supposed to do. This is a concept known as Literate Programming.
Imagine this: instead of reading other people's code and then trying to parse their intentions form it, you read the documentation to understand their intentions and then you read the code. You no longer have to strain yourself trying to understand what someone wrote for another audience (the machine). They've already explained it for you.
The best implementation of this I'm aware of is the Entangled bi-directional tangler. A tangler extracts code from your documentation and distributes it across the appropriate source code files. It's bidirectionality means you can use it to write code embedded in documentation, but then also edit that code normally which it then propagates back into the code blocks in the documentation. This allows programmers to use existing tooling for testing, refactoring, and code formatting without...