Software is Evergreen
And why it doesn't feel like it is.
Lately, I’ve been quite busy programming my own web development foundation in Clerk. I’m quite fond of Scheme, C, the web, and decided it was finally time I re-enter web development from a bottoms up approach. I decided to target FastCGI as I’ve implemented HTTP—the protocol that runs the modern World Wide Web (WWW), now frequently mistaken as the Internet at large—and already knew of the potential pitfalls I’d prefer to avoid when programming yet again. Instead, FastCGI is a much simpler protocol, one specifically for what are known as application servers, the software that makes the WWW more dynamic, and it lets them communicate to a proper web server that handles the practical complexities of HTTP communication. This process has led me back down a path of thought I’ve been down many times: Why software seemingly degrades, why companies are happy to allow it to fall to obsolescence, and how software programmers I’ve met throughout the industry like to perpetuate the myth of software as an engineering problem.

To be clear, I’m not proposing an industry–wide conspiracy theory. Instead, I’m arguing that the way software programmers are educated, and the way software itself is perceived, has led to an ever deepening chasm of misconceptions about what software is, does, and how it behaves. Throughout my 15 years programming, the primary ways I’ve seen programmers engage with the art form is with a level of frivolity and humorous self-deprecation that is quite shocking for an artisan to view their craft, or even for a worker to view their own labor. If pressured they may defend their work, but at large they’re happy to decry themselves a fool. From this foolishness begets many ideas prevalent within the larger “software engineering” industry: That code is a liability, inconsistent, superfluous, or otherwise a force that must be controlled by the fools who are hired to do so. I would like to spend time challenging these ideas, and proposing a foundation in which software can be better perceived.
The Ontical Proposition of Software
So then it must be asked, what is software? Perhaps an elucidation will come as we walk backwards along the path, back towards its origins. This backtracking takes us towards an intersection of three other paths: mathematics, formalized logic, and industrialization. Therefore, I will start us at an arbitrary beginning: That of mathematical machines. The first mathematicians to be declared programmers, generally, are Ada Lovelace and Charles Babbage. It is important both are mentioned: Babbage had hoped to build a machine for arbitrary calculation, Lovelace identified how such a machine could extend beyond mathematics, and they worked together to create theoretical programs that could run on it. Given the machine itself, the analytical engine, never came to be built, their contributions to software ended as a historical curiosity, and a rose-tinted origin story.

Instead, the origins of software as it is today, can be better traced back to the work of two logicians: Alonzo Church, and Alan Turing. They didn’t define software, instead, they defined more fundamental aspects that is used in software: computation, and algorithm. Turing conceived of the Turing Machine, an infinitely long tape machine that evaluated instructions based upon what was present upon the tape. Church, then, proved that a mathematical function on the natural numbers can only be calculated effectively if it is computable by a Turing Machine. Additionally, Church derived his own formalization of computation: The Lambda Calculus. This was additionally later proved to be equivalent to the Turing Machine. But the outcome of this became a general definition of computation—that which can run on a Turing Machine, Lambda Calculus, or other equivalent—and of algorithm, a sequence of computable steps.
Equipt with these definitions of computation and algorithm, we come closer to understanding what software is. But we are still not ready, no, for we need to come to an understanding on what a computer is as well. In the modern day we view them as machines, perhaps even as black boxes in which heretofore unknown processes happen, but historically a computer was an occupation, a human. These human computers followed algorithms, computing the outcome of intense mathematical calculations, centuries before even the electronic calculator came to be, and before the formalization of computation itself. From this history spills out the shared word program, a sequence of events, actions, or other important information. It does not spill out of the tacit sequence of facts, that of history, but of the fact that computation has always been a distinctly human endeavor, an acceptance that coming to an outcome requires a programmed series of steps.
Software then, in the modern propositions of machine computers, formalized computation, algorithm, and programs, comes closer to being shown. Software, a word intended to distinguish from hardware, wares of the physical world, and firmwares, algorithms intended to bridge the two, become algorithms or programs of simulation. Given their separation from the real, and rooting in the theoretical, with the need to bridge to the real for practical purposes, lends them outside of the real altogether. These simulations—and frequently simulacra, in the Baudrillardian sense—compose themselves of sequences of algorithms, a program of programs. They become ideas in their own right, outside of space or time, constructing their own being out of constitutive recursion back onto itself, until the foundations of formalized computation is reached. This free recursive property of software has a name, that of abstraction, where the disclosed sequence of an algorithm becomes encapsulated in a simpler form, such that it can be reused and/or distributed.
Some programmers may call out the fact that software still relies upon the real machine, and interacts with it through memory access and side effects. While true, this definition of software does not make a pure or even functional assumption, and those aspects of software programming can be thoroughly folded into the larger theoretical landscape of formal computation as aspects of a Turing Machine’s instruction set. Memory becomes separate slots along the tape, side effects become peripheral behavior instigated by the machine. Software, then, becomes concerned with a conceptual machine, not the particular machine of firmware, and that serves as the critical difference between software and firmware. More generally, software concerns itself with itself, becoming its own machine, and its being is defined in terms of itself, in the way of ontical recursion, unraveling towards the fundamental computation models in formal computation, algorithm, and programs that define a series of computable steps. This leads us further into the realm of abstraction, as since software is defined in terms of itself, we must follow the path laid bare, taking note to observe what changes in software’s own characteristics.
Up The Abstraction Chain
Given software being defined in terms of itself recursively, it should be no surprise that the industry of “software engineering” has become a deeply complex space. There is no education, no formal training, that seeks to explain how these first principles have coalesced into what we have today. They are taken as givens, cast upon naïve learners, who then must contend with modern layers of abstraction so far away from them that they become lost. What is a Turing Machine to a modern web framework, or a single function to the systems design of object orientation? For this reason, I hope to try and provide a high-level guide through this abstraction chain. This starts from two points: The particular, and the theoretical. The particular is how all machine computer software began, as machine code, simple assembler, and firmware. The theoretical stands behind it all, behind firmware, behind the design of the hardware, but most importantly behind the essence of computation itself, and has already been discussed in the ontical exploration of software itself.
The Particular to The Conceptual
After the affordance bestowed upon us by theoretical computation, the machine computer sprung forth. These were and are practical, real machines, that must contend with reality as it fosters a space for simulation within it. As a result of this, all written code for them qualify as firmware, as code that was intended for a particular machine. This code, referred to as machine code, still utilizes the same properties of computation as software, but are merely coupled to a singular type of machine. The first of these machine computers was the ENIAC, a general–purpose, programmable machine that provided its own machine code for computation. There was no high-level programming language, no networking, and certainly no screen. This was a revolutionary system, one that showed the potential of machine computers to complete computations at speeds simply unavailable to their human counterparts. It was also notoriously unreliable, complicated to run, and expensive to operate.

