Intention vs Implementation
When a person designs anything – a house, a car, a class – they have some intent. They may intend for the house to feel spacious, the car to be fast or the class to be an efficient string parser. The purpose of design is to fulfill your intent and the purpose of implementation is to fulfill design. If the design is “bad” it does not meet the intentions of the designer; but if the implementation exactly matches the design then the implementation has been a success.
The word “design” conjures up many things, most of the associations for me are visual and revolve around solving the essence of the problem. In contrast, “implementation” is a mechanical, algorithmic, boring process that converts the pure ideas of the designer into the concrete reality. However, even the most basic piece of work in other engineering disciplines know that this is not so. In civil engineering, the construction of buildings can never be fully specified on paper. Even with the most complete set of working drawing the full realities of implementing, that is, mixing the concrete, selecting the timber, laying the bricks and even hammering the nails will make the differences in whether the building is well finished or maybe even structurally sound. The recent earthquake in China has shown even if the design is sound, if corners are cut in implementation the design will not fulfill the intentions of the designer.
Mostly, things are never even close to being finished in the design stage. The architect wants to pin the design down like a butterfly. The implementers – the builders – want the design to be practical and easily implemented. The clients – as always – want the design to change because “it isn’t like it seemed on paper!”. In manufacturing engineering, a design that fully solves the problem and is a beautiful piece of work mechanically and aesthetically will be rejected if it has not been made with mass production in mind. In chemical engineering, the most fantastic product won’t be a success unless you can get it to flow down the pipes in the factory.
Of course, the skill of the designer can extend into the realm of implementation. The most skilled designers are expert implementers. The bad designers are out-and-out fantasists who complain that the implementers ruin the purity of their designs. The worst designers can’t even convert their intent into a design (like me picking colours, I have no sense for what colours “go” together).
Where is the design?
The problem with designing code is spotting the difference between your intent and your implementation. Design should be the bridge between intention and implementation. When we make a house, we can see the difference between the plans for the house and the house itself. We hope that the implementation is like the design but how can we know if the drawings are like the design? For the architect of a house, the creation of the plans is an implementation in itself.
Particularly when we talk about code, the activity of turning the code into a program running on a computer is mechanical. So for making computer applications the implementation is writing the code, so where is the intent and where is the design?
That just pushes us one step back up the chain; a designer has intentions and she converts them into a design, a mental model, that fulfills her intentions, but that first step is entirely internal and discussing that would take us deep into the region of philosophy of mind, and I don’t think that is productive.
She then converts that mental model of the design – which, for designers of physical objects, may be already visual – into some design artefacts that can be passed to other people. It may be a sentence that describes the design, it may be a picture. She then may, if she wishes, enter a feedback loop where the design artefacts are used to refine her understanding of her design, to explore areas that she may not have fully or correctly imagined. Imagined is a powerful word here, we are creating something and then holding in our heads while we explore it; we may be exploring it visually – literally turning it over in an image in our minds or flying down into the details to imagine “in close up”.
In that case, what is the design? Is it the original mental model or the refined design artefacts that are passed to others? I would say the analogy of a bridge is appropriate: the conversion of one thing to another, the intent to the design artefacts. Like the old joke: what crosses a river every day but never moves? A bridge. The designer may cross the “bridge” many times passing from intent and mental model – her internal representation of the problem – and crossing over to her solution to the problem – the design artefacts which are external – that will be used by implementers.
I think that when we write code – which remember, is our implementation – we still pass through these stages of intent, mental model and design artefacts. For a simple problem we may move through them so swiftly and easily that they are accomplished subconciously, like the throwing of a ball. For a large problem we may struggle under even trying to get a clear grip on the intent. Especially if the problem is so large that we require many people to be involved in the process. That means we need not only need design artefacts, we need intent artefacts to communicate with. All of the transitions between stages can be hampered by miscommunication.
The design is the bridge, it happens somewhere between the clear formulation of intent and the clear formulation of the design artefacts, but that bridge may be crossed many times. How that bridge is formed is a question for philosophy and neuroscience.
How precise are your design artefacts?
The key question that I posed above – is the drawing like the design? – is very important to coding. We can have architectural plans that vary from a sketch on a napkin to full working-drawings that specify every nail and bolt. Those plans may or may not accurately represent the mental model of the designer. She may have only a vague impression of the shape of the building in which case the napkin sketch is conveying her design (and possibly her intent) but will be no good to implementers. She may have imagined every conceivable detail but doesn’t wish to provide all that when she is trying to put across an idea quickly in a sales pitch, in that case her mental model is fully formed but her design artefact is not. As I mentioned earlier most physical designers think visually and many of them will iterate as their mental model interacts with their design artefacts.
So what about coding? What are my design artefacts? Well there is a huge range, as we would expect for a non-physical design. The simplest things are sketches like this one I did yesterday
or they could be a list of comments that you make in an empty body of a function before you start to implement the code. Of course, they can also be things like a set of UML diagrams or a Z spec. The simplest of all is that you make no actual, physical artefacts; you just have an full understanding of the design that you have imagined that you can convert at will to any one of the above representations. I think that full understanding must at least be expressible in some language, even if that language is a language that only you fully understand; it may be symbolic or use normal human languages in a special way (like a jargon that only you know).
These all vary in their precision, but they are all languages of a sort.
Why is making computer programs not like making physical things?
Well, if you are going to have to express your design in a language, you would choose a language that has a natural fit with your design and your problem domain. I know a good one for expressing the designs of computer programs; it is human readable, compact, can be sent over any electronic media and is very, very precise for specifying information processing tasks; it is called c#.
That, to me, is the core of the difference between computer programming and many other engineering disciplines: the design artefact that completely expresses the design is also the implementation of the design. Of course, it doesn’t have to be that way – we can include UML, Z, a sketch etc etc – but as we have a language that completely expresses the design and implements the design why do anything else? Of course, that forces us to combine the designer and the implementer in one person. But really, as we have discussed there is no “pure” design that can be implemented just as it is; all forms of design artefact other than code have to be interpreted (or compiled, if you will 😉 ) in such a way that they can be made into code. All design artefacts are incomplete, only the implementation is complete. Only then can we see if we have something that matches the mental model of the designer, and only then can we see if the intent has been satisfied.
I’m not, of course, arguing against all forms of documentation that aren’t compilable. What I’m saying is that design artefacts should not try and be too precise. You should stop adding detail when you have conveyed the intent. More than likely, for a large system, you will need many types of design documentation; you should not expect one type of artefact to meet all needs. Of course, the more artefacts that you have the greater the chance that they will not agree with each other, nor with the intent nor with the final implementation. You won’t get these things to match unless there is some process to go and check. The simplest example is finding that the comments in your code no longer match the code; worse than useless!
Of course, this is why agile processes prefer conversation over documentation as the back and forth of conversation allows you to completely ensure that the other person has understood your intent.