We all know that when you are trying to get a software product delivered, that dependencies are “bad”, but we also know that we will have them. I think, however, that we underestimate just how big an impact can have on the successful delivery of a project, with the implication that we should be doing a lot more eliminate, or at lease reduce, dependencies that are built into the way we deliver value.
If you asked any project person “What is the ideal development situation” you would hear “the situation where I have total control of the situation.” In other words, a world where the work I am doing has no dependencies on any other work. Why is this the case? Its because I have total control over the success or failure of the project.
Lets say we are providing our project is to provide a service to another person. In other words, your customer is dependent on you, but you have no dependencies. You customer has a natural concern in that for her to be successful, not only does she have to be successful but you do too. Interestingly the success she has is not only dependent on you doing a good job, but also doing it on time so they can do their work. Success is “value provided”, “to quality standard / defect free”, and “timely”. If we do the work and deliver on time, but then get feedback that we have not got the answer we need, then from the perspective of the customer, we now have a failure to deliver the dependent capability.
Lets say our chance of delivering the dependent capability is 50% by this criteria; this sounds bad I know, but I always assume our customers will provide some feedback as a result of seeing what we have provided for them. For the customer of our capability to be successful you need to be successful, and the customer needs to be successful. There are 4 ways this can work out:
In other words, there is a 1 in 4 (or 25%) chance for your customer to be successful in the delivery of the capability and in the timely fashion.
But guys, this is just one dependency. What happens if we have 2, or 3 …
It turns out the chances of success are exponentially lower the more dependencies you have! For X dependencies, the chance of success is 1:2^(X+1) or as a table:
Dependencies (50%) | 1 in X Chance | Percentage Chance |
---|---|---|
1 | 1:2 | 50.0% |
2 | 1:4 | 25.0% |
3 | 1:16 | 12.5% |
4 | 1:32 | 6.3% |
etc | etc | etc |
“But”, I hear you say, “we are much better than that 50%, even with that criteria. We operate typically at 80% success rate.” OK, I understand, although I suspect that is not true, but if we run the numbers that way, we get:
Dependencies (80%) | Percentage Chance |
---|---|
1 | 64% |
2 | 51% |
3 | 40% |
4 | 33% |
As you can see, even with that high success rate, a string of dependencies will quickly create a problem. With just 2 dependencies you are already a coin toss (about 50%) as to whether the whole thing will be delivered successfully.
Dependencies means delays
There is more to this problem than a simple problem of risk management. One of the reasons people want to deploy an agile approach is that they want to reduce “time to market”. From a feature perspective, we want to want to understand how long a feature is “in progress” or cycle time (some call this lead time). The problem with dependencies is that the more dependencies you have to release a feature, the longer the time it will take to build.
How long will it take to deliver a story? If we assume that we have a common Sprint length and that in the normal case a team takes on and completes their work in a Sprint then a simple model for calculating the amount of time it will take is:
Cycle time for story with dependencies = sum (sprint length for all teams in the dependency tree)
If you have a common Sprint cadence (i.e. all teams finish the Sprint on the same day) or:
Cycle time for story with dependencies = sum (sprint length for all teams in the dependency tree) * 1.5
If you do not.
Dependencies | Number of Synchronized Sprints (to complete a stories) | Number of Unsynchronized Sprints |
---|---|---|
1 | 2.0 | 3.0 |
2 | 3.0 | 4.5 |
3 | 4.0 | 6.0 |
… | … | … |
7 | 8.0 | 12.0 |
And so on. Now if you are thinking “we want quartertly releases”, and your user stories “require” work from a number of teams (in other words, you are organized as a series of teams that do not deliver whole features but rather architectural layers of a product) then you have a problem.
You might argue that this thinking is too pessimistic. You will often see teams start and complete work mid-Sprint or even jointly work on items in parallel. Others argue that this thinking is too optimistic as teams produce bugs with introduce loops and additional delays in getting an item finished. In general I've found that while your specific numbers might vary the analysis is valid and can be easily made more realistic based on your data.
Simply …
“Why is hand-off so destructive? Because the best teachers on their best days get across less than 30% of their knowledge. So, hand-off implies throwing away at least 70% of knowledge on its way to the people doing the work“ — Allen Ward
Every time you hand something over from one person or group to another, you lose knowledge, unless you spend a lot of time making sure the information needed also flows through.
The book "Team Topologies" by Matthew Skelton et al argues that in order to improve the flow of value you should organize Teams and Trains so they have low cognitive load.
There are three types of cognitive load:
In many cases cognitive load increases as a function of the number and type of dependencies we have, which again impacts the flow of value.
Now my question to you - “how many dependencies do you have in your project and how deep are they”?
The “deep” question is based on thinking through “in order to deliver value of a specific item to a customer, how many layers do I have to touch?”
One of the problems with traditional software development has been that we increasingly created silos of knowledge based on specialization of disciplines. As a simplistic example, we'd have a team that would be responsible for the user interface, another for the business logic, still another for the data access. In order to deliver any functionality that the customer would regard as valuable, we immediately have created an environment where the probability of success is around 12% for any feature as there are 2 dependencies (assuming UX is the “driver”). Worse, all our features require a path through all these layers, and so we set up this “failure” environment for all features in a project.
Dependencies lurk everywhere:
The more dependencies you have, the more likely it is that your project won't be successful.
The steps are simple to describe but, of course, hard to do for any decently sized project:
For those that follow approaches adopted by Amazon, they take an aggressive approach to dependencies. Basically the idea is that it is up to everyone to aggressively work dependencies in Amazon. It is seen as a sign of leadership. Jeff Bezos broke the approach down to 3 steps:
1. “Whenever possible, take over the dependencies so you don’t have to rely on someone else.
2. If that is impossible, negotiate and manage unambiguous and clear commitments from others.
3. Create hedges wherever possible. For every dependency, devise a fallback plan—a redundancy in a supply chain, for example.”
Note: You need to make sure that you really do work the dependency and improve your execution. For example just moving the work from 2 teams doing the work to 1 does not eliminate the dependency. It only potentially helps eliminate the dependency. If the team that takes on both sets of work does not materially change how they are going to compete the total work then you can expect only limited benefit from putting it in to one team. But I also think there is a chance for improved success because that option is available to the team and, at a minimum, learning from doing package 1 is available to the team which is also working the next package.