Regardless, such a machine was the birthplace of much that we now take for granted. In fact, the first computer program to emit another computer program, a nearly ubiquitous modern concept, was first programmed and ran on this machine by Betty Holberton (shown above). This led towards one of the first major milestones of abstraction: That of computer language, and formal syntax. While programming in pure machine code would continue for decades after the ENIAC came online, the self-recursive nature of software (firmware, at the time) was already announcing itself. If computer programs could emit other computer programs, that gave us the luxury of incorporating formal logic more directly into software, by giving space to the concept of programming languages.
These programming languages differed from both the machine language of particular machines, and the assembler languages that provided a simpler way to write machine language. Utilizing formal language, more human–friendly languages could be used that would then emit the machine language that machine computers could evaluate. This not only meant that programming could now utilize representational syntax and semantics, instead of being simple instructions for a machine, but it also decoupled programming itself from the real machine it was ran on. This decoupling of computation from the real machine is the first step in allowing software to flourish in its own right: Program semantics once again entered the conceptual, and abstract syntax enabled the programmer to target a conceptual machine that was then either converted to a real machine, or ran inside a virtual machine that emulated its conceptual counterpart.
In a very distinct sense, the birth of the programming language as a separate category from machine or assembler languages, was the birth of software itself. It was the first time computation was able to exist both within the conceptual domain, and practically evaluated in the real. What this also meant, as computer science grew into its own field, is that semantics became detached from syntax itself. One can simply look at the variety of "Hello, World!" example programs to see how the same semantic computation can be represented through entirely different syntax structures. So not only did the programming language decouple computing from the real machine, but it allows it to be expressed in any number of different syntax, any number of different languages.
The Singular to The Plural
As software was birthed by the detachment of programming from particular machines, abstractions began to grow rapidly. Machines gained persistent storage, punch cards gave way to physical and then virtual terminals, and the software abstracted these new systems in ways that allowed consistent behavior between them. Software became a system to store your notes, to analyze data, and soon it became clear that computers needed ways to interact, ways in which the software system on one computer could structurally communicate to another to transmit information, or execute instructions. This is the birth of networking, another dense and complex field initially within the more practical world of computer engineering—to be noted as distinct, but not unrelated, from software programming. Software clearly needed a way to interact with these network layers, and thus additional firmware brought forth abstractions to give pure software this power. In fact, some of the later abstractions are still in common use today, in the form of Berkeley sockets.

