Software systems are complex systems
I finished reading Complexity by Mitchell Waldrop yesterday. First, I must say that it is a very interesting book. Given the things I am interested in – systems, self-organization, adaptation, emergence, networks, et cetera – I got more out of reading this book than Emergence and Linked. As for all three of these books, I have tried to apply the things in them to software development – as well as to the process as to programming in itself – and Complexity was by far the richest source in this regard.
The book deals with systems that are at “the edge of chaos” – that is, that they are neither in “the ordered regime”, nor completely chaotic. Systems at the edge of chaos are living or lifelike. They are there because they are made of myriad agents, coevolving, constantly adapting to each other. The interactions among the agents, rather than the nature of the agents themselves, are what makes the system living/lifelike. The agents might be utterly dumb (as in the brain) or smart (as in a social system, such as an economy). The “rules” by which the agents act give rise to a far more complex behavior at the scale of the population, even if the rules are very simple. Very simple local interactions can create a system that exhibits order, even if it is constantly constantly changing – like a flock of birds.
The book is centered around a handful of people that together formed the Santa Fe Institute – an unconventional research institute devoted to exploring the science of complexity in physics, economics, the global environment, et cetera. The book starts with Brian Arthur’s thoughts about the flaws in neoclassical economics. The view that economies are in almost constant equilibrium, and that the agents in an economy are perfectly rational, that was held by economists at the time (and basically since the eighteenth century), was something that Arthur had problems with. As he tried to get his papers published on increasing returns (as opposed to diminishing), he was ridiculed and several journals turned him down.
To Arthur, the economists were too caught up with the idea that everything in economics must be expressed mathematically; he felt that they were too fond of their theorems to see how real economies behaved. Neoclassical economics indeed seems like a cousin of Newtonian physics. In reality, the simple theories of economics are indeed there, but given the number of (perfectly irrational) agents in any economy, the economic systems are messy – they are unpredictable, they crash, they boom, they are living things. In Newtonian physics, the metaphor was something similar to a clockwork; in complexity science, the metaphor is more related to the growth of plants, or the flocking of birds.
So, if the theory is simple, and the result of myriad agents all acting according to this theory is an unpredictable system – what does this tell us about software? Well, you could say that individual agents (objects, methods) in a software system are, more or less, theoretically simple. Code is expressed in a simple notation, and could be seen as stating the theory for how the agent is to act within the larger system. In reality, however, the agents are either too complex right at the start, or grow too complex over time.
If we agree that individual agents in a software system are theoretically simple, it is the interactions among them that makes the system complex. Take the simple rules behind the flocking of birds in a computer simulation (in which the creatures are called boids), as explained by Craig Reynolds in Boids: Background and Update:
Separation: steer to avoid crowding local flockmates. Alignment: steer towards the average heading of local flockmates. Cohesion: steer to move toward the average position of local flockmates.
These few rules are enough to create something very similar to how real flocks of birds behave. So, if such a simple theory can give rise to unpredictable and complex behavior in the interactions of a population of several such agents – does this mean that a software system soon gets infinitely complex, as it evolves into consisting of several agents, each following its own specialized, and often not that simple theory? Well, in a sense no, it doesn’t. Single software agents are generally not crafted to adapt to their surroundings, as the boids do, or as any organism in an environment does. Most often, they are seen as discrete things that systems are built of, similar in notion to assembling a car engine.
What distinguish software from car engines, though, is that the parts have much more complex interfaces to their surroundings. Any random software system is more complex than a car engine – and this is not about software systems being like big car engines with lots more parts. True, there are more parts, but what’s significant is the interfaces of the parts being more complex, resulting in more complex interactions between parts. Also, any given part in a software system interacts with more other parts than what is the case for car engines.
So, given the fact that the interactions are much more complex in software, the risk for unpredictable behavior is very high. Every programmer has experienced bugs that were very hard to track down – probably because the symptom of the bug was a side effect of a chain of events instigated by the bug, meaning that the bug must be traced by repeating the bug and following the chain of events backwards until the bug is discovered. If I’m not mistaken, this is what Alan Turing’s ideas about “undecidability” is about. This is mentioned in Complexity, however only brief, but as I understood it, it essentially means that any non-trivial piece of code must be executed to reveal what it does – it’s virtually impossible to deduce it from reading the source code.
In Extreme Programming (XP), one thing that is frequently repeated is that the only thing that counts is running code. Documents doesn’t provide business value. This is true, although some documents might indirectly help to provide business value (which isn’t something that XP denies) – but the fact that complex systems – consisting of many parts, that interact in complex ways – must be executed to be known to work, speaks louder in favor of getting started writing code as soon as possible. And given that the understanding of the problem domain is very poor at the beginning – for programmers as well as for customers – and that learning is much more effective when you learn from concrete results than from abstract ideas about a potential system – given all this, it’s hard to imagine any other viable way to developing software than to do it incrementally, organically.
Footnote: Complexity is a brilliant book, but it was published eleven years ago, at a time when complexity science was just taking off. If you have any suggestions about further reading, I would appreciate if you could drop me a line. Also, I would love to get feedback on this post.