Comprehension Can't Be Reduced to the Artifact


Peter Naur, 1985#

Most developers carry an implicit belief that the source code is the program. Peter Naur disagreed. In a 1985 paper titled “Programming as Theory Building,” he argued that the program is not the text we commit to version control. It is the understanding in the minds of the people who wrote it. The code is merely one artifact that understanding produces.

Naur was not speculating from the sidelines. He co-created BNF notation, helped design ALGOL 60, and later received the Turing Award. His paper is short and precise, and the ideas in it are worth understanding.

The Central Argument#

Naur’s thesis is direct. Programming, he argues, is not primarily the activity of producing code. It is the activity of building a theory of how a real-world problem maps to a computational solution. The code is an artifact that emerges from that theory, but the theory itself is something richer and more complete than any artifact can capture.

“Programming properly should be regarded as an activity by which the programmers form or achieve a certain kind of insight, a theory, of the matters at hand.”

Naur borrows the word “theory” from philosopher Gilbert Ryle, using it to mean something specific. A theory in this sense is not a formal specification or a written document. It is an understanding held in the programmer’s mind that enables them to do three things.

  • Explain what each part of the program does and how it relates to the real-world problem being solved.
  • Justify why the program is structured the way it is rather than some other way.
  • Respond to new requirements or changes by knowing where and how the program should be modified.

That third capability is the most revealing. A programmer who holds the theory of a system does not need to trace through the code to figure out where a change belongs. They already understand the relationship between the problem domain and the solution structure well enough to know where new requirements fit. This is the difference between someone who built a system and someone who is reading it for the first time, regardless of how expressive the code is.

Where the Theory Lives#

If Naur’s argument is correct, then the theory of a program lives primarily in the minds of the people who built it. This is the uncomfortable part of the paper. The source code is not the theory. Documentation is not the theory. Comments are not the theory. These are all artifacts produced by people who hold the theory, and they contain traces of it, but they cannot fully reconstitute it in someone who lacks it.

Consider what source code actually records. It records the final decisions, the “what,” without preserving the full reasoning that produced those decisions. It does not explain which alternatives were considered and rejected. It does not explain which aspects of the problem domain are represented in which parts of the code, or why the boundaries between modules fall where they do. You can look at a system’s coupling and cohesion and observe its structure, but the structure alone does not tell you why those particular groupings and separations were chosen.

Documentation faces the same limitation from a different angle. It records conclusions at the time of writing. It captures a snapshot of reasoning, not the living understanding that continues to evolve as the programmer encounters new situations and refines their mental model. The best documentation, such as architecture decision records, captures fragments of theory by recording context and alternatives considered. But even thorough documentation cannot transfer the full capacity to extend, modify, and reason about a system the way its builders can.

This is not an argument against documentation or against writing clear, expressive code. These things have real value. Naur’s point is narrower and more precise. No artifact, however well-crafted, fully substitutes for the understanding held by the people who created it. The artifact is evidence of the theory. It is not the theory itself.

Dead Programs#

Naur introduces the concept of a “dead program” to describe what happens when all the people who hold the theory of a system have left. The source code still compiles. The tests still pass. The documentation still exists. But the theory is gone. The program is, in Naur’s framing, dead.

New developers inheriting a dead program face a qualitatively different challenge than the original builders faced. They are not continuing the theory. They are attempting to reconstruct one from artifacts alone. This is reverse engineering in the deepest sense. They must infer from the code what problem was being solved, why it was solved this way, and how the parts relate to each other and to the real world. They can succeed at this, but the theory they build may differ from the original in ways that introduce subtle inconsistencies over time.

This explains a phenomenon every developer has encountered. A codebase that the original team could modify confidently and quickly becomes a codebase that a new team modifies cautiously and slowly. The code has not changed. The tests have not changed. What changed is that the theory left with the people who held it. The new team is not simply “ramping up.” They are building new theory, and that process takes time that no amount of documentation can eliminate entirely. This is the mechanism behind what Brooks’ Law observes at the team level. Adding people to a project does not add their understanding. They must build it, and they must build it while the existing team spends time helping them do so rather than advancing the work.

Practical Resonance#

Naur’s paper was descriptive, not prescriptive. He was observing something about the nature of programming, not recommending a process. But his observations connect naturally to things working developers experience every day.

Team continuity matters more than most organizations account for. When a team that holds the theory of a system stays together, they can respond to change with a fluency that no documentation handoff can reproduce. When that team disperses, the new team’s effectiveness depends on how much theory they can rebuild, and that rebuilding is constrained by the same communication structures that Conway’s Law describes. The organization’s structure shapes not just what gets built, but how effectively theory can be transmitted.

Practices like pair programming and code review serve a function beyond catching defects. They are mechanisms for transferring theory between people. When two developers work through a problem together, they are not just producing code. They are building shared understanding of how the problem maps to the solution. That shared understanding is more durable than any document because it lives in multiple minds and continues to evolve through conversation.

The real cost of turnover, in Naur’s framing, is not the time it takes to train a replacement. It is the theory that leaves with the person who departs. Everything that person understood about why the system is shaped the way it is, which tradeoffs were made and why, where the bodies are buried, all of that understanding must be rebuilt by whoever comes next. This is why teams that maintain low turnover and high continuity can sustain velocity in ways that high-turnover teams cannot, regardless of individual talent.

The Paper’s Enduring Relevance#

Naur wrote this paper over forty years ago, and it describes something that has only become more visible as software systems have grown in scale and complexity. The observation that the constraint was never writing code but always understanding is a modern restatement of exactly what Naur articulated in 1985. The tools we use to produce code have changed dramatically. The fundamental challenge of building and maintaining a theory of how problems map to solutions has not.

Naur was not offering solutions. He was naming something real. The understanding that makes a programmer effective on a particular system cannot be fully externalized into any artifact, whether that artifact is source code, documentation, or a specification. That understanding lives in people, transfers through collaboration, and dissipates when those people leave. Every developer who has inherited a system and felt the gap between having the code and having the comprehension has experienced what Naur described.

The original paper is short, clearly written, and freely available. It is worth reading in full.