Start With The End In Mind

We have completed another lap around the sun, and that’s often a time to think about our plans for the new year. In my previous post, I talked about New Year’s Resolutions and thinking in smaller steps rather than a goal that might take 12 months to complete. But if you only think in small steps and focus on where you want to be in a few days or weeks, then it’s often hard to know if you’re going in the right direction – there can be such a big gap between where you are and where you want to be.

If you were planning on travelling from Toronto to Montreal then you need to plan further ahead than just “which street do I take now?” You might think that was a bad example as the 401 covers the vast majority of the distance, but that assumes you’re optimising for time and that your method of travel is by road, i.e. you have already ruled out many alternatives. Take a step back and consider your goals: if minimising travel time is the primary aim, then flying is significantly faster. If you want the freedom to move around and have a meal without it impacting your travel time, then the train could be your best option.

But let’s go back to driving between the two cities, and assume we have picked the route we would like to take. We set off but before long we discover there’s a problem ahead: an accident is causing a long delay. If we had only been inspecting our progress over small steps, then we might not see the impact of the accident until we’re sitting in the traffic jam and it’s too late to do anything else. We would see a similar outcome if we set the route and followed it regardless of what we discovered along the way. One of the reasons we chose to drive is to have flexibility – we can’t easily change our route if we chose to fly or take the train.

Choosing flexibility (aka agility) may not be the cheapest, fastest or most comfortable path, but it gives us options when new information (whether that’s delays or shortcuts) is available … so we should ensure that we take advantage of that discovery, otherwise we probably shouldn’t have picked this approach!

The plans we create should provide clarity on where we want to be in the future (and why!) but we also should revise them when we see a better alternative. Sometimes it’s a detour that still gets us to our destination but in a better (faster / cheaper / safer) way, but sometimes the discovery is that our goal needs to change – maybe the reason we were heading to Montreal can also be achieved in Ottawa, saving about an hour of driving. If we don’t respond to that new information, then why didn’t we just get on the train, put our feet up, and just enjoy being passengers?

Incidentally, this is why we call some plans “roadmaps” – their purpose is to show potential alternative routes and to allow for changing course while still heading towards the destination. If our plan has only one path from A to B, then it’s not a roadmap. If the plan says “build X” rather than “solve problem Y”, then it’s not a roadmap.

I’m not saying you always have to drive (i.e. use an agile approach) – there are times when the train makes sense, for example when I travel to Montreal for a concert I know the destination isn’t going to change and I would rather get there with minimal stress. In the same way, if we know exactly what we need to build and don’t expect any changes along the way, then we could create a plan, write detailed specifications, and do all the design upfront … but, in our industry, how often can we go from A to B with no learning, no discoveries, no need to adapt?

So: start with the end in mind (understand where you want to go and why); consider what your constraints are (e.g. time) and how you expect to react to new information (do you want to accommodate discoveries or follow the plan); then choose your vehicle and route accordingly.

*Yes, I know the second habit that Stephen Covey describes in “The 7 Habits of Highly Effective People” is “Begin…” but he has a registered trademark for that phrase so I’m avoiding it, and anyway I’m not using the phrase in the way he does.

New Year’s Resolutions

I’m sure most people will be happy to see the end of 2021 but also trying not to build up too much expectation for 2022. There won’t be a sudden end to COVID – it’s going to take a continued effort from everyone. It won’t go away just because we’re all tired of dealing with it. Stay strong; hang in there; support each other; and keep safe, please.

The New Year is a time when many people set Resolutions – things they want to improve, e.g. eating better, getting more exercise. It’s a handy reminder to review how happy we are with various things, but is doing it once a year really enough? It often leads to huge goals because it’s going to be so long until the new review… and, of course, huge goals aren’t usually achievable. That’s why most resolutions are abandoned within a few weeks. It probably helps to have a vision of how you would like things to be in a few months (even a year), but set smaller goals – what are the steps that you think will take you towards that vision?

Hopefully that sounds familiar: regular retrospection, identifying where you want to improve, deciding on small steps to go in that direction; take a step, then go back to retrospection, rinse and repeat.

Engineers and product owners should be well practised in this – retrospectives to look at how we work, and experiments to probe what to build. So how do we convince HR that annual appraisals should be replaced with frequent feedback, and Finance that regular (e.g. monthly) planning trumps attempting to predict six or even twelve months ahead? That’s a challenge I’d like to add to my backlog for next year. Suggestions are welcome!

p.s.
2014: Didn’t jog
2015: Didn’t jog
2016: Didn’t jog
2017: Didn’t jog
2018: Didn’t jog
2019: Didn’t jog
2020: Didn’t jog
2021: Still haven’t jogged
This is a running joke! 🙂

Is Technical Debt Really A Technical Problem?

I often hear the term “tech debt” kicked around but I don’t think it’s well understood.

What is tech debt?
Ward Cunningham created the metaphor to help explain the process of delivering early which leads to the need to go back and “finish” the product. In general, tech debt comes from releasing a product before it is completely done – it’s the gap between what’s done and what needs to be done. That gap should be visible and understood by the dev team and the Product Owner. In fact, the team & PO should agree that there is tech debt before deciding to release; some gaps will be acceptable and some won’t.

