This treatise answers three questions. The first is whether the software development process can be adequately explained by hermeneutical and rhetorical theory. In our discussion of programming practice in Chapter 2, we saw a real-life example of a development process at the small computer game company Tribeflame. Section 4.1 analysed Tribeflame’s process using the theories and concepts of mainstream programming, and we saw that these theories were of limited usefulness. The failure of mainstream theories to explain a real programming process is easily explained by remarking that, although the mainstream theories often are taken to be universally valid, they represent a limited perspective and do not apply without modification outside the range of practices for which they were developed.
With this in mind, Section 4.2 presents a hermeneutical analysis of Tribeflame’s process. We see here that hermeneutical concepts are able to explain some features of the process that were difficult to understand using only mainstream theory.
First, the process, which initially seemed to be strangely unstructured, turned out to have a definite structure, consisting of a continuous oscillation between working alone and working together, and between trying out things and reflecting on experience. We saw that this structure could be explained by the concept of the hermeneutical circle. We also saw how hermeneutical concepts such as authority, tradition, and prejudice could explain the presence of, and relationship between, different parts of the process: leadership, the expertise of the developers, experiences of outsiders trying the game, meetings, and so on. Finally, we saw that the process is first and foremost driven by its application – to make a game that is fun to play – and not so much by any abstract idea of what the process should be like.
To provide a contrast with the particular example of a small computer game company, Chapter 5 describes the processes used by some companies in safety critical industries, which make heavy use of mainstream software engineering theory. The hermeneutical analysis of safety critical development processes revealed them to be primarily bureaucratic processes that are as much about producing documentation as about programming.
Again, hermeneutical concepts such as authority, tradition, and prejudice proved to be helpful in understanding the processes. The hermeneutical circle is useful for explaining the mutual influence that industry standards and development practice have on each other. Just as game programming is driven by the concept of fun, safety critical programming was seen to be driven by the concept of safety, albeit a very distinct notion of safety that is deeply connected with the bureaucracy of safety standards.
Chapter 7 returns to Tribeflame and presents an analysis of a small part of the source code of a computer game. It is shown that the code is not only instructions to the machine, but is also meant to be read by people and is therefore amenable to rhetorical analysis. The analysis shows how rhetorical concepts can be used to understand how the code is constructed and how it should be read. Examples of rhetorical aspects of program code that are beyond purely technical analysis include the use of comments, conventions for code, and the purpose behind code lines.
In conclusion, Chapters 2, 4, 5, and 7 demonstrate that software development practices can indeed be explained adequately with hermeneutics and rhetorics, and that these forms of analysis can tell us things that escape the narrower viewpoints of the programming theories of software engineering, Agile development, and computer science.
The second question this treatise seeks to answer is whether the differences between different kinds of programming practices can be explained by cultural theory. Chapter 6 addresses this question, and Section 6.1 explains the concept of cultural form. This is a cultural analytical concept that enables us to carry out a comparative investigation of different forms of programming practice.
In Section 6.2, Tribeflame’s form of game programming is compared with forms of safety critical programming. We saw that game programming is a cultural form that is primarily subject to market constraints. It is a form that satisfies a demand for creativity and does not demand much communication with outsiders about the details of the work process. Safety critical programming is a form that, in its most common manifestations, is also subject to market constraints, but it is even more pressingly subject to the constraints of a highly regulated bureaucracy of standards. It is a form that conserves tradition to a high degree, and creative expression is carefully regulated by rules. Communication with outsiders plays an important role and is made easier through standardization of the process.
Section 6.3 compares different forms of safety critical programming to each other. We saw here that companies in the safety critical industries are far from homogeneous. Companies can play many different roles within their respective industries, and there are variations in the strategies employed to deal with the demands of the bureaucracy of standards. This shows that the context of a programming practice is essential to understanding the practice, because different forms can appear in similar circumstances and similar forms can appear in different circumstances.
Chapter 6 thus shows that differences between different kinds of programming practice can indeed be explained by cultural theory, and that cultural form is a conceptual tool that can help us understand differences and similarities between practices.
The third question that this treatise seeks to answer is, what are the practical implications of a hermeneutical and rhetorical understanding of programming? First, it is important to note that philosophical hermeneutics claims to be true of all understanding, which means that it is both epistemological and ontological. This means that hermeneutics is not a method or a theory that will produce a certain result; it is a way of describing what people always do when they understand something, whether they are conscious of it or not. Thus, we can look hermeneutically at what programmers do regardless of whether the programmers themselves know about hermeneutics.
Programming has many different aspects, and we have touched upon some of them in this treatise: economic aspects, technical aspects, management aspects, mathematical aspects, and others. Consequently, there are just as many different ways to approach the study of programming. These aspects are all cultural, insofar they involve human perception and human use of computers. Cultural theory therefore provides a starting point for the study of programming that can encompass all the other approaches. Culture itself can, in turn, be regarded with hermeneutical and rhetorical perspectives – these are ways of looking at cultural expression, not replacements for cultural theory.
Throughout this treatise we have looked at programming phenomena from a hermeneutical perspective. These phenomena include the mainstream theories of programming, and as such these theories have implicitly been judged according to hermeneutical criteria. This means that hermeneutics is used as a kind of meta-theory: a theory that provides a certain view of the world, according to which other theories are judged.
However, it is important to understand that the points made by hermeneutical theory are for the most part quite obvious. Hermeneutics is not some kind of exotic world view that is incompatible with analytical thinking. On the contrary – it is a call to return to the essentials of science: to observe a phenomenon, then seek to understand it, and finally to test the results of that understanding, which may lead to observing the phenomenon in a new light, and so on. Science is thus a circular process of experiencing and understanding.
It is essential to hermeneutic theory that understanding and practice are inextricably linked and conceptually constitute each other. Likewise, subject and object constitute each other; the subjective perspective cannot be defined without referring to the objective one, and vice versa. According to hermeneutics, from the time of Descartes philosophy has been mistaken in believing that subject and object can exist independently of each other.1 In modern philosophical thought, subjectivity is typically regarded as epistemology, the domain of the subject being action, language, and thought. Conversely, objectivity is seen as ontology, the domain of the object being occurrences, observations, and things. From a hermeneutical point of view, the traditions of computer science and software engineering replicate this philosophical mistake by focusing on objectivity to the exclusion of subjectivity. This, in turn stems from a belief that subjectivity and objectivity are opposites.
In addition, there is a separation between understanding and practice, because of the belief that true understanding can come about by theoretical speculation that may be informed by practical observations but is not itself intimately connected to practice. Latour has warned against this belief, noting that theory cannot be properly understood in isolation: “Speaking about theories and then gaping at their ‘application’ has no more sense than talking about clamps without ever saying what they fasten together, or separating the knots from the meshes of a net.” 2
To be clear: it is not uncommon within computer science to have exaggerated ideas about how much theoretical results can accomplish in industry.3 On the other hand, it is not uncommon within software engineering to believe that it is possible to control every significant aspect of the software development process as long as the right engineering principles and theories are applied.
From a hermeneutical point of view, both of these ideas are mistaken, and stem from the schism between subject and object that computer science and software engineering have inherited from modern philosophy. The consequence is that computer science and software engineering thinking has a slightly unreal quality to it, as exemplified in the software paradox described in Chapter 1, in which academic software research, despite being hugely successful, is never quite satisfied with its own results.
Agile thinking is different because it preserves a close connection between understanding and practice, and between subjectivity and objectivity. For agents in an Agile project, it is only possible to measure their progress objectively because they have the right subjective approach.4 Thus, Agile thinking is much more in line with hermeneutical thinking and seems to be an approach whose philosophical foundations are not, in principle, far from the foundations of hermeneutics.
So what is the consequence of these theoretical distinctions for programming practice? The answer is that theory is important for practice. Good habits follow from good principles, and bad habits follow from theoretically unsound principles, such as maintaining an untenable opposition between subjectivity and objectivity. Hermeneutics tells us that theory is unavoidable, in the form of prejudice. If one has “no theory”, this does not mean that one has no prejudice – it means that one has a non-conscious, implicit theory that might be unsound, which is hard to discover as long as it remains unarticulated.
The argument made in this treatise is essentially an argument against reductionism. Reductionism is the belief that in every situation, the important aspects can be reduced to a small set of logical principles and rules for how to proceed. Hermeneutics tells us that reductionism is not tenable as a first principle. Reduction is a choice that must be carefully weighted against other choices in the particular situation. This does not mean that thinking cannot be stringent: a true hermeneutic analysis, for example, can never be reductionist, but it must be stringent. It does mean, however, that practice should always include some form of deliberation over goals and application.
The crucial contribution of hermeneutics in this respect is that it points out how very important tradition is in evaluating the goals of a practice. Looking at tradition is a way of discovering the original intentions of the practice, and these original intentions will heavily influence the theories and assumptions of a practice – as demonstrated, for example, by the heavy reliance of safety critical programming on assumptions that stem from the engineering tradition of regulating practice by standards.
2 Latour 1987 p. 242.
When we look at the hermeneutical analysis in Chapters 4 (Game programming) and 5 (Safety critical programming), we notice that the concept of effective history is the hermeneutical concept that plays the smallest part in any of the programming processes. This is no coincidence. Effective history is a concept that expresses awareness that knowledge is historical and that the motives for knowledge have consequences. Since mainstream programming theory is to a large degree based on modern philosophy, it is also somewhat ahistorical, which makes it difficult for its adherents to assess its own history. Software engineering and computer science in particular are ahistorical to the degree that they embrace universal principles rather than historical context.
Historical consciousness is important because it underpins the values that are embodied in a company’s culture. Leslie Perlow’s sociological study of corporate culture among software engineers shows how short-sighted values can be detrimental both to productivity and to the employees’ satisfaction with their work.1 In an experiment that attempted to change software engineers’ use of their work time, she has also shown how changes in routines and behaviour have no lasting effect unless the underlying values are changed.2
What, then, do programmers need to do in order to be able to take advantage of the insights of hermeneutical theory? They need to learn to see themselves as cultural agents: that is, as part of, and carriers of, historical tradition. They also need to understand that a large part of their work consists of interpretation – interpretation of code, requirements, situations, and what it means to be a good programmer.
The comparative cultural analysis provided in Chapter 6 (Programming culture) shows us that all understanding of programming has to take the context into account. This means that there are no universal principles for good programming that are independent of the goals of the work. In other words, “best practice” is always dependent on context. Programming involves making trade-offs and choosing what is best in the current situation; and what is best in a situation cannot be determined beforehand with the knowledge of only a limited set of parameters. For example, it is important to develop programs without errors. But the level of error tolerance varies. Web pages will have more errors than aircraft guidance systems because it would be too expensive to find and remove them all. Likewise, the amount of upfront design that is sensible varies between different kinds of projects.
It follows from this that part of the work as a programmer is to figure out what the work actually consists of, what the real goals of it are, and how these are effectively pursued. The programmer’s ability to do this can be divided into three aspects:
• Technical ability – programming skills.
• Hermeneutical ability – ability to interpret and understand.
• Rhetorical ability – ability to express oneself properly.
This invites the question: if programming always has to be seen in a cultural context and therefore has no universal principles, is it even possible to say something general about programming, as this treatise tries to do? It is. The key to this is recognizing that programming is rhetorical in its essence. Like a speech, a program is a form of expression, and it is impossible to give a universal method for how to write a good speech or a good program – it depends on the audience.
However, that does not mean that we cannot learn something about the general principles that underpin programming expression – by studying good programs, for example. Hermeneutics and rhetorics give us some conceptual tools to understand programming practice and help us discriminate and find out what we can learn from a given programming example.
A consequence of the conclusions drawn above is that that there are limits to what research and theory can do for practitioners. A scientist who is far removed from actual practice cannot solve every practical problem – practitioners understand their problems better than do academics and researchers. With this insight, we have come full circle to the story of the Tower of Babel that Brooks uses as an explanation in his essays on software engineering.3
Brooks views the Tower of Babel as an engineering project that failed because of lack of communication. Hermeneutic theory shows that Brooks is wrong in his interpretation, and that better communication or engineering principles would not have allowed the “engineering project” to succeed: the tower fell because mankind is fundamentally limited in our knowledge and abilities, and this is the ontological aspect of hermeneutics. God’s destruction of the Tower was not revenge but a simple acknowledgment of this limitation: man is not God and therefore cannot hope to have perfect knowledge of anything. We have only imperfect knowledge.
Imperfect knowledge is the domain of interpretation and hermeneutics. The most important contribution offered by this treatise is to point out how hermeneutical theory can provide a richer understanding of programming. The insights into programming that are presented in the previous chapters are the result of applying hermeneutical analysis to programming practice. The analyses themselves are examples.