The Agile Codex emphasizes strict dependency identification and tracking. Why is this so important?
The Importance of Dependencies
The fundamental question in any project always comes down to “What is going to be delivered, and when?” Arriving at the truest answer to this question is the holy grail of all collaborative building projects. Imagine a conversation with a few tradespersons building a home:
“Charlie, When will those two boards be nailed together?”
“Two minutes (assuming the hammer hits the nail on the head and the boards stay true).”
“Ana, when will this wall be framed?”
“Three hours (assuming the studs were nailed together as planned (assuming the hammer hits the nail on the head and the boards stay true)).”
“Jack, when will the house be framed?”
“5 days (assuming the walls were framed as planned (assuming the studs were nailed together as planned (assuming the hammer hits the nail on the head and the boards stay true))).”
At each level, the “what” that is being delivered changes. Everyone along the chain of delivery asks for their “what.” And sometimes, when they worry, they ask for the “whats” before that, and before those:
“Are you sure the frame will be done in 5 days, Ana? What about the kitchen wall, Jack? Will Ana really get it in time?”
Depending on the level you look, not only does the answer but the question changes as well. At the micro level, we are asking “When will those two boards be nailed together?” One level higher: “When will this wall be framed?” Another level: “When will the house be framed?” until finally: “When can we move in?”
At each higher level, the answer becomes loaded down with more and more assumptions.
So, the answer is always, “it depends,” meaning, it is critical that at any level it is easy to unroll those dependencies to both calculate and justify the answer.
Sometimes the “what” is more important than the “when,” such as we often see in the video game industry, or with Apple hardware releases, where rumors of and actual delays are the norm.
Sometimes the “when” takes primacy, especially in emerging software startups, where Minimum Viable Product is the goal, and first customers have the expectation that they will be beta users for a long time.
Sometimes neither matters, as in the world of experimentation and research into emerging or not-yet-existing markets, such as Alphabet’s X – the moonshot factory.
Both “what” and “when” are important in large projects with many interdependencies and cross-team collaboration, where delays and bugs can have significant cascading upstream and downstream effects as you might see in the enterprise software industry and high-technology-equipment manufacturing.
Every assumption is a dependency.
Every dependency is a risk.
Every risk has a cost.
Planning and executing the delivery of software is the art of minimizing that cost, which means identifying, classifying, and minimizing risk throughout the life cycle by correctly identifying and tracking dependencies.
Building the Assembly Line
Now a thought exercise to draw a (literal) picture of what the Codex means in practice: we will build a saltshaker.
In the physical world, the order of operations is largely obvious, thanks to gravity. In order to build up, you must root down. No roof can be placed on a home without walls. No walls can be placed on soil without a foundation. While some things can be built in parallel, and stitched together all at once, the full assemblage can never exist out of order.
So to make these dependencies obvious, let us start with an example in the physical world. Consider the saltshaker. A ubiquitous, unassuming resident of every kitchen and restaurant table. What is it made of?
Simply:
A base that holds salt, and a lid with holes in it.
Let us break that down a bit more.
The base is hollow. It is light enough to be picked up with one hand. It may be transparent, allowing one to see how much salt is inside. It may have ridges, or texture to ensure a secure grip while shaking. The top is threaded to secure a removable lid. The base is flat, to keep it upright. It has enough volume to store many shakes of salt. The lid has holes in it, of just the right diameter to let some grains pass when inverted, but not too many. And there are enough of these holes that every shake accumulates enough salt to mitigate the need for too many shakes when seasoning a typical plate.
As the inventive humans we are, we imagine the construction of this saltshaker. We invent it backward by detailing its physical components in their final form:
The base is a hollow cylinder of ridged glass, threaded at the top. The lid is stainless steel, perforated on top, and threaded to the size of the base.
And imagine backward thus:
The lid: Given a steel disc, shape it into a lid. Thread the lid and poke holes in the lid.
The base: Given glass, shape it into a hollow cylinder. Thread the glass at the top of the cylinder.
Assembly: Screw the lid onto the base.
And now we have our simplified assembly line.
Every tool takes a certain amount of time to do its work – to transform the object from one state to another. And some states take a tool longer to transform than others. In our case, it turns out that threading a glass cylinder takes two minutes, while threading a steel disc takes three.
Based on this, how long does it take to build our saltshaker?
Pretty simple and straightforward so far, right? Now let us complicate it.
Now that we have our assembly line, and this new constraint where the same tool cannot be used simultaneously, how can we parallelize the work to minimize the calendar time spent (indicated by the length left to right)?
Parallelize the work to minimize calendar time.
Time to perform each step.
Required sequence of steps.
No steps requiring the threader or shaper can happen concurrently.
Now play out each possible scenario (removing the final assembly step which is common to each).
Cylinder shaping must happen before threading.
Lid shaping must happen before perforating and threading.
Lid could be perforated before threading.
Lid could be threaded before perforating.
Calendar time: The total time for the saltshaker parts to be complete
Effort time: The total time spent doing work before the saltshaker is complete
Idle time: The time work is not happening before the saltshaker is complete
Scenario 1 has the fewest gaps, or least idle time possible, at 1, and also has the shortest calendar time, at 6. Scenario 1 is the optimal choice.
In Review
Which steps could happen in either order
Which steps could not
How long each step takes
Which steps use the same tool
Once we identified the possible dependency trees, we were able to play out scenarios until finding the optimal solution.
This same mechanistic process of optimizing the assembly applies just as well to our software assembly line. As with our saltshaker, all software delivery methodologies are dependent upon how well the end product can be envisioned and broken into discrete, sized, and sequenced tasks, which are then optimally parallelized across shared resources.
If anything causes the tree to change, we can simply reconstruct the new tree and replay scenarios as above, choose the optimal one, and resequence our assembly line to reflect it.
In this book we will move this saltshaker analogy into the software world, making the case for the effectiveness and feasibility of this platonic ideal, and how we can best approach it in a variety of circumstances. Because it turns out that doing this well, in the right way, not only maximizes certainty around what will be delivered by when, it also minimizes the cost of the inevitable: change.