Vico, Descartes, and decay of knowledge in software.
This is the second post in the series dedicated to ontologies in systems engineering:
Perdurantism in systems engineering standards
Vico, Descartes, and decay of knowledge in software
Making is knowing, it makes things intelligible. This is the foundation of<br>epistemology of the Napolitan philosopher Giambattista Vico, and it explains why<br>we lose the knowledge of software faster than it decays technically. I am<br>overviewing Vico's philosophy as a system/software engineer, highlighting<br>connections with our daily work, and raising concerns about AI code generation.
TLDR
Software decays epistemically before it decays technically. The code still<br>runs, but no one remembers why it runs that way – why that ugly function has<br>ten arguments, why that branch exists, why that test does something weird.<br>The knowledge vanished while the code kept working.
Save your mistakes. When you make a decision, write down what you didn’t do.<br>"We chose A over B,C,D because…" Without the rejected paths, the choice is<br>a mystery for the future you as well as for others.
Read old code like a detective. Before you refactor, ask: what made this<br>sensible six months ago? You’ll either learn something or earn the right to<br>rewrite.
An LLM cannot give you a genuine rationale (it has no intentions). You must<br>force agents to produce a trace of decisions and alternatives that a<br>human can validate. Otherwise, you’re accumulating unintelligible artifacts.
Lost rationale
"What I cannot create, I do not understand"
– quote found on Richard Feynman's blackboard at the time of his death in 1988
We, who proudly wear the mental scars of engineering a large project, who have<br>seen code creatures bizarre and unthinkable, who slew dragons and learned to<br>kill hydras without cutting their necks, who grew weary and wise and know when<br>not to start a fight and just let the beast remain in their cave, to us I address<br>this lamentation. For we know what it is like to tend to our own work from months<br>ago, trying to figure out its grand design. For we understand that there is<br>something we lose when we complete the act of making. The cord is severed, and<br>the most intimate connection between the maker and their creation disappears.
While I'm making, I know my decisions. Some pieces accidentally fall to the<br>right places, but others I am placing deliberately. I name variables, functions,<br>types; I carve up interfaces; I structure the types; I choose or create<br>algorithms; I use specific languages and tools. All these moments will be lost<br>in time. Another day comes and I stare back at my work in disbelief. You must be<br>joking, Mr. So-and-so, this function has 10 arguments? Don't you know anything<br>about design?
But I glimpse at my scars and I know better, and I do not touch it. Otherwise I<br>am likely spending the rest of the day trying to fix it just to rediscover that,<br>because of some contextual reason, this ugly monster of a function was the<br>lesser evil in a freak zoo. If I'm lucky, the context has changed enough since<br>that time: some dependencies or hardware updated, some compiler bug fixed. Then<br>I can properly rewrite the code. Good for the codebase, bad for me, as it<br>provides an intermittent reward to my risky behavior. My code winks back after a<br>facelift. Here's another type which clearly does too much work, how about we<br>decompose it?
The fever intensifies when I touch other people's work, but me from a year ago<br>and my colleague from yesterday aren't that different. The cause is still the<br>lost rationale. If I don't understand why this function was made with 10<br>arguments, I don't really know it. And so I attempt to rediscover this lost<br>knowledge, studying the context and inferring the missing bits. I recover some<br>scraps of rationale, and I should be content with it.
Old code may look ugly, dumb, complex but the real problem is that it is not<br>intelligible, because its causal history is gone1. Sometimes it is not ugly, but<br>situated code, carrying scars from real contact with the world, a platypus<br>growing a beak because that was its best shot at survival. That function with 10<br>arguments, it was also chosen among a few alternative options, and likely for a<br>good reason. Maybe grouping the arguments into structural types or decomposing<br>the function would hit the performance on a specific version of compiler or<br>runtimes, or trigger some compiler bug, or destroy interoperability with some<br>weird 3rd party module. I only wish someone wrote that somewhere.
Struggle of makers
When we were finishing a semester course in Modern Philosophy, our teacher,<br>Michał Kozłowski, chose "The New Science" by Giambattista Vico as the final<br>text. Vico, a XVIII century Neapolitan professor of rhetoric, is a rather niche<br>read for philosophers, and a totally unknown character for engineers. Professor<br>Kozłowski was barely holding his excitement: "This is a very different kind of<br>philosophy, unlike anything we've read so far." So far,...