What tech debt isn’t
Tech debt isn’t an excuse to write bad code. It may be incomplete because there are parts of the puzzle that are lower priority, e.g. it’s more important to get feedback on the high priority parts first. It may be that parts of the Definition of Done aren’t finished because you’re going to sit with some early-release users to observe them using it so documentation can wait, for example. But poorly written code is just that: bad code, not tech debt.

Accruing interest
One of the reasons that debt is a good metaphor is the concept of interest – the longer you have debt, the more interest you accrue and the longer it takes to pay off. With software development, the longer you leave a product “in debt” the harder it is to build on top of it.

If, for example, there are no automated tests then changes to that piece of code become riskier because you can’t easily check for unintentional consequences (aka bugs). If you now decide to write automated tests for this subsequent change, then it will take longer (cost more) because you’re starting from scratch rather than adding to existing tests.

Good and bad debt
The debt metaphor continues to work when thinking about when to incur it: there are times when it can make sense to incur debt, e.g. buying a house. An important part of intentionally incurring debt is having a plan for paying off the debt.

Deliberating incurring tech debt is often driven by deadlines, or at least the pressing need to “ship now and deal with the consequences later”. This tends to come from (or, at least, through) the PO so the cost should be obvious. The team should ensure the PO knows what is outstanding and therefore an informed decision, weighing up costs and benefits, can be made. The absence of that shared knowledge and conscious decision-making leads to surprises and mistrust; remember that the Definition of Done is an agreement between the team and PO – it’s a common understanding of what “done” means, so it’s important to be clear when a release is falling short of that bar.

Have a plan
An important, and often overlooked, part of responsibly incurring debt is having a plan to resolve it. It’s all too common for tech debt to be forgotten or ignored, but pretending it doesn’t exist won’t make it go away. If it’s important to release something now, before it’s finished, then make sure the tech debt items are identified and added to the backlog … but then also agree when they will be addressed.

Of course plans can change, but start with a target and ideally that’s as soon as possible, while the context is still fresh in everyone’s minds. The plan could also be that some items will not be done; my preference would be to have those items in the backlog and then mark them as “Won’t Do” (or whatever the equivalent is for your situation) so there’s a reminder of that decision. (This isn’t for any “blame” – it’s so I don’t forget and later end up wondering why things aren’t done.)

Review your tech debt
I don’t mean review the backlog items representing your tech debt; I mean think about the cause(s) of your debt. Include tech debt in retrospectives or continuous improvement discussions: what led to incurring the debt and was it avoidable. For example, could the scope have been reduced so that the team could have fully completed something smaller rather than 90% finishing it all?

As part of reviewing what led to the tech debt, it’s also useful to identify any patterns in which items are incomplete, i.e. are the same corners being cut on a regular basis? If so, should we just remove them from the DoD and then add what’s needed for specific features.

Is tech debt a technical problem?
If you’re wondering “Who ‘owns’ tech debt?” then I believe it is the responsibility of both the dev team and PO – there should be a shared need to minimise tech debt, both accruing new debt and paying off existing debt. The are many reasons why, amongst them: the health of the product, the wellbeing of the team, and the speed of future development.

I’ve seen some teams have a formal 80:20 split of time in a sprint, trying to balance “product work” and “technical work” (I’m not a fan of this approach but I’ll save that for another post) so they might wonder whose time does tackling tech debt fall into? Well, if there was no tech debt that would mean the product work was completed as per the DoD, and therefore that was all done in product time. So if there is tech debt, that means some of the product work was not completed, and therefore when tackling the tech debt it should be seen as product work, the same as it would have been in the first instance. Personally, I would prefer to call it product debt because that’s what it is, a deficiency in the product, but the tech debt term is ubiquitous … and I’d rather put effort into reducing it rather than renaming it.

Conclusion
Incurring technical debt is not necessarily a bad thing – there are times when making an informed decision to take on tech debt is the right decision … but there needs to be a plan to pay off that debt. Ignoring tech debt won’t make it disappear and eventually you’ll have to declare bankruptcy, i.e. the software has so much debt associated with it that the only way forward is to wipe it out and start again. Few organisations can afford to do that, so Product Owners need to prioritise tackling tech debt as well feature development.


Resources:

Take Courage

Courage is the willingness to confront fear; one Scrum value says “The Scrum Team members have the courage to do the right thing, to work on tough problems”. It may not be “running into a burning building” courage, it can still be quite daunting to speak up when you feel yours is the lone voice or when stepping into unfamiliar territory.

For the upcoming hackathon, my fellow coaches and I have decided we’re going to spend a few days trying to better understand the developers’ experience by using some of the same tools and techniques. Why does this take courage? Well, some of us haven’t written code professionally in many years (~20 years in my case) and some of us have never been a developer, so we all have a lot to learn. Fortunately, as a strong team, we know we can rely on each other for support as we learn but it won’t all be “the blind leading the blind” – we have found ourselves a coach 🙂

We have the benefit of it being greenfield development (starting from a blank page rather than on top of legacy code) and the freedom of being our own product owner. It means we can focus on the things we want to experience rather than what we need to build; if we discover our current “product” (a slack bot to support team appreciation) doesn’t give us the learning opportunities that we want, we can chop and change it.

I expect it will be interesting to see many software engineering principles being applied in new ways, for example in my day change control was managed via sccs or vcs; these days it’s git. The rationale is the same, the operations are the same, but the commands have changed … and why did they decide to use push and pull counter-intuitively? 🙂

Just like the teams we coach, I’m sure there are things I’ll need to unlearn before I can learn the new approach.