(special thanks to Deepa Joshi for her input!)
This is the fourth and final part of my series on work breakdown (WBD) for large software efforts. In the last post I chatted in detail about what constitutes a good piece of work in the breakdown, but in this post I'd like to get more holistic and talk about what the entire WBD will look like when it's done well, and how the pieces of it should inter-relate. This is the critical big-picture view.
A good WBD will ideally have 3 primary properties defining the relationship between the pieces: mutually exclusive, collectively exhaustive and prioritized.
The pieces should ideally have no overlap of effort between them. You haven’t really successfully broken something down if the pieces haven’t been completely separated. Some pieces will definitely require other pieces to be completed first, but that can be done with proper sequencing and without actual overlap.
The pieces should ideally comprise the entire effort and not just part of it. It’s much more difficult to manage an incomplete WBD where we’re regularly adding more work. Many runaway projects that I’ve seen suffer from a lack of holistic view of the entire breadth of the project. Sometimes there are a bewildering number of unknowns, but those should be handled as early as possible with questions, experiments, prototypes, research, etc, so that the WBD converges on “collectively exhaustive” as quickly as possible.
Prioritization is another huge part of the breakdown process. If we’re continuously delivering value, we want to be delivering the highest value first and then decreasing value over time. There are different kinds of value to consider too: derisking, dependencies, learning & business-value. You also want to consider the cost of them (usually just measured in developer time, but not always). I’m not going to get into prioritization frameworks, or tell you how to decide between the things that deliver business-value, but it is useful to talk about how to prioritize business value among the other kinds of value.
User / Business learning: Probably the biggest waste in software development is building the wrong thing, so we want to prioritize this type of learning pretty highly. Especially learning that:
Approach-Derisking: Assuming we’ve got high confidence in what we’re building, we next want to derisk our approach. First we want to derisk the actual plan by figuring out whatever we need to, to ensure the work breakdown is comprehensive. Secondly we want to do any technical research, prototypes, or experimentation that we need to do to clear up anything that’s technically complex and not straightforward.
User / Business value: You want to deliver things in order of business value so you capitalize on your efforts in the most optimal way possible. Even if you’re not delivering to production until completion of the entire effort, you still want to derisk the highest value things first by getting them as complete as possible first.
Dependencies: You’re basically forced to prioritize fulfilling dependencies before their dependents, but it’s helpful to make this explicitly part of your prioritization. Otherwise there’s potential for people to not see dependencies and start work on something with unfulfilled dependencies. They’re sure to eventually get blocked and forced to work on the dependency. Dependencies themselves have risks as well, so it’s better to work on them first and not have them block other efforts.
It’s also worth noting that the clock runs out on plans before they’re complete all the time. Companies change priorities and cancel plans in progress. Prioritizing like this ensures that the work that we don’t do is the lowest value work, and ensures that even if we’re interrupted, we’ve still captured as much value as possible in the time we had. It’s also worth looking at the lower priority work early-on to see if that work can just be considered for a subsequent effort instead, or even eliminated. Proactively removing work that doesn’t need to happen as part of this effort can have a massive positive impact on the size of the effort and the speed at which it’s delivered.
Being able to build and deploy the work is table-stakes. You can’t play the game of software delivery if you can’t build and deploy the work. I highly recommend that the first thing that you do is to ensure deployment is possible and safe.
For new software where no one is using it yet, it’s good to set up your build and deployment so that you ensure early and often that what works on your machine works equally well in your target production environment. It takes no additional time because you have to do this eventually anyway, and you don’t want to be debugging environmental differences after you thought everything was done.
For existing software, ensuring safe deployment is equally critical. If we’re focused on continuous delivery and we’re so results-oriented that our progress is visible in production, we’re almost certainly using feature flags so it’s worth chatting a bit about them as part of the WBD for those that are working this way.
My primary piece of advice is that you always deliver the feature flag FIRST as part of the greater effort, because that’s what enables the rest of the delivery to be both safe and continuous.
Secondarily, it should reveal as small a piece of functionality as possible to be still visible. The functionality revealed could just be a placeholder for future work (like a “hello world” message), but you do want to show that the feature flag is working end to end (be Visible!). This proves that you will be continuously deployable as you go, and allows you to turn on the feature flag internally so everyone can test the real production progress whenever they want.
I think this feature-flags-first policy is worth noting here separately because in general people naturally tend to not add the feature flag until the perceived end of an effort when they start thinking about delivering everything in totality to real users. Adding the feature flag last means that you’re integrating your work at the very end. That’s a completely unnecessary addition of risk. Your internal teammates have a harder time seeing things along the way and giving feedback, and you unnecessarily delay finding out about any trickiness of adding the flag that might seriously impact your timeline. Some feature flags are really non-trivial to add.
Finally, I’d like to discuss how to do all this continuously. A good WBD is the essential core of a good plan in general. The thing to know about plans though is that they quickly drift away from being the most optimal plan as we work through them. We learn new things. We find out that we had some things wrong. Circumstances change. Plans fall apart.
For these reasons my strong recommendation is that, as you go, you continue assessing your work breakdown along all the criteria written here, and improve it continuously. You don’t want to foolishly pursue a plan that is falling apart. You want to react to new information and keep adjusting the plan.
The most common questions you’ll want to ask yourself are:
In short, make your planning and replanning activities more continuous. Ask yourself continuously: Is this still the best plan? If it’s not, fix it!
I know that this 4-part series about breaking large software efforts down can seem like a bunch of bureaucracy compared to immediately getting to work on writing the code, but it really is pretty critical if your software effort is large. Sure I've seen teams function well without this kind of rigor, but usually it's when they have work that is already naturally broken down into thin vertical slices (eg maintenance teams or growth teams). For other types of teams that actually are delivering larger efforts, not putting the time in to get a good WBD can mean that you're working on the wrong things more often, or delivering value to users more slowly. In the worst cases, the project can go completely off-track and be a total failure. Not only will a good WBD help prevent these types of things, but sometimes you can even apply a good WBD to a failing project and bring it back on track.
Think of it instead as a design exercise. You want to design your work so it's the kind of work that makes you look and feel successful as you accomplish it. It also happens to be the kind of work that will actually be successful.