When I use a word, it means just what I choose it to mean—neither more nor less.
It is the fate of every vocation to be misunderstood by outsiders, and engineering is by no means an exception: ‘Most people think engineers do things in a very mechanistic way. … They don’t seem to have any idea of the creativity and ingenuity in engineering.’2 [2 Tom Connor, quoted in Dietrich Georg, ‘Getting People’s Perceptions Closer to Reality’, Civil Engineers Australia (May 1996), pp. 25–26.] To the public at large the engineering method is just following an impenetrable set of scientifically predetermined instructions, the engineer a ‘soulless apparatchik’3 [3 K. Strauss, ‘Engineering Ideology’, IEE Proceedings Vol. 135(A5) (1988), p. 262.]—the sort of person who might regard the employee-feeding machine from Chaplin’s Modern Times as a splendid labour-saving device. It is as if engineers had created such machines in their own image.
Software engineering has an even bigger perception problem, though: it is widely misunderstood even by insiders. Civil engineers who fail to recognise their work in the typical engineering mythology may be certain that, by definition, it is the public perception at fault. What is engineering if not what civil engineers do? By contrast, without some traditional engineering experience for guidance a software developer in the same predicament cannot rule out the thought that software development is somehow unlike engineering—or, worse, that we are doing it improperly.
Certainly there are those even within the engineering profession who do subscribe to the outsider view. Software developers are engaged in the exact same debate about the nature of our work as engineers in the more traditional fields are about theirs. The difference is that while software developers disagree about how software development ought to work, most accept without question the mechanistic theory of how engineering works—the engineering method as ‘adherence to a specified morphology’4 [4 Billy Vaughn Koen, Discussion of the Method (Oxford University Press, 2003), p. 83.]. The morphology with which we are all familiar is known as the Waterfall Model,5 [5 Winston W. Royce, ‘Managing the Development of Large Software Systems’, Proceedings of IEEE WESCON (1970), pp. 1–9. Only those who have not read Royce’s paper could see it as an endorsement of the Waterfall Model as such.] and the idea that all ‘real’ engineers follow it is practically an article of faith.6 [6 For example, see Philippe Kruchten, The Rational Unified Process (Addison-Wesley, 2004), pp. 53–54.] It would come as a shock to most in the software community to discover that this is not really the way engineering works. Proponents of a mechanistic kind of ‘software engineering’ have been allowed to define the term in agreement with their own prejudices.
At the root of the unwillingness of the software community to accept software development as a form of engineering lies a single misconception, inexplicably shared across ideological boundaries. To see what it is, we must first define a little terminology.
The technical term for the output of an engineering process is an ‘artefact’. The artefact is only nominally what customers pay for. The actual product is some experience that occurs between the artefact and the user.7 [7 End users sometimes make this error. Stories abound of customers who purchased a product that met their needs, but felt ripped off because the artefact seemed insufficiently impressive.] This is what Pirsig was referring to when he wrote that ‘Quality is not a thing. It is an event.’8 [8 Robert M. Pirsig, Zen and the Art of Motorcycle Maintenance (William Morrow, 1974), p. 233. This is not the final form of Pirsig’s Metaphysics of Quality, but it marks a breakthrough in his thinking.] A bridge is an artefact but it is not the product. The product is not getting wet.
A design document—for example, a set of engineering drawings—describes how to construct one or more artefacts, but is not itself an artefact. A building is an artefact; the product it provides, or one of them, is (again) not getting wet.9 [9 Since the dawn of history, humans have been willing to forgo resources in consideration for not getting wet.] You can get some of the effect by holding a set of working drawings above your head, but beyond a certain point—probably a stiff breeze, anything more than a light drizzle or when your arm gets tired, whichever comes first—you are bound to want the actual building.
Our problem arises when people mistake software source code for an artefact. Source code is not an artefact because the user does not interact with it; there is no product experience created in this way. Source code is a design document because it describes how to construct the true artefact, which is the machine-executable code.10 [10 Interpreted languages make this boundary harder to discern. Nonetheless, the step of translation to machine code always exists.] Source code is the map, not the territory.
This point is critical to the understanding of software development because, as Jack Reeves explained in 1992, it identifies our work as designing rather than constructing (or, for that matter, manufacturing) software.11 [11 Jack W. Reeves, ‘What is Software Design?’, C++ Journal (Fall 1992).] Construction is an activity performed by compilers and the associated infrastructure around them—not for nothing do we call this the ‘build system’. We are software engineers, not software construction workers.
We should not see engineering as a metaphor for software development. Each branch of engineering has its own set of heuristics, moulded in part by the nature of the materials with which it works, and software engineering is naturally no exception. Chief among its unique features is that software construction is both fast and cheap—often taking on the order of seconds to minutes, generally with zero marginal cost. Most engineers do not have the luxury of such a short feedback loop between their designs and the finished artefacts. It would be inappropriate for software engineering to simply adopt a morphology from another branch of engineering, even if such a thing existed. The common thread uniting those branches is not some shared morphology but the fact that none is capable of being reduced to such a morphology.
Those who see software development as mechanistic in nature invariably also mistake it for a construction activity. Usually these people will say ‘Software engineering is not yet a true engineering discipline’,12 [12 Mary Shaw, ‘Prospects for an Engineering Discipline of Software’, IEEE Software Vol. 7, No. 6 (November 1990), p. 15.] but that they hope it will eventually become one.13, 14 [13 Anthony I. Wasserman, ‘Toward a Discipline of Software Engineering’, IEEE Software Vol. 13, No. 6 (November 1996), pp. 23–31.] [14 Christof Ebert, ‘The Road to Maturity’, IEEE Software Vol. 14, No. 6 (November 1997), pp. 77–82.] The obstacle is always a lack of ‘rigour’, the solution more ‘discipline’.15 [15 Harlan D. Mills, ‘Software Development’, IEEE Transactions on Software Engineering (December 1976), pp. 268–269.] Apparently the best way to instil this discipline may to threaten the practitioner with imprisonment.16 [16 Steve McConnell, ‘Y2K: Countdown to Certification’, IEEE Software Vol. 16, No. 3 (May 1999), pp. 4–7.]
The most prominent example of this school of thought is the unfortunately-named Software Engineering Institute at Carnegie Mellon University. It is funded by the United States Department of Defence, whose bizarre procurement policies treat designs and artefacts identically. Unsurprisingly, the SEI tends to label ideas that fit its patron’s worldview as ‘software engineering’, even when they may be the opposite of established engineering practice.
One form this takes is the fetishisation of reliability over all other properties of a system. To the mechanist, the fact that software sometimes crashes is damning evidence that software is not yet an engineering discipline. In part this is coloured by an unjustifiably narrow view of the range of work in which engineers are engaged. Pencils and paperclips break all the time.17 [17 Henry Petroski, Invention by Design (Harvard University Press, 1996).] Even in areas where safety of life is an issue—popularly assumed to be the sole province of engineers—failures still occur absent any negligence on the part of engineers.18 [18 Henry Petroski, To Engineer is Human (Vintage Books, 1992), pp. 5–6.] To assume that software is unique among humanity’s creations in its tendency to fail is to ignore both the evidence and the more prosaic explanation: that the cost to society of ensuring it never can usually outweighs the cost of taking the risk.
The temptation is strong to declare that this reliability-obsessed process is not engineering at all, but it must be resisted. I do not claim that all software is engineered, at least in the modern sense. Yet so long as we are developing software within a social context, where the finished artefact has users other than its designers, we can scarcely escape the conclusion that what we are doing is engineering. Still, I would certainly argue that methodologies that disregard the expenditure of resources are the antithesis of good engineering.
If I wished to be kind to the SEI, I would note only that the context in which they operate is not shared by most—or even many—software engineers, and that they could do us all a favour by choosing a name that does not imply that they represent the only way of doing software engineering. If I were feeling less charitable, I might add that even in their chosen context their methods have proven conspicuously unsuccessful.
On the other side of the fence, many of those who reject the mechanistic theory of software development nevertheless mistake the source code for an artefact just the same. At the nexus of these two ideas lies the concept of software development as ‘craft’. Recognition that all software development is unpredictable design work and belief that software is constructed by humans can be reconciled only in a medieval model19 [19 Andrew Hunt and David Thomas, The Pragmatic Programmer (Addison-Wesley, 1999), p. xx.] of software development, in which the design and construction of artefacts are not separate activities:
The technology of the middle ages was the technology of the artisan. … [In the Renaissance] the artisan has been split up into his components, the engineer and the worker.20 [20 José Ortega y Gasset, History as a System (Norton, 1961), pp. 151, 155.]
Seen in this light, the epitome of the software craftsman is to be found in the story of Mel, the ‘Real Programmer’, who famously programs directly in machine code. Mel’s legendary technical skills have made him a hero to many, yet he seems completely isolated from the economic consequences of his work.21 [21 ‘Whether or not this actually sold computers was a question we never discussed.’] It exists in a vacuum, outside of any social context.
Something is always lost when the engineer is separated from the worker, but such transitions occur because these losses are outweighed by the gains. The combined efforts of all the master craftsmen in Florence might never have been sufficient to complete the cathedral dome had Filippo Brunelleschi—or some other engineer—not devised a way to build it.22 [22 Richard P. Gabriel, ‘Designed as Designer’, pp. 11–12.] In software such a split was already in evidence by the 1960s, simply because the methodology Mel used to craft his blackjack program imposed a very low upper bound on software’s transformative power. In the intervening decades the workers—‘programmers’, in the contemporary sense of the term—have been automated out of existence. The revolution will not be televised; it already happened and you missed it.
To regress to a guild of medieval Real Programmers does not strike me as a goal to which we should aspire. We need not do so if we recognise that source code is not an artefact and accept our role as software designers and not software builders. Engineers, freed from the need to personally construct their artefacts, take no less care in and derive no less pleasure from their work than did the craftsmen who preceded them.
In all our discourse about software engineering, we have failed to challenge the assumption that it could only be brought about through the application of ‘rigour’, ‘discipline’ and government-mandated participation in a monoculture that treats every line of code as if lives depended on it, on pain of imprisonment, regardless of context. This vision may be to some a shining beacon of hope, to others a nightmare that makes Kafka look like Disney. But the essence of engineering is not to be found in these things. To be an engineer is to strive for change in a world where resources are limited.
We are the heirs of an engineering tradition as old as civilisation, but Eden is burning. The name of our profession itself—the very core of our identity—has been co-opted by some of the most dysfunctional organisations in society and redefined in ways that conflict with our values. In order to claim our birthright we must first recapture what it means to be a software engineer.