About continuous improvement
At the moment, NASA’s most ambitious project is to develop a space ship that can bring 46 tons of cargo into space. The project was started in mid 2011 and the first flight was planned in 2016, but that did not happen before end 2022 due to all kinds of delays. The initial development cost was estimated at $18 billion; up until now, the project has cost about $24 billion and the total estimate is $70 billion. When ready, a single flight is estimated to cost about $1 billion.
SpaceX is also developing a comparable space ship. It can deliver 100 tons of cargo into space. The project was revealed by SpaceX in 2016; a first orbital test flight is planned for 2023. When ready, a single flight is estimated to cost about $1 million.
The differences are striking. NASA has been developing rockets for decades. As long ago as 1969, they were able to put men on the moon, whereas SpaceX had their first launch only in 2006. Yet, they are able to develop a better product in shorter time with much lower cost. Where does the difference come from? Although I am not an insider, literature suggests that one major cause is the difference in organizational principles that they apply. NASA develops in big projects with tightly defined phases, each phase making a massive leap in development. On the contrary, SpaceX is much more focused on delivery: they start with a basic platform and grow on that, each time adding new functionality and applying what they learned. Although SpaceX did not yet perform an orbital test flight, many parts of the projects have already made live tests. It’s the difference between top-down and bottom-up development.
When developing software, can we apply this principle too?
Read more: About continuous improvementImprovement levels
The core idea of how SpaceX works is incremental improvement. Start small with something that can be fairly easily be delivered, and then incrementally add to that, solving one challenge at a time. But do not stop to keep improving. It is evident that this requires flexibility built in from the ground up, because the list of improvements is also flexible, and you may end up with a product that is being used completely different from what was envisioned at the start.
How can we apply the incremental improvement approach? In my opinion, there are three aspects required:
- The increment is defined as something that is a well defined delivery that provides value to the user. This includes all necessary testing levels and deployment. In the software world: it is a program that is run by actual users.
- The increments are small. If you’re new to this: as small as possible is fine. In my experience, it takes practicing to define actual increments. I often see people falling back to defining increments like “define the database structure”. This is asking for problems (more about that here).
- New increments include the lessons learned from the experience with the product. So the project planning must be flexible: experience may show that some feature is much more important than originally envisioned, or that changes are required to an already delivered feature.
Incremental improvements
Working with increments has the huge advantage that you can make improvements every time a new increment is started. Since there are many increments, improvements do not have to be very big in order to have a big effect. Also, improvements can be applied very early in the project, so they can provide their value much earlier.
The incremental approach also has another huge advantage: it makes failing fast possible. Now failing does not sound like an advantage, does it? But it still is tremendously important to allow failures to happen early in the project. Because early in the project, failures tend to have little consequences, but often provide valuable insights. Those insights is what we’re after, because they can guide is throughout the project. With NASA’s “quantum leap” approach, the most important insights become only apparent very late in the project, where it has become impossible to change directions. That is why the SLS project had many setbacks and cost overruns. You’re going to make failures anyway, therefore it is better to anticipate on them rather than to postpone them. Failing early is much cheaper than failing later (orders of magnitude). In other words: learn as fast as possible by figuring out what works and what not.
Can it work?
When I first encountered the incremental delivery approach, I was a bit skeptical. There were two main reasons for that:
- I doubted that it was possible that there were changes that couldn’t be made in the incremental fashion. I imagined that there were certain big bang refactorings that were required, but not possible to break down into smaller increments where each increment would deliver value. It turns out that that is not the case. In practice, such a change turns out to be a generalization, and it is always possible to go from a specific implementation to a more general one.
- Each increment allows for optimizations. This means that optimizations are relatively small. I figured that the local optimization problem may occur: since optimizations are done locally, it may lead to a local optimum so that big improvements are missed. But this is not the case, because the lessons learned from delivery are not local but global. So improvements contribute to a global goal.
Also, because of the early delivery, you get a feeling for what is actually required (instead of what you think is required). This leads to insights into what works and what doesn’t. These insights follow from the failures early on because they tell what works and what not, so they act as a very powerful feedback mechanism.
Another insight I learned over the years is that software is always work in progress, so better treat it as such. This means that features can be finished, but the product itself cannot. There is always room for improvement.
Incremental improvement approach
If you want to deliver using an incremental improvement approach, then there are a number of things to take into account. One insight is that improvements can be done on a number of axes:
- Product axis: this is about which features and fixes will be included in which increment.
- Process axis: this is about how the product is being made.
- Person axis: this is about how you do your work. During development, it is very possible that you realize that you need to learn a new technology. It is wise to take these lessons into account.
The next paragraphs will elaborate on the details for each axis.
Product improvements
The product is what you made. Improvements to the product will make it more usable for the intended audience. Or it might make it suitable for new audiences. This is basically not the domain of product management. A good product manager weights the estimated cost of developing a feature against the value it may deliver and ranks them according to this priority. A good product manager also finds out what users actually need.
As a developer, you also need other feedback mechanisms to deliver early and often. As a basis, a good CI system is indispensable. It will turn out that you need to introduce new abstractions in order to make the software more flexible. You need to refactor out duplicate code and cases of structural duplication. And when the software grows, it eventually turns out that some parts of the software have functional overlap, which gives rise to new generalizations that you didn’t recognize before.
Process improvements
Incremental delivery means that you need to deliver early and often. On process level, this means it is very important to reduce the cycle time, that is the time between the start of a feature until it is delivered. Shorter cycle times means that you can deliver more often, and hence learn faster. This starts by defining features of the right size. But it goes further than this: also the time required for testing and deployment must be reduced as much as possible. This also means that implementing Continuous Integration very early provides great value throughout the project.
An alternative approach is to reduce waste, where waste is defined as “everything that does not add value for the customer”.
In order to come to good process improvements, it is very important to have a review once per iteration. This review does not only inspect the product, but also the process. It must come up with concrete improvements that can be implemented right away.
Personal improvements
Just like the development process and the developed product can be improved, so can the developer itself. Since it is very difficult to see what you miss, finding concrete personal improvement actions is very difficult. But still, this will provide very much value. Personal improvement also has a number of aspects:
- Hard skills: these are the skills to do your specific job. For a developer, this includes things like mastering programming languages, frameworks and technologies. In short, everything that you can put on your resume.
- Soft skills: these skills are much less tangible, but they are regarded as important as the hard skills. Examples of these are problem solving, analysis, communication skills.
- Domain knowledge: when you recognize that you miss some knowledge, it may be sensible to spend time to improve it. This can prevent mistakes due to misinformation.
- The key here is not to personal development (which is important but not the subject of this blog post), but think from a project perspective what you can do.