This extension of the computer to include its neighbors, and even its distant counterparts, did not happen overnight. Much like the development of programming languages, the efforts undertaken to develop networking into maturity took decades. Eventually, this development reached a vital point when the World Wide Web was developed at CERN. It took the networking efforts before it, one that usually required strict rules of connectivity and access, and abstracted it into an open-ended node graph structure that more than endorsed open connectivity, it was the entire philosophy of its structure. It should be noted that it was not the first to move towards this idea, but it was the first to do so with little to no assumptions of the content of each connection. FTP has its file structure, Gopher has its list structure, and HTTP has hyperlinks. Hyperlinks are free-form, open, and had no rules of use; This changed the nature of how computers, and humans, interacted over a network permanently.
One may see a relation by how the WWW provided a conceptual network to run on top of the particular network—TCP, and now QUIC, in its own case—and how programming languages did the same to the machine. Such a comparison is important. Again, it was not the first to move in this direction, but it is the abstraction that held, the one that hypostatized into what we have today. What was once a landscape of discrete network interactions became a fast web of interconnected computers, where the singular machine was thoroughly abstracted into a plurality, a chorus, of computers interacting. Those familiar with networking history may object that a similar feat was reached with networking generally, and while networking itself did obviously permit such behavior, it was truly the WWW that succeeded in detaching networking from the computer itself. A website became not a computer, but a website in and of itself; A new form of being emerged on top of the abstractions laid forth by the underlying networking layers.
Convenience and Being
The two major abstractions defined here, that of programming languages and the World Wide Web, serve as the high-level examples of the abstraction chain(s) that comprises modern software. In the modern era these chains do not change nearly as much as is led on, they merely expand. A website that was once a mere collection of data and styling markup has become an application to rival your word processor, if not reach beyond it. An operating system’s userspace—where the user interacts with software atop it—has come to be a dynamic, networked environment, from its humble beginnings as a text prompt. What has facilitated these changes is the hypostatized links along this chain of abstraction, links that attach many separate abstraction chains to a single point. While a web application may rely on different ECMAScript frameworks, different web servers, they still rely upon the core link of HTTP.

This is both the beautiful, and horrible, nature of software. Given its near-free ability to abstract itself, there is little to nothing stopping it, and it has a tendency towards a fractal of complexity that makes the entire field nearly impossible to embody in the mind. At any point there is software that exists separate from the dominant abstraction chain, one that may even gain prominent use, but one that can never be known to become the next hypostatized link or not except in post. As such, as software became the dominant force of profit over hardware, it also came into a panic to find the next big thing. This change has overwhelmingly seemed to change the overall direction of software abstraction from that of extensions of behavior, to platforms of convenience. This comes naturally in a capitalistic environment: Convenience is itself an easy way to improve productivity, while also enabling deskilling effects, leading to a larger labor pool. The workers love it as they are told they can work less, and the employers love it as it provides them leverage over their workforce. What ends up happening is a tale at least as old as industrialization: Workers are worked harder, in more menial roles, and more money can filter upwards.
If the sudden shift to politics concerns you, and you merely want this article to remain technical, then all I can offer you is pity. No tool, no abstraction, no human phenomenon exists outside the context of the sociopolitical horizon it rests on. Therefore software abstraction, as it has shifted itself towards the deskilling of an artisan labor body, needs to be seen through such a lens. It is true to say that there is nothing ontical about software abstraction that lends itself towards this end, nothing in its nature or state of being defines it as a deskilling force, but there is also nothing in its being that precludes this. Much like the Luddites to textile machines, or the factory worker to assembly lines, technology is once again being touted as liberation as it serves to further depose the worker from their labor. Additionally, I will not emphasis this enough: While I do hold AI as a deskilling and force of cognitive decay, this is not new to that abstraction.
But if it is not new to AI, where did it come from?
Software is not Engineering
To begin answering that question, I take the stance that this largely began as software came to be viewed under the purview of engineering, instead of following its nature as evaluable formalized logic. Moving software away from its nature, and into the life cycle and limitations of engineering, inserts a faulty ontical perspective that software itself decays, or dies. This lends towards arguments of safety, structure, or other abstractions that attempt to control this spector of decay, in order for it to maintain a life cycle as declared externally. This falsely subjugates software to systems engineering, fettering it to practical considerations, and obscuring software behind the real. This has been the prevailing view of software for a large amount of its overall existence, and I am not the first to call out its shortcomings.
The Legitimization of Computer Programming
However, to avoid this descending into a meaningless diatribe, it is worth explaining where software engineering as a terminology originated. This is especially important as it did not come out of a capitalistic, nihilistic, or manipulative phenomenon. Instead, it came out of a highly bright mind’s desire to be recognized and respected among peers. The inventor of the term software engineering is Margaret Hamilton, who led the development of the Apollo program’s guidance computer software. During her work for NASA at MIT’s Instrumentation Laboratory, software programming was not respected as a trade, nor as a science. While computer science had come to be recognized, and in fact became quite interdisciplinary in its own right, the development of software outside of this space was still perceived quite negatively.

