This post originated from an RSS feed registered with Agile Buzz
by Laurent Bossavit.
Original Post: Popperian Software Design
Feed Title: Incipient(thoughts)
Feed URL: http://bossavit.com/thoughts/index.rdf
Feed Description: You're in a maze of twisty little decisions, all alike. You're in a maze of twisty little decisions, all different.
No one who reflects thoughtfully on the practice of software development disputes that good design is important to good software. (Not necessarily all-important - there are those who will argue that design matters a lot less than, say, success in the marketplace or in use. We'll ignore that for the time being.) There is less agreement on how to tell what constitutes good design, and there is agreement least of all as to what process results in good design.
Consider design as exercising rationality, or intelligence. Daniel Dennett classifies "degrees of intelligence" according to a hierarchy of models named after famous theoreticians - Darwinian, Skinnerian, Popperian, Gregorian.
I'll just give a quick overview of the hierarchy - go read Dennett's books for more detail. This is best explained in terms of beasties of various levels of sophistication. Darwinian creatures have no intelligence at all - think bacteria. There is variation in how well they survive the rigors of their environment, so that the best are selected - the ones equipped with the "technology" most appropriate for that environment. Skinnerian creatures have behaviour - they can do several things, not just sit there in a Petri dish. And they can learn - behaviour which produces good results is "reinforced". Popperian creatures such as the brainier animals don't blindly try out behaviours - they "think" about them first. They're named after Karl Popper who argued that such thinking "permits our hypotheses to die in our stead". Finally, Gregorian creatures have an extra level of sophistication - they don't just think, they also acquire mind-tools to improve their own thinking; tools such as language. That's, essentially, us humans.
Now that phrase - "permit our hypotheses to die in our stead" - is a severely compressed version of a longer quote, which I was able to track down, not all the way to the original source, but at least to one of two Web pages out there where it appears in entirety:
On the pre-scientific level we hate the very idea that we may be mistaken. So we cling dogmatically to our conjectures, as long as possible. On the scientific level, we systematically search for our mistakes... Thus on the pre-scientific level, we are often ourselves destroyed, eliminated, with our false theories; we perish with our false theories. On the scientific level, we systematically try to eliminate our false theories - we try to let our false theories die in our stead. -- Karl Popper
When we discuss "design" in the context of software development, and in particular in any discussion that ends up contrasting "up-front design", "analysis", "domain modeling" and so on with the class of so-called "emergent" processes favored by agile methods, I suspect that underlies the discussion is a Popperian model of design, and a critique thereof.
On what might be termed a "pre-scientific level" of software development, we dive into code - a phrase commonly seen to express the concerns of people who favor the more classical approach with full-blown analysis, modeling and so on as a prerequisite to implementation. What perishes with our "false theories" - our wrong assumptions as to the nature of the problem, or the structural difficulties faced in implementing a solution - is the project itself. That is, we end up being over schedule, over budget, with crappy code and the customers hating us nerds in IT or in engineering for failing to deliver.
On the "scientific" level, or so the Popperian view would have it, we design so that "our designs die in our code's stead". A design is a hypothesis: "a solution structured thus can be built in the allotted time, will perform correctly, and will solve the customers' problems". For a design to die in the code's stead is for the hypothesis to be falsified - we must show that the design is solving the wrong problem, or that it cannot fulfill its function, or that it is unfeasible to build it with the scheduled effort.
This Popperian view of the design process has several features which can clarify our thinking and our discussions about design. The first is that within its context - the comparison with Darwinian processes at the bottom of Dennett's tower, and its role in explaining intelligent action - the Popperian view stresses the goal of good design: adaptation to a given environment. This can get rid of disagreements about what constitutes good design - a piece of software that "survives" has good, or at least adequate design. Which probably means something rather demanding - the project being seen as a success, the software being put into actual use, without the very first item on the agenda being the development of a replacement.
Further, Popperian design eliminates. It kills hypotheses. So we should be able to verify that a Popperian design process is in operation by finding the remains of discarded theories, hypotheses, or designs. If it seems that a project ended up implementing the very first version of its "design", then something else was going on. As a corollary, design documents should document not just the current design, but the list of design alternatives which were found to be likely to cause the project to "die", if they had been implemented.
That last - if they had been implemented - leads to the crucial property of a Popperian design process - it is able to make predictions as to how a design alternative will turn out if it is implemented. There are many ways to make such predictions, any of which are in principle valid in a Popperian view.
For instance, you might have a "model environment". This would be similar in intent to a wind tunnel for testing the shape of airplane wings - except that you would be "modeling" the relevant properties of the context that the software will operate in. That would be an excellent reason to have an Analysis phase on a project. And a Popperian view would definitely clarify what Analysis is, what we expect of it, and what kind of evidence to look for that the result of Analysis activities was used in this particular way.
But this is not the only way a Popperian elimination could go. You could perfectly well rely of formulaic rules for eliminating design alternatives - say, checking for conformity to design patterns or the Law of Demeter.
However, two things have to be true, I think, for a Popperian view of design to work. First, it must be the case that your predictions are by and large correct. That is, your "analysis model" must correctly rule out invalid design hypotheses, and rule in valid ones. Or your "design rules" must have some correspondence to regularities across various software environments, so that one could verify "if you violate the Law of Demeter, it is in fact more likely that you will end up with a project failure".
Second, and also crucial, it must be the case that the effort involved in eliminating a design alternative is less than the effort involved in actually realizing that design alternative, and seeing - in practice - whether it succeeds or fails in the target environment for the software. (Where "environment" means users, other technical platforms, political considerations, and so on.)
This last hints at how "agile" development can be seen as a critique of Popperian design processes. The claim is that good testing, factoring of the software in flexible and modular pieces, and good teamwork are making it cheaper to try out design hypotheses in actual code. The claim might be true or false, in general or depending on context, but at least our discussions can be based on something that has an empirical basis; we do not need to resort to arguments that up-front design is "voodoo", a meaningless ritual, or that agile development is "non-rational", a discourse that prohibits thinking.
Of course it can also be that design isn't best understood as a Popperian process. But so far, that way of looking at it is the best I've come up with to make sense of the countless discussions of "design" I've seen or been part of.