Holding A Theory
On Peter Naur's "Programming As Theory-Building"
I find that some of my enthusiasm, on first discovering it, for Peter Naur’s 1985 essay “Programming As Theory-Building” was based on an emotional response to the apparent promise of the title. On re-reading it’s impossible to overlook that Naur quite stubbornly refuses to mean by this phrase what I supposed he ought to mean by it. I took him to mean that the program itself is the material trace of a process of theory-making, such that the program “bears out” the theory in its own structural idiom. What he actually means is that the activity of programming is one by which programmers form theories in their own minds. The theory does not “live” “in” the program. The program is if anything a sort of dead residue, logic without sense.
Naur ‘s essay opens with the suggestion that 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”. What is proper to programming, what programming is properly, is expressed through the achievement of a relationship between “insight” and “matters at hand”. A domain is mapped, a set of practical concerns is theoretically subordinated. Programming is only secondarily, im-properly, "a production of a program and certain other texts”.
Now I don’t entirely object to this. The thrust of the claim is that programming is a constructive rather than a productive activity. It’s not fundamentally about emitting lines of code or assembling a technical artifact that efficiently does our bidding, it’s about gaining greater purchase on the world through the feedback we get from attempting to automate our practical goals. The working program (which we presumably do care about) is a by-product of this process. Taylorist management starts with the assumption that programming is a productive activity and tries to drive it towards greater productivity, measured in terms of outputs. Naur is arguing for an understanding of what programming accomplishes that is closer to that of programmers themselves. In this understanding, developing the means to accomplish our practical goals happens at the same time, and in the same process, as refining and revising what those goals themselves should be.
There’s a version of this in Agile, where partial progress yields working software that can be placed before customers to obtain early feedback, in theory enabling incremental convergence of ends (what the customer wants) and means (what the software does). But Naur doesn’t mention customers (or “users”, as they were known in those innocent days). They are almost euphemistically handwaved around:
One thing seems to be agreed by everyone, that software will be modified. It is invariably the case that a program, once in operation, will be felt to be only part of the answer to the problem at hand. Also the very use of the program itself will inspire ideas for further useful services that the program ought to provide. Hence the need for ways to handle modifications.
The programmer’s feedback is coming from the domain of endeavour itself: from the system. The demand for modifications arrives from the “felt” inadequacy of the program, or its ability to “inspire” new notions of utility. The social dimension is thus bracketed: feelings and inspirations cross the boundary by a sort of depersonalising osmosis. The pertinent interface is between the system as it stands and the problem space as it unfolds before it.
The austerity of this bracketing encourages the reader to picture programmers as alone, in a sense, with their theories. Facing “matters at hand” or “the problem at hand”, circumstanced by an ambient requirement for “modification” of the program that addresses them, is the programmer’s inalienably present mental conception of the task and its solution. The programmer “possesses…the theory of the program”. Hence, “an essential part of any program, the theory of it, is something that could not conceivably be expressed, but is inextricably bound to human beings” (my italics). Not only is programming “properly” theory-building: it is the building of proper theories, theories as property that could not conceivably be unbound or ex-propriated1.
It’s clear why Naur holds the program itself to be a sort of dead residue. If an essential part of it cannot be expressed, and if the program itself is taken to be a form of expression, capable of being extricated from one set of human beings and transferred between teams and practical contexts, then the program itself is lacking an essential part of itself. The program as product is degenerate, decaying the instant it is produced. And programmer lore broadly concurs with this view: programs succumb to “bit-rot” the moment they emerge into the world; the code you wrote six months ago will be unintelligible to you now.
So where do I demur? For me, as I said at the beginning, “programming as theory-building” suggests that the program itself is a relay of thought, a way of throwing the nerves in patterns on a screen. “Theory” is not properly located in individual programmers’ brains, but disseminated among people, organisational structures, exocortical artifacts such as source files, documentation, and running systems. It may not travel well across situations, because much of how a theory is instantiated in code and conduct is buttressed by implicit norms, “magic knowledge” shared by those in the know, and other things not likely to be written down. But it is not wholly intransmissible, and the program itself transmits it in part, as a trace referring to other traces within its operational context2.
These matters are brought to a head somewhat by the experience of programming with LLMs, because the LLM’s problem is that it lacks a theory of the program it is confabulating (and so tends to extend it in aberrant ways), but its singular mechanical competence lies in being rather inhumanly good at following the theory-traces within the codebase it’s working on (much as it’s also rather inhumanly good at decoding modernist poetry) . Naur’s example of the confusion that can be wrought by a team poor in theory will resonate with those who have experienced friction of similar kinds when working with LLMs. A new team, “group B”, comes to make extensions to a compiler implemented by “group A”:
During the design phase group B made suggestions for the manner in which the extensions should be accommodated and submitted them to group A for review. In several major cases it turned out that the solutions suggested by group B were found by group A to make no use of the facilities that were not only inherent in the structure of the existing compiler but were discussed at length in its documentation, and to be based instead on additions to that structure in the form of patches that effectively destroyed its power and simplicity. The members of group A were able to spot these cases instantly and could propose simple and effective solutions, framed entirely within the existing structure.
Here we observe a failure of transmission, not only of “magic” not-written-down knowledge, but also of knowledge “inherent in the structure of the existing compiler” and “discussed at length in its documentation”. The problem, I infer, is one of salience: group A hold a mapping of the system which enables them to navigate its inherent structure and documented features, and identify opportunities for “simple and effective” re-use of its existing affordances. Group B have access to the same information surface, but do not know what within it is significant and relevant to their needs. They make guesses which result in ad hoc “patches” that realise their practical goals, but add needless complexity and obscurity. And so, if haplessly thrown in medias res into a software ecosystem without clear navigational affordances, do LLMs.
Loud voices within the software industry insist that destructive guesswork of this kind is not worth fretting about if the practical (and, above all, commercial) goals of the organisation are realised. Programmers are accused of “obsessing”, with geekish inattention to the bigger picture, over cleanliness, elegance, syntactical consistency. And admittedly there is a tendency to put the cart before the horse in focussing on hygienically organised “clean code” rather than the overarching theoretical integrity that naturally results in “simple and effective” implementations. As the software architect Barry O’Reilly has argued, “decoupling” at the right boundaries is the signature of a resilient architecture, not the means of achieving one. You can decouple at the wrong boundaries and end up with a system that is both awkwardly decomposed and operationally hamstrung. This supports Naur’s claim that the program as end-product is not the proper locus of theory. In programming as in politics, we cleave to hygiene rules when the truly structural issues elude our comprehension.
Nevertheless, I think it is possible to organise programs and their supporting artifacts in ways that scaffold the transmission of navigational understanding, rather than leaving future developers scratching their heads, or burning through tokens, trying to gain purchase on a mass of undifferentiated detail. To push back on Naur’s example above, I think that if a compiler affords simple and effective ways to implement features it does not yet have, then it ought to be possible to document those pathways, and perhaps even implement them, in ways that are pedagogically leading. The art of programming with LLMs might be considered a relative of pedagogy: it involves directing “attention” (contextual focus, and pattern-extending propensity) to the right detail, and finding ways to make the system being worked on pervasively exemplary of its own theory.
By the same token, I think we can see the crisis AI is exposing in the software industry as a crisis of pedagogy. We are being confronted with just how bad we are at transmitting theory, just how much we rely on the repeated wasteful expenditure of time and energy by neophytes who are expected to claw their own way towards systemic understanding. For most of my 20+ year career, the ability to tolerate being in an environment where you know very little about how everything hangs together, and to quickly assemble a working picture sufficient to enable you to start getting things done, has been considered a key professional asset. A newcomer who dislikes feeling incapable and ill-equipped, who cannot comfortably pass through repeated episodes of profound deskilling, will be quickly discouraged. This fact alone probably accounts for some of the persistent demographic biases of the profession: for some people, the social cost and precariousness of being in that position is much higher than it is for others.
I read a lot of Derrida at an impressionable age.
A lot of Derrida.

