In my post about how to form teams, I talk about products… not in their monolithic, holistic state… but as a subsystem within a larger integrated solutions architecture. In other words, big products are just a series of small products that work together in an integrated fashion. Each of these smaller products has a backlog, a team, and the team can produce a working, tested, increment of the product at regular intervals… you get the idea.
There are tons of reasons that make this approach a great way to build software. Code ownership is less complex. Branching strategies simplify. We have a much smaller group of people interacting with the codebase and business logic, etc. The downside of this approach is that you’ll probably have to coordinate requirements dependencies between teams and you’ll often introduce sequencing dependencies between subsystems.
We’ve established that dependencies are evil, so let’s talk about a few strategies for breaking them or at least minimizing their impact:
1. To fully break dependencies between products and shared components, products can only commit to features built on capabilities already present in the shared component. Products can request new capabilities from their component teams, but those requests go into the queue and get done when they get done. It’s as if the component team was a separate company having to balance the needs of multiple customers to provide the most value to as many people as possible. The product team can request new capabilities, but they cannot mandate them or set a date.
2. To minimize dependencies between products and shared components, products can only commit to capabilities that are on the near term roadmap of the component team. In this case, if the component team is stable and has a known velocity… and they can reliably size your request… and let you know where you fit into their backlog… it might be safe to bet on the fact that nothing will change and you can get your capability added in the sprint or release that the component team has planned. This is only safe a sprint or two or maybe a release out.
3. To manage dependencies between products and shared components, products inject capabilities into the component teams backlog and force a dependency. This is the riskiest of all strategies, but could possibly be necessary for some circumstances. In this case, each team better have a stable backlog and a known velocity and be able to make and meet a commitment with a pretty high level of confidence. If this is an exception to the rule, and only used as a last resort, you might be able to get away with this occasionally. Again, this is the least desirable approach.
So in short:
1. Never commit to a feature that depends on a component capability that does not exist
2. Sometimes commit to a component capability on the near term roadmap
3. Rarely commit to a component capability with a hard date-driven dependency.
Let me know if you have any questions or comments. I think this is going to be a challenging concept for many folks. I’m interested in your thoughts.