As a response to this negative perception, Hamilton began using the term software engineering as an explicit effort of folding it into the larger systems engineering landscape. This made perfect sense where she was: An engineering lab, working on spaceflight systems, directly tied to engineering efforts within the real. The software written still did not decay, the algorithms to compute the guidance trajectories surely did not erode unless physics itself has, but it became fettered to practical engineering considerations. Surely the software could have been better written as to become general, logical abstractions for use, but that wasn’t why it was made. Being fettered to engineering diminished software’s evaluable qualities into a means for accelerating the labor of astronauts, a repression that came to the direct benefit of the entire Apollo project.
This fettered form of software isn’t useless, of course, but it is reduced all the same. While I’m sure Hamilton had no intention, or even concept, of software engineering as a deskilling and reductive force, it isn’t a hard line to draw in retrospect. To reduce software from its eternal representation of formalized logic, algorithms that become evaluable due to magnificent engineering work to instance the conceptual, to instead be subservient to that exact same engineering, restricts our view into the nature of software itself. This isn’t an issue in strictly restricted environments such as engineering proper, but as software abstractions continued to build alongside this restrictive ontical perspective, it became muddled as non-engineering efforts were blindly viewed as such. Unlike engineering, the abstractive nature of software affords it abuse that would be intolerable in true engineering environments.
The Agile Cult
A primary example of this abuse is the Agile software development methodology, or the Agile Manifesto, is an invention of 17 software programmers, and four of its general priorities are given as:
Individuals and interactions over processes and tools.
Working software over comprehensive documentation.
Customer collaboration over contract negotiation.
Responding to change over following a plan.
Certainly not unpleasant preferences on paper, in fact I to this day agree with some of the 12 principles, but agreeance towards some is not a belief in the manifesto whole. Additionally, the four aspects of agile stated here rely on practitioners to follow a form of common sense that is well known to be fallacious. The lack of explicit reasoning within the manifesto means, if we are to take these priorities as truths, certain logical outcomes emerge:
All processes and tools become attached to the interaction of individuals. If an individual refutes a tool, it is to be immediately discarded. If an individual will only use it, it must be tolerated. This can lead to clear logical contradictions.
It is acceptable for software to work despite there being no definitive knowledge as to how.
Agreements are moot, and programmers must be pulled in any direction at any time.
If these are not to be taken as truths, but simply “general guidelines”, then they become immediately useless as the mechanisms of each preference are linked directly to the power structure of the software team. In this case, the language used in the manifesto becomes meaningless dogma that can be used as batons within this power dynamic. Agile, as a framework for software programming, effectively abandons software itself in the name of cooperation with business and customer interests. Given as a means of liberating software programmers from the overburdening processes of Waterfall, it instead fully enslaves it to the whims of external forces. It is the perfect framework to facilitate deskilling.
Agile serves as a noticeable move away from formalized logic as a whole, in favor of heuristic belief systems. These heuristics are then used to quickly iterate, test, and publish incomplete solutions to the customers they claim to value. Whether it be the argument to deliver software frequently, conflicting with the argument for technical excellence, or the defense of design despite the acceptance of radical change, Agile puts the nature of programming into a nearly undefined space underneath the currents of business. It appears then, if software engineering serves to impair the programmer of their ability to solve logical problems, then Agile restricts them in their ability to structure the path to a solution at all.
Software as Idealism
By now I hope that it is clear that I correlate the perceived decay of software directly to the practices endorsed by the programmers who write it. But to return to a more positive, constructive orientation, it is time to review software’s nature in preparation to more concretely define the ways in which it displays a semblance of decay. Software, a recursive logical structure that unravels its own being until a theoretical mode of computation is disclosed, holds itself as a distinct and quite deeply useful form of idealism. By formalizing logic into abstract syntactical structures, the human being has been able to directly control the speed in which ideas are evaluated and expressed, through the use of simulating machines. These logical structures themselves represent models of certain other states of being, or simply model themselves through the recursive nature of itself. Every behavior, bug, state, or otherwise announces itself through an effort of intentional logical abstraction. In this way all software is perfect: It is a representation of the logical system as it was defined.
Bugs, faults, or other perceived issues are merely failings of the programmer to define the system properly—a common problem that every programmer will have to face, and is to be welcomed as ideas themselves are refined. This is especially true if a programmer relies upon the abstractions laid out by others, in which they must fold in the failings of others into their own software system. This deep responsibility of formalization placed upon the software artisan is, in its essence, simply a special case of what it means to program software, what it means to bring formal logic into the space of evaluation. A correct orientation towards this problem does not make the programmer perfect, but it gives them the ability to better refine their formal systems, to write better code. Excessive testing, multi-deployment environments, reproducible builds, are all ways to offset the lack of focus placed upon the logical process of programming. They are themselves not useless, of course, but they are incomplete, and incapable of solving a deeply conceptual, and theoretical issue, of logical systems refinement.
Semblances of Decay
So with all of this said, why does software hold a semblance of decay, if they exist as idyllic logical systems? I have seen a few reasons, including the human element of software engineering and heuristic-based processes, as well as some that appears to come out of the nature of software itself, some that come out of the sociopolitical reality that the use of software is contained within. But regardless, this remains a semblance, apart from any form of decay that comes as part of the nature of an entity.

