Scaling Extreme Programming: Dependencies
(This will be the first in a series of posts about XP. I’m publishing them here because the overlap with Tidy First? readers seems substantial & the subscriber list is long. Please lmk if you’d rather I had channel/topic.)
I have written before about Professor Zaninotto’s framework for understanding why complex systems are impossible to control. The tl;dr is that systems become unpredictable when you combine:
Variation in inputs
Many potential states of the system
Irreversibility (decisions once made have permanent consequences)
Inter-connection—changes in one element of the system spread to other elements
Extreme Programming works by reducing irreversibility. Promoting reversibility. Giving you an Undo button for projects.
Planned for the wrong priorities? No problem, we’ll replan Monday.
Changed the design the wrong direction? No problem, we’ll change it the other direction.
Accidentally changed the behavior of the system? No problem, the tests will catch it in minutes.
What About Orgs?
Reversibility unclogs complexity for Whole Teams of 15 or so. It’s hard work, but okay. However, I never developed a story about scaling XP to organizations of hundreds or thousands of people. (Much more about this in followup posts.)
Reversibility can go a long way even in large organizations. However, reversibility isn’t the whole story. Inter-connection, which is addressable in a world of direct human relationships among 15 people, becomes a more disruptive factor & difficult to address among a thousand.
Let’s say you have an organization with lots of teams & lots of dependencies between teams & lots of missed deadlines & lots of unexpected delays. You’re not out of luck. Here are 10 things you can do to tame the dependency head of the Complexity Dragon:
Awareness. If things are herky-jerky & unpredictable & you have no idea why, having a map of the teams & dependencies is the first step.
Team improvement. All that XP stuff (planning, pairing, whole team, testing, incremental design) can improve conditions for downstream teams. If the problem is upstream teams, it won’t help the overall system & very well might hurt it (← painful experience).
Slack. Individual plans must contain wiggle room if the whole system is to have any chance of working smoothly. How much? You’re not going to like the answer, but you’ll have to figure it out empirically.
Waiting. You depend on something to be done this cycle in another team? Push your task to the cycle after their’s is done. Yes yes we all want to get done sooner, but I’m assuming that you’re already not getting things done as quickly as you’d like so this doesn’t make reality worse, just the plan.
Slicing. If you have a depended-upon goal, go to the dependencies & figure out which half they’d most like to see first. Yes yes they want the whole thing, but there’s always a half that’s most important. Better to slice now than slice later & way better to slice now than to have the whole thing tumble down at the last minute.
Prioritizing. If you have a depended-upon goal, move it earlier in your cycle. You’ll get quicker feedback & your downstream customers will get early notification of changes.
Duplication. Sometimes we spend millions in dependency costs (delays, unpredictability, lost trust) to avoid thousands in duplicated effort. If you depend on another team’s goal, consider just implementing the bit you need yourself. (This implies that you have a reconciliation process that will operate later.)
Task forces. Combine some folks from each team to work together closely but temporarily to implement enough of the depended-upon task & the dependent task.
Visit. If they don’t have time or priorities to do a task you depend on, implement it yourself in their code. This only works if that team has tests, builds, a reasonable amount of coupling, & a society of earned trust.
Plan needs, not tasks. If my team needs your team to improve performance, the plan should describe the necessary performance & not tasks you expect will get you there. This leaves you the freedom to learn & adapt along the way.
Merge teams. If 2 teams have dependencies back & forth, consider merging them. An awkwardly large team is easier to manage than 2 angry teams.
Self-service. If your team is depended on & your people are the bottleneck, automating your work can reduce or eliminate the dependency. The time you need to implement self-service is the price you pay for not having to manage the dependency.
APIs. Making explicit the information that passes between parts of the system frees each part to evolve independently. Until you realize the boundary is wrong & you have to pay to fix it, but that’s the price of learning.
That’s just a list off the top of my head. Let’s organize it by who needs to be involved in each dependency management activity: managers, producers, & consumers.
I feel better now. Regardless of what role I am playing, if I encounter dependencies there’s something I can do about them besides just living with them.