Design matters! Well-designed software is obvious to users and to the programmers who work on it. Well-designed software is useful and easy to use, maintain, extend, and understand. And when competition is intense, design is often the difference between winner and loser.
In order to achieve sustainable software development, software must be designed to support and enhance changeability. This is because agility is possible only with the ability to easily modify and extend the software. Imagine that you are tasked with creating a set of playground equipment. If the equipment you design requires a welding torch and hammer to reconfigure, you are in a ton of trouble if your customer asks for changes to the configuration. On the other hand, if your equipment is designed to be modular and is put together with some bolts and a wrench, you can respond to almost any customer request. Software is unfortunately more complex than playground equipment because it is never left in any one arrangement, it is continually changing and evolving.
In sustainable development, you cannot afford to have a product that has a high cost of change because your inability to easily change your product will dictate a slow pace of development that will leave you in continual catch-up mode. Good design practices are one of your most important tools to help control the cost of change.
Design clearly has a critical role in software development, regardless of the methodology used. Design is also the hardest aspect of software development to get right because of factors such as schedule pressures, the people on the project, and continual change. As a result, designs fall across a spectrum that ranges between being overdesigned and underdesigned, with an unfortunate number of projects at either end.
Overdesigned projects are typically the result of overzealous application of the engineering approach to software development. This is the traditional waterfall top-down design method, which is still the most widely taught approach to software development. Top-down design advocates thorough design before coding, which of course involves understanding requirements before design. This is what most building planners use: They have a stable of mathematics, standard questions to ask the customer, and building codes that help them make the right decisions before they actually begin construction. Unfortunately, when top-down design is applied to software, the result is most often overdesign and a high cost of change. That is, if any software is produced at allmany of these projects turn into exercises that produce stacks of documents but no code.
The other extreme to top-down design is ad-hoc code-then-fix development, which is just as bad. In this case, there is little or no design, and change is just as hard because the code is a tangled mess or hard to comprehend. Underdesigned software is painful to work with. It is also unfortunately a great form of job security, because one of the symptoms of underdesigned software is the fact that the code is divided into the exclusive domains of various individuals. These heroes can crank out new features, but heaven help you if they ever leave the project.
In order to achieve sustainable development, you can't rely on top-down or bottom-up development. What is required is a middle ground so you can capture the good points of each: You want to have the discipline and ability to think about good design while at the same time proceeding as rapidly as possible.
Extreme Programming [Beck 2004] outlines evolutionary or emergent design. This method relies on simple design (only design what you need), refactoring (disciplined code changes), and test-first development (to ensure that the behavior stays as originally intendedsee Chapter 5). Evolutionary design works because of a tight feedback loop with end users of the software: The idea is to get the software into their hands as early as possible and then evolve the design as requirements change. However, evolutionary design can lead to unintended oscillation, where the same code is repeatedly changed over and over because sufficient thought was not put into the design:
For sustainable development, you need to understand how to balance the good aspects of up-front design and various design techniques with evolutionary design while avoiding the pitfalls of each. With up-front design you need to avoid overdesigning the solution by erring on the side of simple design while at the same time avoiding the documentation trap by focusing on producing software not documents. And you have to avoid design and code oscillation by thinking ahead and having a design vision and guiding principles. The design vision and guiding principles are explained as practices below.
Another way to think about up-front and evolutionary design is through the understanding of good design and good design evolution. Practitioners of up-front design concentrate on understanding what makes a good design, while practitioners of evolutionary design focus on understanding designs that result from evolution and how they evolved:
The reality, however, is that design is hard because you need to understand good design AND good design evolution. You can't understand design evolution if you can't recognize good design, and design is pointless without evolution because evolution is inevitable. And good design without evolution is pointless, otherwise the tendency would be to design for the sake of design. Hence, design has a yin (good design) and a yang (good design evolution) and this I think explains why it is so hard to get right. Good design doesn't just happen, it requires hard work and thought plus experience and knowledge. However, I also believe that good design doesn't just emerge from a single individual, no matter how brilliant. Good design requires collaboration, because collaboration provides support as the team collectively works toward their goal while balancing the yin and yang of design.
Design in sustainable software development means creating an environment where decisions are continually made within a framework that emphasizes change and designing for change, while ensuring consistency in the decisions. Design work is recognized as being crucial and something that is done every day by every member of the team in as collaborative a fashion as possible. The challenge is to ensure that the time spent on design tasks is appropriate for what is being designed and that the effort spent documenting the design is appropriate for the conditions of the project and is minimized to the greatest extent possible.
Other elements of design in sustainable software development are:
In typical software projects there are many kinds of design. The most prevalent are the design of the software architecture (classes, hierarchies, methods, etc.), the user interface, web site, marketing and sales material, user documentation, test infrastructure, and database structure. I am intrigued by the idea that while each of these areas is different, there are common elements that can be applied. Hence, although this chapter focuses on software design, the design practices are applicable to other areas of design as well.