Past wisdom in software development held that the proper sequence of events should start with perfect requirements, followed by perfect design and planning, ending with implementation. The flexibility promised by agile methodologies of software development, according to that view, is as costly as allowing for the possibility that the kitchen in a half-built house is not in the desired location. Besides, what is the meaning of software “architecture” if we allow for shifting designs and evolving features?
To answer the criticisms about agile developments, one must examine the underlying concepts supporting traditional, sequential “waterfall” development:
- Perfect planning is possible;
- Change is inevitably costly;
- Architecture must result in unchangeable results
But perfect planning isn’t possible. It is a disservice to the client to require a perfect plan. In the real world, knowledge of the business is dispersed among many stakeholders; concepts suffer from varying degrees of vagueness; and the desired outcome often begins to crystallize only after the work has begun. It is therefore more cost-effective to have technical talent that can function in an interactive environment with the stakeholder and adapt the work to an evolving plan.
Change isn’t always costly. The cost of change can be minimized if enough flexibility was implemented in the first place. Planning must therefore allow for the ability to make changes. The extra initial cost reduces the risk of a higher cost being incurred later.
Architecture does not equal rigidity. Proper software architecture makes use of techniques that reduce dependencies, generalize software components and anticipate changes in the design itself. To continue the half-built-house analogy: The ceiling is not resting on too many walls, and the infrastructure for the kitchen is in many places in the house.
The practice of writing flat, unidirectional software, based on the theory of the “perfect plan” has resulted in legacy software that is hard to change, maintain or understand. The evolution of the software engineering discipline is in part a response to that problem. The common threads in modern software design concepts indicate that.
For example, the concept of encapsulation in object-oriented languages, where the inner workings of a software entity make that entity a black box that can be replaced without having to change its context, directly serves the need for flexible architecture at the lowest level. The concept of “pure functions,” in functional languages, where a function is by definition unable to change its environment (making the function easy to “unplug” and replace), also serves the same end.
Proper architecture makes use of established and proven design patterns, selects the right patterns for the task at hand and adapts them when needed based on the specifics. This increases the effectiveness of the planning stage by a) avoiding reinventing the wheel and b) greatly reducing the number of possible paths that need to be explored.
It takes a certain attitude to embrace the agile approach: one that thrives on innovation, freedom and work that never stops improving.