|Chapter 6 - Design primer|
Analysis is all about requirements. You are analysing the requirements to gain an understanding of them, to improve their quality and clarity, and to begin to formulate an appropriate response to the stated needs.
Design is the creation of a technical statement to fulfil the requirements. It will be understood only partially by those who stated the requirements, yet will be sufficiently detailed to lead the developers in construction.
It is a drawing together of the people's needs and the technological and resource limitations and capabilities, to create an artistic and innovative solution. Requirements and analysis are logical endeavours. Execution of the code and release are purely technical affairs. Design is the most creative act as you come to a technical and aesthetic understanding of the problem.
As a designer, you have the same set of artistic and technical tools that everyone else has. What will differentiate your product from their product is your design.
As a rule of thumb, design will take five times as much effort and time as analysis.
The reason for design
Many developers believe design is discovered during coding. Code is a fairly workable medium, and a change of plan can be reflected by moving code around, or rewriting bits of it. Huge changes of plan require quite a bit of fumbling, and often developers find themselves rewriting bits over and over as requirements change. This is a result of failure in the requirements process. It must not happen. The reason it must not happen is that it is a waste. No-one would buy a car whose design was discovered during construction. Why tolerate software created that way?
Figure 6.1 The exponentially increasing cost of change
How would you feel if builders used construction to discover the architecture of your house or workplace? You would be horrified, and the resulting building would be a mess. You would not want to live or work there because it might fall down around you.
In software, we have not always followed the precedent of design before build, and the reason is that code is far more malleable than steel, bricks and mortar. The hero programmer, working long days, nights and weekends, cracks the problem and delivers a solution. Happiness, or relief, abounds on delivery in difficult circumstances, therefore the glory of the hard working programmer lives on.
But hard work in difficult conditions can lead to less structure, less careful coding, less careful error prevention and handling. The resulting software is highly likely to have high defect rates compounded by insufficient testing, and less easily understood code.
The hero programmer creates a lifelong dependency (and possibly employment) between themselves and their code, or creates a nightmare of rework for the next team or generation.
The reason for design is to:
The best unit of work, by common consensus, is a project with three or four developers taking around six months from requirements to delivery. The focus enforced by using few people in a time-boxed arena will provide the impetus for a successful team. A smaller project might not require so formal a methodology, and a larger one, further technical, process and personnel complexities.
Often, the approximate size of project is clear from the outset, particularly with new and replacement work. System updates and rework may require some analysis before the effort can be estimated, but even then, a system expert should be able to provide estimates without a detailed work breakdown structure.
Large scale projects, typically ten developers for a year, must be broken down into a set of subprojects built upon a common foundation. Projects falling inbetween are a matter of judgment.
Figure 6.2 Small and large scale projects
Huge projects, those requiring developers by the hundred, or timescales of years, must be broken down in stages of ever decreasing size and increasing definition. Huge projects are certainly the most risky to undertake. They have a habit of never getting finished, or becoming obsolete before delivery. This is a sad state of affairs when some organisations excel at huge projects, and with skilful design and management, are more efficient at huge projects than they might be on smaller projects. Efficiency comes with reuse across systems. Reuse comes from good design, and good design on this scale takes a lot of effort. If you are to act as software architect on a large or huge project, you must not have any other role.
Huge projects can also be referred to as programmes of work. A programme manager will take the helm, and coordinate the work of the project managers of the projects into which the programme has been divided. The lead architect will work at the programme level, coordinating the work of architects or designers on the projects.
Tiny projects, where a developer may take a few weeks, can often be shaped rather than designed. This is design based on the ancient art of winging it. Have the developer sit next to a future user, and design it with them rather than for them. Such development is perfectly acceptable, and should be used for such pieces of work. Too many small pieces of development are clogging up analyst and test teams when the best tester and requirement documenter is the user. Involving users to this extent is a fundamental tenet of agile methodologies.
Reducing the project scale
The first key to success on a larger project is to break it down into ever smaller pieces. This division of labour and complexity may occur at any point in the lifecycle, from initial project conception right through to design. If it occurs before design, then some reassembly may be required at this point to appreciate the true scale of the work, and what might be shared or enforced across the projects.
It may seem a thankless task to assemble already divided work, but division from the point of view of shared functionality and technical limitations may yield a different set of projects than division from a purely functional point of view. It will certainly place a different emphasis on the importance and risk of developing shared code.
Figure 6.3 Reducing project scale
At the beginning of the decomposition, a set of subprojects is created. Each project will sit within a common framework and use a common set of tools. At this stage, all internal and external interfaces are defined.
If the subprojects are still large, then break them down again. Add to the toolkit, refine the framework, or create another layer of framework for each successive set of subprojects if this is realistic.
An example of a framework is a layered or multi-tiered set of objects which abstract away operating systems, networks, storage methods, business logic and context to provide more meaningful and helpful operations for the applications and developers. An example of a toolkit is a math library, or set of business calculations, information repository calls, object builders, gui tools and graphical displays.
Each time this subdivision occurs, the subprojects become smaller and smaller, until they can be assigned productively to teams.
To effectively deliver interdependent projects requires time spent defining where those dependencies are, and how and when they will be developed. It is a detailed and demanding task, and must be carried out by, or with the full cooperation of the project managers. Timing and slippage on these shared development are of the utmost importance. If one team is ready to use a component or function call that will not be ready for another month, the most likely course of action will be to write their own, thus circumventing your architecture, reducing reuse and introducing complexity to the code, to testing and future support.
Good architectural design in the structure of the system is more important than in the successive subprojects. It is here, in framework, toolkit and interfaces that the (lead) architect must focus.
Design is an extension of analysis
Many design tasks are extensions of the work carried out during analysis. Technological options are investigated and resolved to technological choices and the reasons for these choices recorded in the design documentation. User interfaces are given detail and look and feel. Object models are defined further with structural and dynamic diagrams.
In some cases, design will simply be a more technical and detailed definition than is achieved during analysis.
Designing large systems
To be able to deliver large systems most effectively, it is vital that there is a single vision for the project. This is most easily achieved by a lead software architect, but could also be achieved by a team of specialist architects working together.
The considerations of large system design are this:
Package diagrams are probably sufficient at this point for detailing system structure, with state, interaction and sequence diagrams of interacting and collaborating packages.
Designing small systems
Some of the design issues for small systems are the same as for large systems. Where systems and interfaces are defined in large projects, components and interfaces are defined in smaller systems. Within those components, classes (or code structures) and interfaces at an even lower level are defined.
Small system design will consider the following items:
Class diagrams will define the static structure within the projects, and sequence, interaction, timing diagrams etc, will define the dynamics. UML's strength is in design, and must be employed to the full within the projects.
All design tasks must take into account the architectural concerns discussed further in chapter 16: enterprise architecture.
Design for politics
There will be occasions when your user group or sponsor demand a solution which you consider will be a worse solution than you have proposed. This blinkered demand is often a result of something going wrong in the past. If you have a better solution and your sponsor is demanding something else, one of you is being pig headed. It is not always your sponsor.
Resolve the problem by refactoring your sponsorís design with ideas from your own. It will then be their design with slight modifications from yourself in the name of technological feasibility. If you cannot do that, then offer parameterized alternatives or user choices. If someone must have view X, make it the default view, with another (your design) available in a menu.
Without doubt, you will one day hear: ĎI donít like the colourí. You must avoid all temptations to change it, because if you make this particular user happy by changing the colour, your next viewer will say: ĎI donít like the colour.í
To avoid colour problems you can ignore people who donít like it, or use blue. Most people are happy with blue because there are less blue cones in the eye than there are red and green, so it causes less of a reaction. People who have a particular dislike of blue tend to stay indoors to avoid the sky. You are less likely to meet them.
There are many computer based design tools, case tools, user interface designers etc. Your development environment provides you with prototyping tools to test out new ideas or components. Yet the best design tools are non-technical. Here are four you might like to use. They are all variations on a theme, being used to simplify complex structures.
Method 1: The consultantsí favourite. Post it notes.
This is probably the consultantsí favourite because it is quite easy to master. It can be explained to groups of people in about a minute, and everyone will understand it and be able to contribute. It is the technique I used to design the structure of this book.
It works by writing down lots of ideas on post it notes. The only rule is one item per note. You write them down, then you stick them on a wall and begin to group them. By doing this for this book, I ended up dividing all my ideas into 18 chapters in 5 sections. It is known as a bottom up method. You start with the pieces and end up with the lumps, and finally, the design. Top down methods would start with the high level design, figure out the lumps and then detail the lumps.
Method 2: CRC Cards.
CRC stands for classes, responsibilities and collaborators.
Figure 6.4 Simple CRC card
Here is the simplest form of the CRC card. The class name is obvious enough. The collaborators are other classes which help this class to do its work, and which other classes are helped by this one. The responsibilities are what the class does and what it knows.
Figure 6.5 CRC Card for a carburettor
This example shows the Carburettor class created by composing it of other classes. This is perfectly acceptable, even when multiple inheritance is available.
The CRC and post it note methods can be used together. Write out some cards and then start sticking post it notes on them. When youíve finished shuffling the post it notes from card to card, copy their contents to the cards and throw them away.
I use a carburettor quite often as an example component, so I should explain how it works.
In a car engine, a fuel pump pumps fuel to the carburettor. The carburettor then holds fuel in its fuel chamber, where a float in the fuel rises up and closes a needle valve. The needle valve prevents any more fuel entering the fuel chamber.
The fuel is mixed with air and the carburettor delivers a vapourized fuel and air mix to the combustion chambers of the engine.
Inside the carburettor, fuel is drawn from the fuel chamber by the venturi effect, and when the throttle valve is closed, (accelerator is not pressed) then just enough air and fuel go through a side door to keep the engine ticking over.
As an example component, it is quite perfect. It has about the right level of complexity. It is created from a set of smaller components, and uses a pre-defined technical method - in this case the Venturi effect.
Figure 6.6 A carburettor schematic
It has interfaces to the external world, i.e. the choke lever, the accelerator or throttle, and the line to the fuel pump. Air comes in through the air filter, is mixed with fuel and drawn into the combustion chamber where it burns. The exhaust gasses are then pumped out of the exhaust.
The carburettor is a component composed of other components (by aggregation rather than composition if you are an oo purist), and provides a meaningful piece of work in the system. It has interfaces and takes part in the flow of air and fuel through the vehicle.
When designing classes, you should think about its equivalent in engineering or product design. Hereís what Steve McConnel has to say about design, and this can apply to systems, frameworks and classes:
Method 3: Mind maps, also known as spray or thought diagrams
Figure 6.7 Mind map of a car from a driverís point of view
Here we see a mind map of a car. It is divided into four types of object: pedals, hand controls, dials and comfort. The dials are subdivided into lights, clock dials and numeric styles.
Mind maps are useful for grouping objects from different points of view.
Method 4: Linking the unlinked objects
Finally, a useful method for identifying links between seemingly unrelated objects. It is based upon a system designed for the Dutch police to identify relationships between criminals.
In the police version, it works like this:
Figure 6.8 Tracing links between criminals
Here, we see a suspected international drugs ring. Contacts in different countries have been identified by the local police. Now Interpol have been given the information, and have added their own international knowledge. Geezer Jim in New York has been in contact with French Franc. Franc is in the same group as Duc Url, who works with Fishy Fred, also in New York. A link up between the two New York gangs is imminent, so they are being watched, and at the same time, Interpol officers are watching the ring members carefully in each country. They will build their web, and swoop. If youíre on the list, be careful. Hans CC is the suspected godfather, but so far he's as clean as a whistle. Will they get him? Tune in for next weekís exciting installment...
You can use this method when identifying related routines or objects in existing code. Write down the objects or functions, and begin drawing in the relationships. The more lines, the bigger the ratís nest. Improving, or refactoring, the code could begin by trying to reduce the number of lines linking routines and objects.
The same method can be used during design to clarify links between components. Once the links have been made, a more logical grouping of components is possible. Imagine our car:
Figure 6.9 Car object collaborations
The relationships between the carís objects are rather obvious, but this is because of our familiarity with a car. From this technique, it is easy to get to a collaboration diagram, and it also uses very little space to show an overall picture of object relations.
A diagram like this can be transformed into a perfectly
valid UML class or collaboration diagram. To make it a class diagram, draw a
rectangle around each word. To make it a collaboration diagram, draw the
rectangle, add a colon before each word, and draw arrows, labels and sequence
numbers along the joining lines.
The foundations are laid; the building blocks identified. Their interfaces are detailed and the grand scheme in which it all works in terms of hardware and software technologies is documented for all to see. Is this where architecture ends, and management and development take over?
Let us look at the building architect and software architect, and compare the environments we each operate in.
Comparing Software Architecture to Architecture
The Royal Institute of British Architects (or RIBA) was founded in 1839. In the UK, they define the technical, personal and ethical qualities that an architect must live by. It is a formidable professional organisation which defines, supports, judges and dishonours, when necessary, its membership. It is extremely difficult to practice architecture or to claim the title of Architect without being a member and having passed through a degree following their syllabus, and an internship in an architectural practice once again on a career path defined by them.
In juxtaposition, almost anyone can claim to be a software architect. IT architecture is still in its infancy, and many organisations are being created in the hope of becoming the professional organisation for IT architects. We have our role models to follow, but absorbing the learning and change of over a century in the building world will take some time. The required growth of our field and our professional status is compounded by the problem that IT architecture is a global rather than a national phenomenon. For now, we can only look and compare.
Figure 6.10 The Architectís environment
Figure 6.11 Comparing the Architectís and the Software Architectís environments
We work in a young industry which has grown rapidly. Already our way of creating, constructing and supporting software is as complicated as it is for our living environment. In comparison to the architect, our lines of responsibility are far murkier. Our different organisations approach the software problem with different ideas, and different business structures. This will continue for some time yet, possibly decades, before we begin to settle into more readily understood environments. Other disciplines such as engineering, accounting and HR are managed similarly across organisations because of the maturity of their professions.
A few thousand years ago, builders began building. Functional buildings required design, so architecture was born (many times in many different civilisations) and suddenly there were great temples and monuments. Some were so great that they outlived the gods to whom they were built.
Now we have discovered software architecture, what monuments will we leave behind? Maybe we shall see Abdullah 2038, the classic foundation of all human compatible robots, or Broad 2042, the cybernetic interface framework.
So far, all we have managed is the automation of paper based systems. We may have added a little colour and better search facilities, but in many cases our software still achieves second place. Try shuffling a few hundred electronic post it notes around on a computer screen - it cannot be done. Can you count all of the letter 'A's in the Bible without any programming knowledge? Try drawing this:
Figure 6.12 This
This rather pathetic figure took around ten seconds to draw on paper. The software version took two minutes and I had to export, then import it into the word processor. Is that an improvement? If I want to change it, I have to go back to my drawing application, re-export and then re-import it.
Of course, the computer method does have many advantages. Electronic pictures are more easily saved, catalogued and duplicated, electronic words are more easily moved around and edited. The great benefits are changeability, ease of storage and print output.
So the floor is open to you who wish to take up the software design challenge. It is where you get to be brilliant. In their vision of the space race, the Americans designed a beautiful pen. It wrote upside down underwater on many different materials and lasted forever, all for the mere cost of one million dollars research. I own one. The Russians used pencils. I own some of those too.
The true objects of nature
There are a few good examples of the use of classes in software design, mostly preserved as design patterns (see chapter 15). There are many more in nature, evolved over millennia, and are worth considering.
We have (at last count) eight classes of quark making up the three atomic building blocks: protons, neutrons and electrons. These three classes combine together in mathematical sequences to make up just over one hundred elements. The elements combine to make molecules, and molecules lump together to make proteins, carbohydrates and fats, which make us.
Now thatís not quite the case. We are, in fact, composed of cells. Each cell we have contains the blueprint of us, i.e. our full genetic code. Imagine if every object we defined in software held the properties of every other object. It would be absurd. Instantiating an object would take longer than a user might live.
Maybe our approach to classes is far better. It uses less space and is more specific to the task each class will be used for. We can aggregate and inherit and compose our higher level classes from lower level ones, and these are very useful techniques for keeping our code thin, precise. Yet nature does it differently, at least in animate cases.
Our classes are mostly not animate objects. We are more interested in what an employeeís name is, and that cannot be read from DNA. Neither can address or postcode. Our classes are limited representations. Perhaps this is because of our limited computing power. When a computer can play twenty questions with us, I will be impressed. I wonder if it will contain three base classes of animal, vegetable or mineral?
Approaches to architectural design
As an architect, it is possible that you will have all of the good ideas, and be able to create then pass on your superb design to a team of willing developers. It is possible if you live in cloud-cookoo land. Thinking one person can have all the good ideas is ludicrous. Japanese engineering grew fast, large and better by allowing anyone to have good ideas, while the rigid organizational structure controlled behemoths of the west crumbled.
Measuring and integrating these ideas is your job as a software architect. You should also be allowing them to occur and be appreciated. The creation of common components, frameworks and tools must go through a validation process, and this is the work of a committee (perish the thought).
A camel is a horse designed by a committee
is what my father used to say about committees. To a point, I agree, which is why the single vision of a software architect is so vital in software development. However, I wouldnít set out across the Empty Quarter on a horse. Camels have their uses. Use a committee to validate and extend shared components. Give your committee an impressive name, like the Integrated Common Component Committee (ICCC). Use it to share ideas which go across systems. Ask everyone involved in software development to put forward components, algorithms and libraries for inclusion in the shared code. Include everyone. That will mean they are less likely to oppose it.
Here is how an ICCC (not the I Canít Cope Club) might work:
Users are people. They cannot proceed for 2.7 kilometers in the direction 330°N without technological help. They can turn left at the big tree then right at the petrol station. They cannot then turn first left, second right, on past Macdonald's to the fourth traffic lights, left then the second exit from the roundabout. It is too much information.
If you are writing an application for a windows based operating system, you are communicating with people who are in a psychological environment of expectation. They expect to be navigated through familiar landmarks. They expect 3D objects to show up as if the light comes from the top left of the screen. They expect scroll bars, they expect to click on things and see something happen that they are used to seeing. As soon as something unexpected happens, like a page of text moving in the direction they are scrolling, they become confused and annoyed.
They expect something to behave the way everything else in the environment does.
They are looking for clarity, harmony, balance, simplicity, refinement, restraint, unity, modularity, sophistication, elegance and economy. They build mental models of what will happen for each of their actions, and have a predefined model for the operating system you are writing for. Write something different and they have to create a whole new mental model for your stupid application.
If they are used to seeing the top of figure 6.13, donít give them the bottom, thinking: ĎMine will be different; mine will be cleverer. I wont make them move the mouse so far when they accidentally go past a page, Iíll put the buttons next to each other. Iíll put those ones they never use on the right, out of harmís way.í
Figure 6.13 The improved interface from geekspeek inc.
They will hate you. They will hate your product. It forces them to create a new mental model, and their grey matter is filling up.
The cold call
I cannot stress enough how design is a collective, inclusive exercise. Being an architect doesnít mean being strange and shutting yourself in a box (or ivory tower - depending on your persuasion) while creating your architectures. Emerging to spread your vision will be a hard sale.
A roomful of people excluded from input into the architecture is the equivalent of a cold call. Selling your design or architecture is far easier if your viewer has something to hook them. If a viewer recognises their input, and is recognised for it, then you are no longer cold calling.
A cold call is a sales term when a salesperson turns up at a potential buyer without introduction and tries to make a sale. It is hard work. Success is rare and fragile. Sales people do it, but donít necessarily like it. It needs a thick skin. Software people try to do it, but they canít. They donít have the skills. The architect ends up presenting. The development team listens, leaves and forgets. The result is this:
Developer: What was that architect on about? Now I have to write system X. Time to start coding.
Architect: Iím glad thatís over. I hate doing those presentations. Now, on to project Y.
Sometimes you get designs wrong; sometimes you get them right. Most often, many different designs will deliver the stated requirements. But the measure of success in design, and as a communicator, is not always how the design delivers the requirements. Think on it as how often the code delivered matches the design.