Developing software is risky and expensive. Software is formless and hard to understand. Subtle interaction can cause software to affect seemingly unrelated components. A good development process focuses on mitigating risk by finding problems early, before they become showstoppers, and while there’s still time to resolve them.
1. Integrate continuously
Creating a system that can be built from day 1 and continuously integrating software into that system as it’s built is the only way to eliminate risk. Delaying integration until one of the last steps before release is a bad idea because integration is the time when we see how our code behaves with other code in the system. It’s often when the nastiest bugs are found. A feature remains unproven and carries an unknown amount of risk until it’s integrated into the system. Integrating features into releases that are tested in large batches is like going all-in in Vegas. The odds are against you.
2. Avoid branching
When we branch in a version control system by feature, team—or whatever—and then integrating those branches before release we are doing Waterfall development. Agile is about burning down risk and that can only happen when code is integrated as it’s built. Once code is integrated into the system the risk drops to near zero, but when components are built in branches and integrated before release the risk is unknown until the branches are integrated. Instead of branching use feature flags to turn off features in the system while they are being built but not yet ready to be activated.
3. Invest in automated tests
Removing all human intervention for validating a release candidate so tests are entirely automated is essential for dropping the cost of development. Fast automated tests let you run them any time and provide important feedback. If you find it difficult to do test automation in your system then consider a redesign to something more testable. A lack of testability often indicates a poor design.
4. Identify areas of risk
Risk often has to do with unknowns or things out of our direct control. Identify what these things are by asking what could go wrong. Identify external dependencies, the things out of your direct control, and then look for ways to mitigate those risks and decouple dependencies.
5. Spike on unknowns
Once an unknown is identified you can work on it for a short period then check in to measure progress. Spikes are generally focused around a question or series of questions to be answered. By creating short time boxes with check-ins and measuring progress we hope to avoid going down ratholes and wasting time. Try to keep separating the known from the unknown so the unknown becomes smaller and smaller.
6. Build the smallest pieces that show value
The whole premise of Agile is to build in small batches. Smaller problems are easier to understand, solve, prove, and maintain. But how small should you make it? My rule of thumb is to build the smallest thing that shows value. If 80% of the value comes from 20% of the features then let’s build that 20% first. We might not even need the other 80%.
7. Validate often
Our customers may not know what they want until they see it. Getting validation early and often can help us build a higher value product and engages the customer in finding better ways of doing things. When development can become a partnership between the customer or PO and the developers we can often build better features than we could have with all the upfront planning in the world.
Reducing risk in software is about assuring that you’re building the right things and assuring that you’re building the things right. We know we’re building the right things by getting feedback from our users early and often. We know we’re building the things right by following good engineering practices for building changeable code that’s continuously integrated into the build. By doing these two things we can significantly improve our likelihood and degree of success.
Previous Post: « Seven Strategies for Measuring Value in Software
Next Post: Seven Strategies for Fixing Bugs »