Programming as Theory Building
Picture, you join a new team working on a big system. Everybody who knew anything has left, either to find greener grass or to enjoy a well deserved pension. You and the team struggle to build new features for the system or to adapt functionality to match changes in legislation. Not to mention the trouble it is to figure out what to fix when things go wrong. At the same time, the business that you support is screaming for innovation and pushing for more and more changes. Recognize this situation? Ever experienced it yourself? A world full of legacy systems āLegacy. What is a legacy? Itās planting seeds in a garden you never get to see.ā - Lin-Manuel Miranda, āHamiltonā Legacy, the thing that you are remembered for, typically the word has a positive meaning⦠how come that in tech the word āLegacyā has such a bad connotation? When we call out a legacy system, we usually mean: code without tests (Michael Feathers) or code you āgotā from somebody else, or code that youāre scared to touch. However, there is a reason these legacy systems are still around. In almost all cases, that system still brings in money or is somehow still valuable. If it did not bring any value anymore, wouldnāt it be decommissioned? There must be something in these systems that makes them survive, where other systems did not. How systems become āLegacyā So legacy systems are those that have become hard or scary to change. In my experience, that not because something is wrong with the code or technology. The major contributing factor is usually that the knowledge about the system has left the organization. And then I donāt mean the documentation, but the people that built, maintained and ran the system. When those people are gone, you know that nobody else is going to be happy touching that thing. The value of software Code is like a mapping of desired real world behavior to a program that can be executed by a machine. So where is the value of a system, is that in that code? Over the past years Iāve talked a lot at conferences and training workshops about the value of code. How I used to explain it is that the value of software is to be easy to change. Itās in the name: soft = flexible. Which contrasts with hardware, which is quite hard to change once youāve soldered everything together. Pretty much all the things that we do to improve our way of writing code boil down to making the code easier to understand for the next person working on it (or yourself in 6 months). Our primary objective for building maintainable systems is to make code easy to change. In a sense, to make the ālegacyā that we leave behind be a positive one. Then, about a year ago, I got drawn deep into the rabbit hole by this video on The Value of Source Code by Philomatics. It stated that the value of a software system does not have a lot to doe with the actual source code. Instead, the real value is the ability to quickly change the system, and that the key thing that you need for that is people with a ā mental theoryā of why the system works the way it does. Without that theory, no person is able to confidently make any changes. For me, this way of looking at it immediately made sense. When I look back at observations I made on the numerous software systems I worked on over the years, everything just fell into place. I also realized that this fundamental shift in thinking about software systems has wide implications. Or as Maria Rey puts it so adequately: āThis theory is learned through immersion, through building and debugging and negotiating constraints. You cannot download it; you acquire it by living with the system until the system inhabits you. This is an uncomfortable idea, because as soon as we say this, the economic picture around code trembles: the most valuable part of the program, the part that determines whether it can be safely changed, does not appear on the balance sheet. It is invisible, embodied, and therefore precarious.ā - Maria Rey That all brought me down the track of diving into this topic, talking about it at conferences and writing blogs like these about it. Programming as Theory Building This is not some new AI-era insight either. Peter Naur, the N from BNF and a Turing Award winner for his work on Algol 60, already wrote about this in 1985 in his article āProgramming as Theory Buildingā. Naurās point is simple, and once you see it you cannot really unsee it. A program is not just the source code sitting in a repo. The real thing is the theory people build in their heads while working on it. Why it works that way. Why it was designed that way. What tradeoffs were made. What parts are safe to touch and what parts will bite you. What made that argument so sharp is the world he was arguing against. The dominant view back then treated programming as a kind of production process. Get the requirements in, have programmers translate them, get code and documentation out. In that picture, the human beings in the middle are mostly interchangeable. If the specs are good enough, anyone should be able to pick up the work and continue. Input = Requirements & Observing real world Programmers = Replaceable "machines" Output = Code & Docs What Naur saw, and what I keep seeing on teams now, is that this is just not how software behaves in practice. Programs are human constructions. The important part is not only the artifact, but the understanding wrapped around it. Specs help. Docs help. Tests help. But none of them carry the full story on their own. They only really work when people still understand what problem the system is solving and why earlier decisions were made. Input = Observing real world, situational experience Programmers = Build a mental theory Output = Theory: mapping between real world & code Code = Side-product This was not just philosophy for Naur. He got there by watching real projects. And that part matters, because the production view sounds reasonable right up until you have to live inside an actual system. On paper, changing software looks cheap. You edit some text. You run the build. You ship. In real teams, the expensive part is figuring out whether the change is actually safe, whether you really understood the situation, and whether you understand what side effects will occur. When he applied the Theory Building view to his observations, the actual outcomes matched exactly with what the view would predict. Software transferred from one team to another with code, docs AND human consulting resulted in success. A similar transfer took place a while later. This time only the code and docs got transferred WITHOUT human contact between the teams. The result: an unmaintainable system. The effect was not only visible in the ability to change a system, he also saw it around the ability to deal with unexpected situations. I advise you to read Naurās original text for more details on what he described. As I already mentioned, to me this immediately clicked. Having people on the team that deeply understand a system makes a huge difference for how effective the team is going to be at adapting it and dealing with incidents. Iām sure that anyone with sufficient experience on software projects will feel the same. Canāt we just document the theory? Ok, so if that mental theory is so important, why donāt we just write it down in documentation? Seems like the obvious answer. The trouble is: you canāt. Writing down your mental model of a system is the same as asking someone to write down how to ride a bike and then asking someone else who never rode a bike to learn it from the text. This is the nature of Tacit Knowledge, it is learned by doing, not by reading. When you learn cycling, you ābuild a feelā for the balance. Reading an essay on how gravity works is not going to help you. The same goes for someone learning the finer touches of playing a violin, or the intuition on how to react thatās built up by basket ball players. | Tacit Knowledge | Explicit Knowledge | | |---|---|---| | Definition | Personal, experiential know-how thatās hard to articulate. | Formal, documented knowledge that can be written down, codified, or stored. | | How itās gained | Through practice, intuition, trial-and-error, observation. | Through reading, lectures, databases, manuals. | | How itās shared | Mentoring, storytelling, shadowing, demonstration, practice. | Books, reports, procedures, checklists, training materials. | | Examples | Riding a bike, a chefās āfeelā for seasoning, a leaderās intuition in a crisis. | Recipes, standard operating procedures (SOPs), user manuals, financial reports. | | Transfer difficulty | Hard to capture in words and usually requires personal interaction. | Relatively easy. You can just copy, store, or transmit the written or digital record. | | Value | Enables creativity, innovation, and expert judgment. | Provides structure, consistency, and scalability. | The theory of a system is tacit knowledge. This is āThe Artā of doing something. The code, tests and the docs are explicit knowledge. These are āthe instructionsā for doing something. āThe Artā of doing something is not something you can write down. It must be passed person-to-person and learnt through experience and social interaction. āThe conclusion seems inescapable that at least with certain kinds of large programs, the continued adaptation, modification, and correction of errors in them, is essentially dependent on a certain kind of knowledge possessed by a group of programmers who are closely and continuously connected with them.ā - Peter Naur, Programming as Theory Building So what survived from the age of Naur? Ok, nice theory from the 80s, why doesnāt anybody seem to talk about this and why does it seem like our industry is just completely ignoring these quite fundamental insights? What I find interesting is that our industry never fully chose one side. We kept a lot of the formalist instinct, and that is not a bad thing. We like tests, contracts, static analysis, CI, typed code,
Comments
No comments yet. Start the discussion.