Firstly, due to the nature of abstraction as chains of interconnected aspects of itself, these chains have a tendency towards sliding, moving further away from an older collective state. These sliding abstractions are, generally, the reason older software may be unable to run on newer software systems, or why one version of software becomes incapable with another. More generally, this sliding is the nature of the logical structure of the software itself changing, one or more links along the chain coming to attach to new points, detach from old, and shifting in form. This is natural in the aptly named living software, the idea that software never reaches a culmination, or any final state, but is continually changed. This changing state of software is human choice, and one largely inspired by capital growth of business, or an attempt to attach to as many other chains as possible.
The second of these semblances is the oppression software faces to the outcome. This was already incidentally referred to indirectly, in the form of software engineering, but I wish to declare it explicitly. Software’s nature as abstractions upon itself, towards the root nature of computation, provides a method for solving problems. In this way, software’s nature is always beholden to an outcome, or some result of complex computation wrapped in endless layers of abstraction. What should be noted, however, is that the software does not decay, the outcome does. Software, if defined truly, will always emit the outcome to the problem it hopes to solve in relation to the input it receives. As humans beholden to time, beholden to a shared world, the outcomes we need are what decay, and change. Software holds no life cycle, our expectations do. This lends itself towards an explanation as to why most modern software is declared living software, as we are incapable of the same immutability software itself is afforded.
Lastly, and perhaps the nastiest of these semblances, is the ways in which particular circumstances arise. Whether it be cosmic rays flipping memory bits, networking failures below the conceptual graph of the WWW, or simply the loss of electricity. Software, as a useful and evaluable form of formal logic, and ideas, are only useful due to practical considerations within the real. Once these real systems fail, software immediately becomes fettered to a simulating machine that is no longer operating correctly. However, this issue exists far less frequently than will be touted in the modern day. Between error-correcting memory, network redundancy along the graph, and other fail-safes, there is an entire industry in keeping the particular away from software. An industry that does a rather good job, and one that showcases that this decay holds no origin in software, but in the simulators that run it.
The Evergreen Fields
If software, as we use it, appears to brown and wilt under the weight of reality, the weight of time and the human condition, one may ask if there’s a reason to view software outside of it. I think there is. Unlike the world, and unlike the human being, software only wilts because we make it, instead of coming about on its own accord. We’ve already seen what happens when we no longer make it decay: High-level programming languages, the allowance of conceptual work being done on particular machines, and the World Wide Web, a conceptual network that does not birth the limitations of any single point-to-point protocol. There’s more, to be sure, and in fact nearly all of modern software rests upon a bed of evergreen. So why should we continue to shackle it to decay, to concepts it has no relation to, if we already see it thriving without them.

The simple fact that code generation tools, AI or otherwise, work at all is a testament to the evergreen nature of software. These extremely high-order systems emit, themselves, code that remains conceptual, relinquishing the programmer to that of a data entry specialist. While I will hold to my political and psychological arguments on how these systems do openly deskill labor, eroding cognition, it does so in the domain of ideas, the realm of the transcendental, it need be stated that their mere existence comes about due to software’s nature of permanence. Not only could these systems not operate without the evergreen nature of software itself, what it emitted would be unusable if not saved by the bedrocks of idyllic systems that came before it. There are no dead abstractions, merely abandoned chains, chains that have merely gone unused as the world has moved on. For we’ve built this transcendental world of software, and we lay upon it atop a field of green.
Therefore, software is perfect, the world is not.


