Do you ever feel that sometimes designing up-front makes sense? Does it feel like a more organized, more controllable way of working? Does it ever make sense to design up-front?
Agile-istas dismiss the BDUF - or Big Design Up-Front. They claim it's impossible to know up-front what the application will look like, and the entire effort becomes too costly and does not produce enough value in return. Some agile-istas dismiss the idea of designing software up-front entirely in response. This argument has been popular for many years and promoted heavily by agile mongers.
Yet dismissing design efforts entirely is often not a good idea. I believe that designing some components in an application up-front is a better alternative than to dive in and code your way out of it. And the best reason to consider designing some components up-front is to achieve better code quality, avoid costs and achieve it with less effort.
Most code bases I've reviewed that were created by agile teams had bad code quality. Not only were their metrics off the scale, their software did not have any components. All code resided in one or a few projects. Yet having separate projects is a great way to maintain an overview of how components depend on each other. If your dependency graph between projects looks like a plate of spaghetti you know something's wrong.
Let me use an example of a common architectural component that can very well be designed up-front: a client interface with a vendor's web services. The web service operations I have in mind consist of two groups:
- Synchronous operations: a response is returned immediately.
- Asynchronous operations: a response is returned at a later time.
The application I have in mind has to provide an abstraction for these web service operations since they will be called from different parts of the application. There are some extra requirements:
- Asynchronous requests have to be retried if the web service is not available.
- If subsequent retries keep failing the calling component in the application has to be notified and the request has to be abandoned.
- The calling component in the application has to be notified of technical and functional errors returned by the web service.
- If no response is received for asynchronous requests after a certain period of time the requests have to be abandoned and the calling component in the application has to be notified of this.
These are clear requirements imposed by the customer. There's an opportunity here to make a good design and take into account code quality in the design phase. For example:
- Synchronous, asynchronous request and asynchronous response handling could be separated in three projects that have no inter-dependencies.
- Callback interfaces could be designed for the calling components to implement. These decouple the web service interface logic from other parts of the application.
- The technical requirements like timeout detection and retry policies could remain hidden for other components in the application.
Designing the web service interface component up-front does not imply that other parts of the application also need to be designed up-front. Here are the most obvious advantages of designing this component up-front:
- The implementation of the interface component becomes easier to understand up front thanks to a design effort.
- The design can enforce better code quality.
- Design documents should take no more than one day to complete. They can be reviewed, also by those critical of upfront design. This should guarantee a better understanding of the tasks ahead than code/test/refactor iterations alone can provide, actually reducing the cost of the web service interface component.
- A design effort can rationalize team discussions about application behavior. It also allows to reconcile certain functionality with other objectives like estimation, code quality or architectural integrity.
In general, I think it's unwise to systematically dismiss design up-front. Some component may benefit from this. This does not mean all parts of an application have to be explicitly designed up-front. However, there is value in trying to get an agreement from your most critical team members.
This can mean they have to prove a design up front is not required. It can also mean you have to prove to them a design up-front for certain components is a winning strategy.