Forensic Analysis of “No Silver Bullet”
(Image by Lee Ufan)
Our task — Software engineering has a long and hallowed tradition of uncritically evaluating and citing evidence . It is our keenest joy to snatch a quote or cite a statistic without any critical evaluation of the source. As far as one might like to dig into the past this is the way it has always been done, and maybe the way it always will be done. Perhaps in the early days the fight for legitimacy was too pitched. The desire for actionable standards too high. As a matter of survival there was no choice but collective agreement and the mask of consensus. At this late stage, however, this mask runs the risk of solidifying and becoming confused with what lies beneath it. As a new generation of software engineers, if we are ever to make software our own it is our job to look below all masks, to become experts in the discernment of the the false lines and exaggerations that betray all masks, and…perhaps…to create our own masks.
The two types of reading — In reading those whose legacy and ideas we are eager to inherit and deploy for our own purposes, it does one good to pause for a moment and to ask a simple question — Where might the author (and I) have gone wrong? This attitude towards reading, or its lack, separates readers into pantomimes — those who merely accept and regurgitate — and philosophers — those who weigh and evaluate. If anything is primarily responsible for the endless proliferation of bad ideas and bad thinking, it is the lack of properly philosophical reading. And as Steve Yegge said a decade ago, software badly needs philosophers.
Which one…? — What is the subject of inquiry in Fred Brooks’ “No Silver Bullet”? In the abstract it is the essential and accidental tasks involved in “software construction”. Later the difficulties “inherent in the nature of software”. Then “the essence of a software entity”. Finally, “the essence of modern software systems”. Are all of these simply equivalent? It’s impossible to see how they could be. Software construction is the activity that produces software entities, and much as writing is not the same thing as a book and construction is not the same thing as a building, software construction is not the same thing as software. So then, these two things cannot have the same “essence” in the Aristotelian sense, or they would be intellectually indistinguishable. Similarly is the essence of software the same as the essence of a modern software system? This lack of clarity persists, and upon reading the list of the four essential properties, it is clear Brooks has bungled together these different objects in his analysis. What are the consequences of this? What else has he bungled?
What are we measuring? — The overall claim and prophecy of the essay is quantitative: the essential aspects of software ensure we will never see an order-of-magnitude increase in either productivity, reliability, or simplicity. Yet, how are we to measure this quantitative claim? How are we to measure each of these individual properties? Is productivity measured in LOC per hour, Function Points per hour, or something else? Is reliability measured in Mean Time To Failure (MTTF), Mean Time Between Failures (MTBF), or Mean Time Between Replacements? Is simplicity an assertion about cyclomatic complexity, Halstead complexity? All of these measures are contentious and all would result in differing outcomes for Brooks’ central thesis. We are never told which ones he means. Maybe he means all of them? To make an empirical claim without clearly grounding it is a slippery rhetorical move. It allows Brooks to wiggle out of any attempt to validate or invalidate his claims. Such a move could only be convincing to those who are inclined to believe his statements anyway, and who hasn’t been inclined to believe them so far?
Essential/accidental confusion — Essence, in the Aristotelian sense, is what something is. For example, a waterfall = water + falling. A puddle may have water, but it’s not falling and so it isn’t a waterfall. Similarly, a rock may be falling, but it isn’t composed of water, so it too isn’t a waterfall. If we are to understand this essay correctly, Brooks appears to be stating software = complexity + conformity + changeability + invisibility. So if we write a program that isn’t complex it isn’t software? If a program isn’t subject to demands for change (like many of my GitHub projects), it isn’t software? If a program doesn’t have to conform to arbitrary social institutions it isn’t software? Yet we have endless examples of software without one or several of these properties. My first hello world program, that I have on a USB drive, isn’t complex, didn’t have to conform to any arbitrary human institutions, and wasn’t subject to any demands for change. Yet it is still software.
In short Brooks wields the essential / accidental distinction clumsily. If we are talking about software these properties don’t especially make sense. If we’re talking about software construction then perhaps they make more sense. But as we’ve seen, the object of inquiry isn’t exactly clear.
A pure mental construct? — We are told by Brooks that a “software entity” is “a construct of interlocking concepts” whose translation and birth in a machine is a monstrous and botched affair introducing all manner of messy “accidental” artifacts. What he seems to want to say is that a “software entity” is merely the translation of a complete mental representation in the mind of the programmer into a form suitable for machine execution. That is, that software is mental first, and physical only accidentally. First, such an assertion seems to require as a prerequisite the belief in the infinite powers of the human mind to fully grasp arbitrarily complex software entities. Who among us actually believes this? Furthermore, can we even imagine a piece of software that did not have to contend with programming languages, physical hardware limits, and other such factors? While there is certainly an interplay between the mind of the creator and the software created, that interplay and its results are not the same thing as purely mental software or interlocking conceptual formations. Software is physical, even if obscurely. It exists in the real world, among uneven sidewalks and puddles choked with fallen leaves, and must contend with all the confounding factors such an existence entails. To take Brooks at his word, and to only focus on the mental aspects, is to impoverish our concept of software.
Pure mental temptation — What tempts us software developers to define software as purely mental? Brooks is certainly not the only one to posit such a thing. Yet I haven’t found a soul yet who has critically questioned this claim. Perhaps it validates our frustrations with the confounding factors we are always struggling against — machine limitations, human error, programming language quirks, etc. — and reassures us these are non-essential tasks. It lets us contend our job is constructing pure thoughts and not safeguarding their real world implementation. When we think this way, we let ourselves off the hook for the mistakes and disasters we create in our working lives, and allow ourselves to pretend we can safely focus on the parts of the profession we like while ignoring those we don’t. That we can do this without harm to ourselves or our craft. Yet the surge in UI/UX research and practice has been directly to counteract this tendency. To reintroduce the “accidental” and “arbitrary” needs of real people back into software development. Thinking of our craft as pure thought is dangerous. It can easily allow us to fall into the habit of thinking that software construction is a process of pure mathematics and not a voyage of discovery — a voyage where each project is a trek into terrae incognitae, whose fate is decided by the navigational talents of its captain and the discipline of her crew. It tempts us into thinking there is no need for preparation for the journey or the proper vetting of the crew. It even tempts the more naive among us into faith in “the one true way” to develop software.
But, alas, all this temptation is a poor argument in favor of adopting a belief.
Fourfold essence — How are we to understand Brooks’ fourfold essence of software? The first three: Complexity, Conformity, and Changeability could easily be folded into one — Complexity. This arbitrary proliferation of concepts (in violation of the DRY principle) is our first signal that something is being done clumsily here. Is complexity truly essential to software? Simple experience is enough to show us that there is a rank ordering of software complexity — that software can be both simple and complex. So why has Brooks made only complexity essential? The answer seems to be because it allows him to easily make his empirical claims. First about simplicity gains, and via that route about productivity and reliability gains. In short, it is a sophistic move convenient for his argument but not for gaining actual insight about software.
Invisibility, however, the hiddenness and non-representability of software — this seems to be the one true essential aspect captured here. That software hides, and that every view and perspective into a piece of software requires a mediating apparatus — a flow chart, a debugger, a keyboard, a screen, a web browser — and that each of these provides only partial and provisional access and insight. That software is intensive and not extensive. All of this seems to us to be well worth exploring further. Yet Brooks has left it largely unexplored except insofar as he can apply it to making his prophecy.
Where does this leave us? — Removing the superfluous Aristotelian baggage, the essay becomes something simpler and less profound. The argument: “Why can’t developing software be simpler? Because it’s complex”. Only stated much more circuitously and from behind such fog and false Aristotelian barricades that it seems to issue forth with much greater authority.
Éminence grise — Why has this essay been cited and circulated so uncritically? First, we could point to its source. Fred Brooks is by and large a respectable man, with experience leading some of the earliest and largest software projects. Such experience lends one a radiant and imposing authority and such authority tends to produce the impression of infallibility. Our respect for his breadth and depth of experience, and the seeming poverty of our own in comparison, leads us to question our basis for criticism, and so we never try. Then there is the intriguing Aristotelian underpinning. Programmers, being on the whole industrious folks, have little acquaintance with philosophy in their day-to-day work, and some (perhaps most) even believe philosophy to be nothing more than a refuge for useless over-thinking and a graveyard for dead, superfluous ideas. Aristotle, however, commands an almost mystical respect and recalls the musty halls of the highest institutes of erudition. So, when a philosophical idea from such a source is put to the task of making a point about programming, nothing produces more awed stares and gasps of disbelief. Besides – the accidental/essential distinction is simple and unproblematic right? Surely Brooks, a man of such erudition as can cite Aristotle, could not have made a mistake here at the outset, in the selection and deployment of his concepts. Finally, there is Brooks general style and approach. His entire corpus is a tempting touchstone for frustrated software developers. In every essay we find him comfortably reassuring us that the failures of our projects — the painful lessons and foolish missteps — are not our fault, but an unavoidable, unfixable by-product of the work itself. Its essence in fact! We could not have known or done any better than we (or rather he) did. The temptation to believe him…and to get our bosses to believe him…is too strong for many of us to resist.
The first step in overcoming someone who has exerted such a grey eminence over software is to ask where their thinking has gotten us? Has it improved software development practice? Has it improved our understanding of software? The certainty is that many of us are still dissatisfied with the state of practice. We sense that we have gotten it wrong somewhere. That we are missing crucial insights. If we are to move upwards and forwards and make software our own, then we must unload the existing baggage. This means ruthlessly questioning those earliest and easiest insights about software.