The computer revolution is a revolution in the way we think and in the way we express what we think. The essence of this change is the emergence of what might best be called procedural epistemology--the study of the structure of knowledge from an imperative point of view, as opposed to the more declarative point of view taken by classical mathematical subjects. -- H. Abelson and G. Sussman (in The Structure and Interpretation of Computer Programs)The Open Organizations Framework is the product of several different kinds of thinking. One of them is a relative newcomer in the field of social theory; because of recent historical developments, it is now an influence in many projects for social change. I believe it fills a major gap that has crippled many movements for social transformation, and therefore deserves a closer look. This way of thinking can be called the engineering approach. It is not an attempt to fulfil the dream of some 19th-century thinkers, whose naive optimism about the human sciences led to the belief that the principles of human nature would soon be discovered, allowing theorists to identify the structures that should be imposed on society. Instead, today's engineering approach is a way for a group of people to engineer their own working practices, by means of a dialogue between needs and principles, between practice and theory, on equal terms. It therefore offers a way to close the age-old gap between academic social theory and the practice of social movements. Engineering in general involves a close interaction between theory and practice compared to many other academic disciplines, for several reasons:
In other fields, people have to cope with the perversity of matter. Of physical objects. Matter does what it is going to do. You can try to model it and if the actual behavior doesn't fit the model then tough on you, because the challenge is to make physical objects that really work. If I wanted to put an 'If' statement in a 'While' statement, I don't have to worry about whether the 'If' statement will oscillate at a certain frequency and rub against the 'While' statement and eventually they will fracture.... I don't have to worry that if i run this program in a salt water environment that the salt water may get in between the 'If' statement and the 'While' statement and cause corrosion.... I don't have to worry when I write the program, about how I am going to physically assemble each copy and whether I can manage to get access to put that 'If' statement inside the 'While' statement.... So many problems that we don't have to worry about in software.... It is fundamentally easier to write a program than to design a physical object that's going to work. This may seem strange because you have probably heard people talking about how hard software is to design and how this is a big problem and how we are going to solve it. They are not really talking about the same question as I am. I am comparing physical and software systems of the same complexity, the same number of parts. I am saying the software system is much easier to design than the physical system. But the intelligence of people in these various fields is the same, so what do we do when we are confronted with an easy field? We just push it further! We push our abilities to the limit. If systems of the same size are easy, let's make systems which are ten times as big, then it will be hard! That's what we do! We make software systems which are far bigger in terms of number of parts than physical systems. A physical system whose design has a million different pieces in it is a mega project. A computer program whose design has a million pieces in it, is maybe 300,000 lines, a few people will write that in a couple of years. That is not a particularly giant program. GNU Emacs now has several million pieces in its design I think. It has a million lines of code. This is a project done with essentially no funding whatsoever. Mostly done by people in their spare time. There is another big saving. If you have designed a physical product, the next thing you have to do is design the factory to make it. To build this factory may cost millions or tens of millions whereas to make copies of the program, you just have to type 'copy'. The same copy command will copy any program. You want copies on CD then fine. You burn a master CD and send it off to a CD plant. They will use the same equipment which will copy any contents on a CD. You don't have to build a factory to make this product. There is tremendous simplification and tremendous reduction in costs of designing things.... The result is software really is different from other fields. Because we are working with mathematical stuff, designing something is far, far easier and the result is that we regularly make systems which are much, much larger and do so with just a few people.It is difficult to make something that is both very complex and perfect. Many if not most programs do a job so complex that no single person can remember the whole thing in detail. Just thinking through everything a typical program does, step by step, would take years. Programmers have always been acutely aware of the danger of runaway complexity, of not being able to understand their own work. Moreover, the environment in which programs work changes constantly. Computer programs have to be designed to allow for this change. A great deal of work has therefore gone into strategies for managing complexity and change. These strategies have two aims. The first is to make the most of our knowledge and skills, in order to minimise the chances of making costly mistakes. The second is to organise practical processes themselves -- the work that programs must do -- in such a way that we are able to grasp them, and so they can adapt to change without having to be redesigned from scratch. One way to make a complex body of knowledge easier to deal with is to write it all down. How you write it down, of course, makes a big difference. Accordingly, one class of strategies for dealing with complexity involves the use of language and communication. It is often said that computer science, like many academic disciplines, is not relevant enough to the practical problems that practitioners face. As in other fields, there is a certain amount of distrust between those who are mainly practitioners and those who are mainly theorists. However, one area of fruitful cooperation has been language. Natural languages are not suitable for writing computer programs, because they leave too much room for interpretation. Since computers cannot think for themselves, they need to be told exactly what to do. This forces the programmer to have an absolutely clear notion of what is to be accomplished and how; no details can be glossed over. The vocabulary of early computer languages only allowed people to describe minute details of a process, one after the other. It was therefore easy to miss the forest for the trees. Nowadays, this statement (also from The Structure and Interpretation of Computer Programs) is a truism:
Programs must be written for people to read, and only incidentally for machines to execute.Like any good work of nonfiction, a good program should be organised in a way that makes the main points clear, and makes it easy to find details of interest. Clarity is essential for the program's original authors, so that they can check their own work and assure themselves that it makes sense. A successful program nearly always ends up being maintained by people other than its original authors; these maintainers need to be able to understand the program well enough to fix bugs and add new features. Clarity is therefore essential for them, too. It is mainly this need for clear structure that has motivated the evolution of computer languages. As people have devised concepts that enable our human minds to understand complex, changing processes, they have invented programming languages in which these insights could be expressed. For example, one problem of early computer programs was that sometimes, the details of every part of a program depended on the details of every other part. The result was unmanageable complexity: nothing could be changed without changing everything. In order to make change easier, people started dividing programs into more independent sections called modules or components, each of which performs a discrete task. Each component is given an interface, which is a description of the ways in which other parts of the program can interact with it; it describes what the component does, without specifying how it does it. This has several benefits. First, it means that the component can be tested separately from everything else. If testing shows that it keeps the promises expressed in its interface, the programmers can then treat it as a 'black box'; they can forget about how it works, and turn their minds to other problems. Second, if the users' needs change, the component can be replaced with a new one that has the same interface, and the rest of the program need not be changed. Third, different components can be written independently by different people, who don't have to understand each other's work; this allows for a division of labour. Because of the clear benefits of this approach, as languages have evolved, they have provided increasingly explicit ways of describing interfaces, of distinguishing between the what and the how. All programs must be able to respond to errors, i.e. failures in their environment. A user may enter nonsensical data, a network connection may fail, a hard disk may run out of space. Early programming languages had no particular way of describing errors or ways of handling them. When one reads programs in those languages, it can be difficult to find the error-handling behaviour and to make sure that all possible errors are actually handled. Programmers realised that this was making it hard for them to manage the complexity of all the things that could go wrong, so they invented languages that provide clearer, more rigorous ways of describing errors. In the very early days of programming, people realised that no matter how clearly a program is structured, it inevitably embodies decisions that will not be obvious to someone who is looking at it for the first time. There have been three remedies to this problem: (1) adding comments for human readers throughout the program, (2) writing articles explaining how it works and why, and (3) drawing diagrams to give people an overview of its structure. The latter two kinds of explanation are called design documentation. Many people feel that every program should be accompanied by all three, in order to maximise the chances that someone unfamiliar with the program will be able to understand it. Good programmers tend to feel that if a program is not clear, it's probably because its authors didn't think through the problem well enough. A good engineer finds the simple solution hiding in apparently complex problems. Once that simplicity has been discovered, writing the program becomes simpler as well. There is one more way that language is used to make programs easier to develop and maintain; it concerns not the way the program is written or explained, but what the program itself says about what it is doing. When a program is unable to do what it is supposed to do, it should say so. We have all seen programs that fail in spectacularly uninformative ways, giving us no hope of knowing how to fix the problem. Although you may curse programmers when this happens to you, it happens to them much more often. By the time the average user gets to use a program, its authors have spent countless hours trying to understand why it didn't work, and fixing their mistakes. Computer scientist Maurice Wilkes discovered this phenomenon in 1949:
As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.In order to understand why a program didn't work correctly, you need to know what it was doing when it failed. One way to get this information is to make the program keep a log of everything it does. Then when something goes wrong, you can look at the log and reconstruct what was happening when the problem occurred. If the program was interacting with other programs, you can look at their logs and see what they thought was happening at that time. Logs often provide precious clues for diagnosing bugs. We can sum up these lessons about language and communication as follows:
Cost does indeed vary as the product of the number of men and the number of months. Progress does not. Hence the man-month as a unit for measuring the size of a job is a dangerous and deceptive myth. It implies that men and months are interchangeable.Brooks's point is that progress will vary according to the amount of communication required between the participants, the difficulty of dividing the task between them, and the complexity of the interrelationships between their work. He is also known for Brooks's Law:
Adding manpower to a late software project makes it later.There are three reasons for this: repartitioning jobs disrupts work and creates more work in itself, training new people takes time, and communication and decision-making are more time-consuming in a larger group. Most of these lessons were already familiar to good programmers by the time significant numbers of people started participating in free software. When sharing of source code started to happen on a large scale, programmers realised that this was a type of communication that had previously unimagined benefits. For the first time, it became commonplace to find and correct bugs in programs that you hadn't written and didn't normally work on. If a program didn't quite suit your needs and you had the source code, you could modify it to do what you wanted. Perhaps most importantly, you could learn the craft of programming by studying the work of the great masters and even by apprenticing, as it were, on their projects. As the corpus of free software grew, it became more and more likely that, when you had a problem to solve, you could see how someone else had solved it, and perhaps even use their solution verbatim. Much of the design philosophy of free software has its origins in the Unix operating system; as a result, many people have been exposed, through free software, to what is known as the Unix philosophy. Here is a paraphrase of some of its tenets, those which are clearly applicable outside the world of software:
|
This work is licensed under a Creative Commons Licence. To contact us, please use the openorg-dev mailing list. |