Traditional software development methodologies, such as Waterfall, tried to follow a series of isolated steps: First you define all the system requirements, then you devise a detailed system design that satisfies these requirements, and then you implement the system according to this design. This approach is also called Big Design Up Front (BDUF), since the detailed design is completed before starting the implementation.
However, in practice the software development teams always must face changes in requirements which invalidate parts of the original design. This fact is expressed in one of the Lehman’s Laws of Software Evolution:
“Continuing Change — A system must be continually adapted or it becomes progressively less satisfactory.”
The modern approach of Agile software development understands that changes are inevitable and that investing in detailed plans is not effective. This is clearly expressed in one of the values from the Agile manifesto:
“Responding to change over following a plan”
This means that it is more important to be able to respond to change than to follow a detailed plan. For example, here is how the Scrum process increases our ability to respond to change, according to the Scrum Alliance:
“Many projects that have elaborate project plans with detailed Gantt charts have failed. We make the plans so complex and detailed that they’re difficult to modify when changes occur. Agile process replaces project plans with release schedules and burn-down charts that can accommodate change. We can still track progress and, in fact, progress is more transparent than in a typical Waterfall project plan.”
It should be noticed that this description focuses entirely in the process: it explains how the Scrum development process is able to cope with changes more effectively than traditional processes.
Now the question is: Is it sufficient to have a process that deals with change? May we continue to design and implement our systems as we did before, or do we need also to have special design guidelines to make our systems more resilient to change?
I think that the proponents of Agile methods have done a really good work in defining new processes and convincing us that BDUF is a bad idea. However, I do not think the question above has received enough attention.
Besides the Agile manifesto, there are also 12 principles that may help guide us in the definition of what are the characteristics of an Agile design:
“Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage.”
“Continuous attention to technical excellence and good design enhances agility.”
Therefore real agility, or the capacity to cope with changing requirements, can only be achieved through investment in high-quality designs. In other words, the design must be change-resilient as much as the development process is change-resilient. Trying to deal with constant changes through a simplistic design is the most common cause of technical debt and continuous refactoring.
I believe that change-resilient systems must be planned to be adaptable. This means that the design should incorporate degrees of freedom, focusing on low coupling and high cohesion. These degrees of freedom do not necessarily introduce more complexity in the design. Actually, they often are the most effective way to defer decisions until the last responsible moment.
The Last Responsible Moment (LRM) is a lean development concept defined as:
“A strategy of not making a premature decision but instead delaying commitment and keeping important and irreversible decisions open until the cost of not making a decision becomes greater than the cost of making a decision.”
How do you defer a design decision until the last responsible moment? The answer is that you must introduce a placeholder, an abstraction that represents the module that will be implemented in the future. The introduction of this abstraction represents an additional degree of freedom, and it allows the rest of the system to be developed as if the specific decision was already made.
When the design is adaptable, the changing requirements may be implemented through new versions of existing components, without the need to change the relationships among these components. A specific component is the realization of a low-level design decision, but the high-level abstractions are stable. Thus, there is no need to refactor the system: the components may evolve independently of each other.
Adaptable Design Up Front (ADUF) is an approach that promotes change-resilience through the introduction of degrees of freedom in software design. I explain and discuss the ADUF approach extensively in several of my previous posts.
Agile software development has focused mostly on the definition of new processes to cope with continuously changing requirements. However the processes are not enough, it is necessary to devise new software design approaches to produce systems that are indeed change-resilient. Adaptable Design Up Front is one such approach based on the introduction of degrees of freedom in software design.
What is your personal experience? What are your design strategies to deal with changing requirements? Please share in the comments below.