Peter Naur On Why Programs Are More Than Just Text

Jimmy Zhang
5 min readJun 21, 2018

--

Let’s start with a syllogism.

Programmers write programs. A program is a set of instructions that work together to solve a problem. Programmers specify these instructions with programming languages, which are written and read as text. Therefore, programmers are producers of text.

While this conclusion may be logical, it feels a bit reductive. So what do programmers produce, then, that is more than “just text”?

One insightful answer can be found in Programming as Theory Building, written more than 30 years ago by Peter Naur. The first part of this post summarizes the definitions, assertions, and conclusions made by Naur. The second part touches how Naur’s ideas can be applied, especially in workplace settings.

The Primary Assertion

Naur’s primary assertion is that programmers should be viewed as developers of theories, rather than developers of programs. He gives this view the name “Programming as Theory Building”.

Let’s dig a bit deeper into what this means.

Programming involves translating real-world situations into symbols a computer can understand. Naur suggests that the output of programming is not the symbols themselves, but rather, a theory about the nature of that translation.

It is these theories that make programmers more than just producers of text.

What is a Theory?

Naur has a specific definition of what these theories are. This definition is best understood by looking at its characteristics.

When a programmer possesses a theory¹ of a program, he or she is able to:

  1. Explain the program, which involves answering questions and justifying implementations.
  2. Identify how similar situations can be expressed in terms of the theory, including any that may arise in the future.

The first characteristic involves having answers to the question: “but why?” As we’ll see, the second characteristic is crucial a program’s success over time.

With these characteristics established, we can make the distinction between merely being capable of achieving something, and possessing a theory on the matter.

As an example, consider a programmer writing a unit test. It is possible for him to write a passing test without fully understanding “why”. On the other hand, a programmer with a theory regarding the test’s purpose can pinpoint the exact set of source code changes necessary for the test to fail. She understands how the test maps to the real world. This allows her to reason about how it covers the entire domain, such as include error states and empty or unexpected inputs.

Implications

This view of Programming as Theory Building can shape the way we think about changes made to existing programs.

Naur first makes a connection between changes and the definition of theory outlined above.

He argues that the first step of making any change involves a “confrontation of the existing solution with the demands called for by the desired modification”. This “confrontation” requires an ability to determine “the degree…of similarity between the capabilities of the existing solution and the new demands” — which is exactly the second characteristic of our theory defintion.

More importantly, Programming as Theory Building provides us with a simple model for evaluating the quality of changes made to a program.

Under this model, quality changes occur when the programmer making the change possesses a theory compatible with the original theory used to build the program. On the other hand, program “decay” is a result of “modifications made by programmers without a proper grasp of the underlying theory”².

This model is also supported by the observation that there are typically many ways to implement a change. In terms of pure program execution, these implementations are all equally correct. When we give a specific implementation qualities such as “simplicity” and “good structure”, we are often doing so in relation to other possibilities. The ability to make these comparisons requires a grasp of the underlying theory.

My Takeaways

Adapting Naur’s view of Programming as Theory Building makes the roles of both new and experienced programmers in an organization crystal clear.

The new programmer’s job is to internalize the underlying theories of a code base as quickly as possible, as the emphasis on quickness reduces potential for decay. The experienced programmer’s job is to make the same underlying theories as available as possible, to ensure that the knowledge can be distributed as necessary.

To this point, Naur states that it “is required…that the new programmer has the opportunity to work in close contact with the programmers who already possess the theory, so as to acquire the knowledge of how the program works and how unusual program reactions and program modifications are handled within the program theory”³.

Documentation and Other Strategies

Although Naur’s prescription is ideal, it is not always feasible for new programmers to always be working in close contact with those “in the know”.

In the absence of such opportunities, what else can we do?

The first, and most obvious strategy, is through the process of code review. Code reviews are a natural extension of Programming as Theory Building. For me, framing code reviews in terms of enforcing theory structure emphasizes the importance of the process, for both the reviewer and as someone whose code is reviewed.

The second strategy we have is documentation. One of Naur’s core assertions is that the theories that programmers develop cannot be adequately expressed through documentation, mainly due to the limitations of written word compared to the complexity of the world.

But I believe that instead of focusing on these limitations, we can be smart about the types of documentation we create. Instead of lamenting over missing pieces, we can combine the lego pieces we do have in effective ways.

Some types of documentation such as commit messages and source code comments, exist contextually “close” to the code, and this proximity can be used an advantage. As commits are inherently tied to changes, descriptive commit messages are great for explaining how those changes relate to existing theory. Informative source code comments touch on both the “why” and “how” — for example, why a particular workaround is necessary, and how existing code can be improved to remove the workaround.

For other types of documentation, we can use the two characteristics of a theory given above as inspiration. On one level, documentation needs to address the “why”, by providing explanations and justifications where appropriate.

But knowing “why” is not enough. In order to grasp a theory, readers must also know how it can be extended. With this in mind, documentation can also include examples of how the program can handle various situations that may arise in the future. Code labs or walkthroughs can also express the theory in terms of core concepts that build atop one another. These types of documentation require active engagement from the reader, and prompts thinking that goes beyond the contents of the source code.

Conclusion

If the content of this post interests you, I highly recommend reading the original paper. In particular, Naur references two real-world examples that led to the formulation of his theory. He also elegantly defines a program’s lifecycle in terms of the theory possessed by its maintainers.

The more I program, the more I realize how much of programming exists outside of a text editor. This paper was one of the more influential ones in terms of describing that landscape. I’m curious to see what else I can find.

Related Links

This discussion on Hacker News led me to the paper.

References

¹ This definition is not specific to programming, and is adopted from Gilbert Ryle’s work The Concept of Mind.

² Naur, pg. 233

³ Naur, pg. 235

--

--