[this is a short, not fully developed blog post – consider it “in development”] I’m getting into the habit of learning in the open, and I think part of letting go of the idea that I need to do everything right is allowing my incomplete ideas to be in the wild.
I think a lot about technical debt. What it means, what makes it happen, how we get rid of it. Mostly, I think a lot about the fact that no matter what you do, you always go and create it again.
Debt seems to be a poor analogy for something that occurs no matter what. It’s essentially impossible to not create technical debt, because time passes, and time itself creates it. Software becomes deprecated, packages stop being maintained, a new security patch is released, and you need to change your code.
Technical debt is a great analogy for the fact that you can incur technical debt to be able to get to market at some point. You take on some debt, you plan to repay it. It starts to generate interest. You pay a heavy amount in interest, and if you don’t, it snowballs, until it consumes all available resources. In that sense, technical debt is the perfect analogy. It’s easy enough to explain it to finance, who understand risk management and how to use debt responsibly; they know how to wield debt in ways that benefit the organization, much like engineers often use some tech debt to get ahead. It’s harder to explain to people who have never taken on debt on purpose, who don’t see it as a tool but only a burden; debt, both financial and technical, are tools to be deployed.
But isn’t debt always bad?
Not really. Some technical debt is almost inevitable. What’s not okay is to let it create a ball of debt that never gets repaid. What was a good decision yesterday can quickly become a bad one if nobody takes this resource consuming debt into consideration.
It’s a bad analogy if you think about the fact that if someone offered to take all your financial debt away, swipe it off entirely, you probably would jump at it.
If I offered a magic wand that takes your technical debt away, and you said yes, you would be throwing away a lot of money that you can never get back, rather than finding yourself with a lot more money to spend.
Your technical debt is where your product hides valuable lessons, and to take it away without rebuilding that knowledge is foolish; it’s why rewrites can be dangerous if not done with care and with a focus on enabling progress rather than eliminating all problems.
The fact that a lot of the important things in your product are hidden in layers of technical debt may be the reason that it’s hard to get rid of it; it contains important learnings, important rules of the business, things that you need to understand to be able to rebuild without that flavor of tech debt.
More than once, I’ve seen myself or others attempt to remove important business considerations when we rush to “clean things up” that don’t make sense. A gnarly bug-fix that wasn’t well documented. An edge case fix that took weeks to identify and solve at the time, with code that looks like crap but serves a percentage of your users well. As you refactor, the risk is that you may introduce different tech debt into your code. That’s not necessarily a bad thing. Some tech debt is dangerous, and some tech debt won’t be considered debt for months or years. But you know it’s going to appear. You may not see it now, or tomorrow, but 6 months from now, some new developer will surely point it out, and you’ll be dreaming to rewrite it again.
When I talk about technical debt being a feature, I know many engineers scoff at the concept.
If only management let us do it right the first time.
I’ve seen engineers spend weeks arguing for the correct interfaces, the perfect APIs, the amazing search system they would implement, if only they had the time. I’ve seen managers like myself give them that time. I’ve also found myself arguing fervently that baring a rewrite nothing could save us… and I’ve been wrong on both sides.
With all the time in the world you plan, you procrastinate, you argue with your peers and reach decisions that seem great, perfect even at the outset… solutions that 6, 12 months down the line are not quite good enough.
I advocate for a continuous improvement approach because it’s the only thing I’ve seen that works. Even then, I’ve never seen a team take it to the point where tech debt is swiftly addressed without guilt. I work to get my teams there.
When I think about the future of a tool, maybe 12 months from now, I think I want us to go “ah yea, this bit of tech debt is there because ….” and have a perfectly sane explanation for it. Not “we were in a rush” but “we needed to do X, this was the solution that made sense due to time constraints”. Even better, I want teams to be able to admit: “This was the best solution we could find at the time, but now we know more.”
I don’t want teams to ashamed of tech debt, I want teams owning it, being able to articulate why it exists, being able to articulate how they will address it, and solving it.
I want teams to proudly state that they refactored an old piece of code that caused trouble without the tingle of guilt that the code was there to begin with. I want product managers to ask what the impact of the debt is, and to make decisions as partners, with engineering, on how and when to address it.
I want teams to operate with safety and be rewarded for it.