Many idealistic Agile practitioners propose the idea of Emergent Design:
“With emergent design, a development organization starts delivering functionality and lets the design emerge. Development will take a piece of functionality A and implement it using best practices and proper test coverage and then move on to delivering functionality B. Once B is built, or while it is being built, the organization will look at what A and B have in common and refactor out the commonality, allowing the design to emerge. This process continues as the organization continually delivers functionality. At the end of an agile release cycle, development is left with the smallest set of the design needed, as opposed to the design that could have been anticipated in advance.”
Based on my 20+ years of experience with Software Development, I’m convinced that Emergent Design does not work. Below I discuss its main problems, illustrated with some nice pictures.
1st Problem: Software Systems Change
Emergent Design may be enough to create an initial design that will be right until it is changed. If a software design is not planned to support change, it will deteriorate very fast. As illustrated on the picture on the right, it may be challenging to keep the design coherent even for very simple systems. Since software systems always change, a design that does not support change is simply wrong.
2nd Problem: Software Systems Grow
Emergent Design may be enough to create an initial design that will be right until the system grows. If a software design is not planned to support growth, its complexity will increase very fast. As illustrated on the picture on the right, the initial design may become a disaster when one of the components grows. Since software systems always grow, a design that does not support growth is simply wrong.
3rd Problem: Dependencies are Important
Emergent Design is based on ignoring the big picture and designing only for the lower-level tasks (user stories). This may work well when these tasks are completely independent from each other, but in most software systems the dependencies are very important. If individual tasks are designed and implemented in the wrong order, ignoring their dependencies, the result may be a total mess, as illustrated on the picture on the right.
4th Problem: Coordination is Essential
Emergent Design is based on the individual work of software developers, ignoring the need of a higher-level shared architecture and team-level cooperation. Each programmer is responsible for his own low-level tasks, which he tries to implement with minimal coordination with other team members. As illustrated on the picture on the right, this lack of coordination may cause a total deadlock.
The Solution: Define Clear Interfaces
The only solution to all the problems above is to define very clear interfaces among the modules in a software system. Of course, this definition of the interfaces must be done much before the developers start the implementation of the individual components. At the component level the low-level design may emerge, but at the system level there must be a pre-defined shared architecture. I give more information about my proposed approach for software design in my posts about Adaptable Design Up Front.
What do you think? Please share your experience in the comments below.