Incremental results, not incremental implementation
Update: Added section on iterative development.
You’re working on a large project, bigger than you’ve ever worked on before: how do you ship it on time? How do you ensure it has all the functionality it needs? How do you design something that is too big to fit in your head?
My colleague Rafi Schloming, speaking in the context of the transition to microservices, suggests that focusing on incremental results is fundamentally better than focusing on incremental implementation. This advice will serve you well in most large projects, and to explain why I’d like to tell you the story of a software project I built the wrong way.
A real world example
The wrong way…
I once built a system for efficiently sending streams of data from one source to many servers; the resulting software was run by the company’s ops team. Since I was even more foolish than I am now, I implemented it in the following order, based on the architecture I had come up with:
- First I implemented a C++ integration layer for the Python networking framework I was using, so I could write higher performance code.
- Then I implemented the messaging protocol and system, based on a research paper I’d found.
- Finally, I handed the code over to ops.
As you can see, I implemented my project based on its architecture: first the bottom layer, then the layers that built on top of it. Unfortunately, since I hadn’t consulted ops enough about the design they then had to make some changes on their own. As a result, it took six months to a year until the code was actually being used in production.
…and the right way
How would I have built my tool to deliver incremental results?
- Build a working tool in pure Python. This would probably have been too slow for some of the higher-speed message streams.
- Hand initial tool over to ops. Ops could then start using it for slower streams, and provide feedback on the design.
- Next I would have fixed any problems reported by ops.
- Finally, I would rewrite the core networking in C++ for performance.
Notice that this is seemingly less efficient than my original plan, since it involves re-implementing some code. Nonetheless I believe it would have resulted in the project going live much sooner.
Why incremental results are better
Incremental results means you focus on getting results as quickly as possible, even if you can’t get all the desired results with initial versions. That means:
- Faster feedback: You can start using the software earlier, and therefore get feedback earlier. In may case I would have learned about ops’ use cases and problems months earlier, and could have incorporated their suggestions into my design. Instead, they had to patch the code themselves.
- Less unnecessary features: By focusing on results you’re less likely to get distracted by things you think you need. I believed that Python wouldn’t have been fast enough, so I spent a lot of time upfront using C++. And the C++ version was definitely quite fast, faster than Python could do. But maybe a Python version would have been fast enough.
- Less cancellation risk: The faster you deliver a project, the faster you can demonstrate results, and so the less risk of your big project being canceled half-way.
- Less deployment risk: Instead of turning on a single, giant deliverable, you will start by deploying a simpler version, and then upgrading it over time. That means more operational knowledge of the software, and less risk when you turn it on the first time.
Beyond iterative development
“Iterative development” is a common, and good, suggestion for software development, but it’s not quite the same as focusing on incremental results. In iterative development you build your full application end-to-end, and then in each released iteration you make the functionality work better. In that sense, the better alternative I was suggesting above could be seen as simply suggesting iterative development. But incremental results is a more broadly applicable idea than iterative development.
Incremental results are the goal; iterative development is one possible technique to achieve that goal. Sometimes you can achieve incremental results without iterative development:
- If each individual feature provides value on its own then you can get incremental results with less iterative, more cumulative development. That is, you don’t need to start with end-to-end product and then flesh out the details, you can just deliver one feature at a time.
- Incremental results aren’t just about your development process, they are also about how results are delivered. For example, if you’re streaming a website to a browser there are two ways to send images: from top to bottom, or starting with a blurry image and getting progressively sharper. With a fast connection either choice works. With a slow connection progressive sharpening is superior because it provides information much sooner: incremental results.
Whenever you can, aim for incremental results: it will reduce the risks, and make your project valuable much earlier. It may mean some wasted effort, yes, as you re-implement certain features, but that waste is usually outweighed by the reduced risk and faster feedback you’ll get from incremental results.
PS: I’ve made lots of other mistakes in my career. If you’d like to learn how to avoid them, sign up for my newsletter, where every week I write up one of my mistakes and how you can avoid it.