Addressing Product Delivery Debt
Updated: Oct 20, 2021
By now everyone knows what technical debt is, right?
All the inefficiencies, which have accumulated over time on the project, that are not technical debt -- are called "Product Delivery Debt".
Just like the Tech Debt, Product Delivery Debt must be paid off --or else, it will cripple your product, or even destroy your company.
How does it even happen? Quite natural. In the beginning, you start with nimble team and simple process. Over time your team will grow, every new person on the team will start with evaluating your process and trying to make "improvements" by adding something to your process. Eventually, things will get so complex, that no one will be able to understand how the process works any more. Just like the Tech Debt, this is natural and unavoidable. The real problem is, that, just like the Tech Debt, the Delivery Debt must be addressed.
How do you know if you have too much Product Delivery Debt? Jira is a good place to start. The same idea applies to any Agile project management tool. Jira is a direct reflection of your process complexities. But Jira also directly influences your process. That's why I'm not a big fan of superb Jira customization ability -- it opens a pandoras box and you will complicate things just because you can.
If you have to call all hands meeting to explain how you intend to use Jira -- that's one giant red flag. If you have to explain it to your staff more than once -- you are doing it all wrong. Here are typical Jira red flags to look out for:
too many columns/states
too many types of stories
too many cards in any given column
creating new card takes more than 1 click -- you have to remember to select values in 10 different customizable drop downs before you can click submit.
It all starts at the Product BackLog. The product owner is responsible for keeping the backlog in order (at least the top portion of it). Only top 10-20 stories need to be groomed -- requirements well defined and stories estimated by the engineering team. These 10-20 stories must also be always properly prioritized by the PO -- the only way to define priorities in Jira should be the order of the backlog. Having customized fields like "Priority", "Urgency", "Emergency" etc... create ambiguity and confusion. If the card must be worked on right away -- move it to the top of the backlog.
I've heard many complains from the PO's that everyone in the company has a way too much power to dump anything they want in the backlog, which makes the backlog a mess. If you (the PO) only concentrate on the top 10-20 stories -- it really should not matter what else is added to the backlog or how big it grows. If an urgent story is added to the backlog, which needs to be dealt with the highest priory -- you will know one way or another. Just move it to the top of the backlog, take the back sit and relax -- your job is done here. Don't worry about the things you can't control.
When the next highest priority story is picked by an engineer from the top of the backlog, it enters the Delivery Pipeline.
Efficient process does not have to have more than 3 columns (states) in the pipeline:
WIP (Work In Progress)
I've seen Jira projects which have 20!!! different columns defined -- this kind of complexity is impossible to manage and is unacceptable.
Why do you need to have columns like "Ready for Testing", "In Testing Review", "Testing Blocked", "Waiting for User Acceptance Testing", "In Testing", "Testing Completed"? When you are (the engineer) done writing code -- move the story from "WIP" to "In Testing" column. Let the QA team figure out how they want to deal with it. As soon as the story shows up in "In Testing" column, it becomes a priority for the testing team.
Similar idea applies to everything else in Jira. You may think that Jira gives you ultimate flexibility to reflect the "unique" complexities of your "special" project by creating all these customized columns? Whom are you kidding? Jira is evil in this regard. I wish Jira had only 3 predefined columns and no way to customize it. When you start adding these "special case columns", you are making your life miserable, as well as the life of everyone else around you. All the complexities can and should be mapped to 3 columns model.
Same idea for customizing different stories types. I've seen engineering teams endlessly arguing about if a particular card has to be recorded as a Story, a Task, a Chore, or a Bug. Why? It's all work that needs to be done one way or another, why would it matter how it's recorded in the system? Every unit of work should be a story (which conceptually maps to a yellow sticky -- this is how agile was born).
Another important thing to keep in mind -- avoid having too many stories in flight. Too many stories in any of the given Jira columns means that some of these stories are in waiting state or blocked by external dependencies. No one can work on too many things at the same time. Average agile squad of 5 people should not have more than 20 stories in-flight. Even 20 pushing it too high. If you have more than 20 -- start moving stories back to the backlog.
Keep it simple -- offload all these complexities from your brain -- you need it (the brain) for solving your business and technology challenges, not for remembering and managing all the tool customizations.
To succeed with this approach -- make sure to clearly set expectations to your team. And, in order for your team to commit to the goal -- it has to be simple and easy to understand.
Agile Team Goal
There is only one goal that is truly Agile -- Move stories through the development pipeline as quickly as possible.
The goal you set has to be measurable -- make sure you have the right metrics in place.
Cycle time is much better metric than the traditionally tracked velocity. Velocity is badly abused and is easy to manipulate, as such it offers little value.
You process should revolve about your simple goal. If the process is too complex (has too many columns, too many types of Jira cards, too many cards in any column), the stories will stall -- it will be easier for your team to hide the real issues in the complexities.
But, how do you deal with the delays which your team can't control? Don't you need, for instance, more columns to draw attention to the stalled stories? No! Not really. Every time you can't make progress on a story for what ever reason, the story either stays in current column until it's unblocked, or goes back to the Backlog if it can't be unblocked reasonably fast. Adding "In Waiting" or "On Hold" columns does not solve the issue -- it postpones it or even worse -- hides it.
When you start to accumulate too many stories in any of the columns -- that's clear indicator of an issue. To address it, start moving the stalled story to the backlog, and let your PO help you re-prioritize. If no one can help the engineers to address the dependencies -- it means only one thing -- no one cares, as such -- it's not a priority.
Make sure your entire team (including PO, UI/UX designers, Devs, QA's. Dev ops) signs off on few simple rules which support your Agile Team Goal:
When the story is moved from the Backlog to the WIP column -- it becomes a priority for the entire team to move it through the pipe-line all the way to the end -- to the "Released" column.
The story is not done until it's in the "Released" state.
Never move things from the "Released" column to the Backlog -- create a new BounceBack story in the Backlog. If the original story was not done correctly the first time, it's an entirely new unit of work which needs to be prioritized, and enter the pipe-line just like any other story in the Backlog. This will also allow you to more accurately record the history of BounceBacks. Too many BounceBacks pertaining to a particular story is a problem that needs to be fixed.
Never have more than 20 stories in-flight (have your team figure out what's the right number of the in-flight stories they can handle).
Record intermittent state changes at the story level in Jira. Branching, rebasing, merging, creating and reviewing pull requests, releasing to staging, signing off on testing results etc... -- all this must be recorded in the story log so that anyone can always know exactly what's been done.
Measure Cycle time. If it's starts to go up -- fix it. Don't hesitate to ask for help the higher level authority of your company -- this is their job to help you remove impediments so that you (the engineer) can do your job.
Estimates are costly because they take time and effort away from your development team. Why bother if the estimates, no matter how accurate they are, will always be wrong? If all you care about is to deliver stories as quickly as possible -- do not spend valuable resources on something that has little value. Instead of providing fine-grained Fibonacci numbers or Power of two based estimates, simplify it -- use T-shirt sizing:
Have the engineering team define what these sizes mean. Use relative approach -- any story larger than Large must be split in smaller pieces. Identifying the larger stories so that they can be split in smaller pieces is the only benefit of the estimates.
Branching strategy and CICD
If your goal is to implement true Agile delivery cycle, you'd want to pursue Continuous Delivery model. The only way to build efficient Continuous Delivery is to keep it simple.
Many branching strategies invented to help to deal with complexities of the Product Delivery.
GitFlow is good example of such an attempt. While GitFlow model generally speaking works well and is recognized as the industry standard, it's already complex enough from the start. If you want to adopt this model on your project -- it will make your process more complex than you need. Is this something you want?
I propose to start with the simplest branching model possible.
If done right, you can manage any use-case with the single stable branch model.
Forget about "Main", "Development", "Feature", "Release", "Hotfix" branches. Who in the right mind would be able to understand and remember when to create particular type of branch and how to manage it correctly? All you really need -- "Main" and "Feature" branches.
Here is how it works:
Main branch -- single source of truth, stable, always reflects what's in production.
Feature branch -- any progress on the project is made on the feature branches, either new feature development, or hotfix, or client acceptance testing.
Few simple things your team has to agree upon to make it work:
Always create new Feature branch from the latest "Main"
Feature branch is created for any type of work you need to perform on code:
small story that takes up to few days to implement
larger story that will be ongoing development for couple of weeks
bugs, regardless of how long they take to fix
hotfix that needs to go to prod ASAP.
It becomes developer's responsibility to keep all their Feature branches up to date with the Main branch at all times.
As soon as something is merged to the Main -- all Feature branches have to be rebased off of the latest to include that change. That's another reason you should never have too many stories in-flight.
Continuous rebasing of the Feature branches helps to make sure that the integration testing happens early, and all merge conflicts are resolved on the Feature branch ahead of time, which minimizes merge conflicts mistakes.
If you ever need to resolve merge conflict on the Main branch -- you are doing it wrong.
The testing, the QA sign-off, the User Acceptance testing -- all of that happens on the Feature branch. The Feature branch always contains the latest from the Main as well as the Feature work.
Releasing feature to production becomes simple and reliable, since all the merge conflicts are already solved and all the integration/regression testing already happened on the Feature branch.
Never accumulate non released state on the Main branch. As soon as there is a merge to Main -- release.
Continuous improvement is one of the foundational Agile principles. Unfortunately, it's easy to forget what that means. Most understand "improvements" as adding more things. Sometimes adding an extra step or a missing piece makes sense. Most of the times -- improvements can and should be achieved by removing/simplifying things.
In "The Aviator" movie, Howard Hughes takes a sledge hammer and smashes second row wings off of the airplane to reduce the air drag and to improve the speed characteristics. Agile is your sledge hammer -- use it wisely.
And that's all folks.
To wrap things up, here are few of my favorite Einstein quotes:
Everything should be made as simple as possible, but no simpler.
If you can't explain it simply, you don't understand it well enough.
Hope, in this post I was able to explain simply how to deal with the Product Delivery Debt. If you still have questions, comments or would like to collaborate on this topic -- I would love to hear from you.