In our previous article on ‘Emergent Design’, we discussed what ‘Emergent Design’ is and provided some definitions. In this article one of our Project Managers describes some practical techniques in applying ‘Emergent Design’ to your Agile projects.
As a quick refresher, there are a number of advantages to applying emergent design instead of a big design upfront. There are 3 main reasons that I think are important:
- We don’t know what we don’t know.
There are known unknowns, but there are also unknown unknowns. By using emergent design, we defer designing for the unknown unknowns until we encounter them.
- Design is code
Unlike traditional engineering which has blueprint before manufacturing, software projects often start one without any - especially in Agile projects that need to start immediately. Similar to the software design discipline, we have a way of building blueprints by creating models. Often these models become obsolete quickly and become just another relic artifact of your project. What matters is the code, so the design is the code.
- Ready vs Predicting the Future
Instead of using a crystal ball to try to predict the future, we should always be ready for it. By applying emergent design, we don’t waste time trying to predict what needs to be designed right now, but instead prepare the code in a way that is modular enough to be ready for the future. Trying to predict the future of the project often leads to over-engineering.
Even before starting your Agile project, you should equip your team with good engineering practices. Good software design and exercises to detect abstraction and patterns in codes are essential for your team. A good understanding of Object-Oriented Design, Domain-driven design, and the very much standard Gang of Four design pattern (and other popular design patterns) are good start for your team.
Starts with TDD/BDD
In the first few sprints of your Agile project, you should lay the groundwork of your project. Items such as the architecture are hard to change later. Once the groundwork and foundations are laid, you should start with Test Driven Design and/or Behaviour Driven Development to begin your journey with emergent design. Start by translating all of your essential functionalities to some behaviour, functional and unit tests, and begin building your code around it. By repeatedly passing and failing your functional and unit tests, your code will eventually produce some patterns that can be harvested to become your design. Start with simple design first and put aside complex design considerations until they are needed.
Design as Technical Debt
Once you have harvested some patterns and want to translate those into your design, you need to decide whether to apply that design now or later. More often in my experience, businesses want to apply it later, especially if it’s not visible to the user and not very tangible to them. We could tackle this by treating deferred design as technical debt. Like real world debt, though, technical debt incurs interest and the more payment (or implementation) is delayed, the more interest will start accumulating. Before long, the technical debt has become larger and the design is potentially harder to implement.
Another thing you may consider when technical debt is growing is to introduce a ‘Debt Ceiling’ and debt payment plans. The team needs to categorise each technical debt based on its complexity and impact/relationship to the more general aspects of your project. Once categorised, your design debt can be presented to and prioritised by all the stakeholders, and debt payment plans started by allocating design debt into future sprints. ‘Debt Ceiling’ is the amount of technical debt within your project allowed at any given time in your backlog. When a new design emerges and stakeholders want it to be delayed, ‘Debt Ceiling’ can be increased with the agreement of all stakeholders. By introducing the concept of debt to all the stakeholders, they will have a different mindset and will start thinking about technical payment plans.
Spikes before starting the implementation
Often the deferred design and technical debt are still unknown even to the Agile team themselves. We can deploy a special team to investigate this by including spikes in your sprint backlog. A Spike is an investigation effort undertaken before development starts for that related issue to decide the bet strategy and plan of attack for the problem. By timeboxing spikes we have more predictable effort to spend on sprint planning.
Refactor to harvest
When your Agile project reaches maturity and stability, a lot of the design technical debt has already been resolved and completed. But you can still find abstraction and harvest patterns by refactoring your code. Often, a lot of complex logic is hiding a pattern that could be harvested by simplifying it down or making it more human-readable. Maintaining cleanliness in your code is another important advantage to harvesting design patterns.
Emergent design should be a continuous effort for your Agile team. By practicing and applying it, your team will become more proficient at finding abstractions and patterns that lead to design itself. By having the designs as late as possible, we can wait until the last responsible moment to decide what’s best for it. Understanding some of these techniques, you can start applying them in your projects immediately. Even without sacrificing design, you can apply emergent designs very early in your Agile projects.
Freddie Muliantono - Project Manager