Undefining “technical debt”
For me, technical debt is defined pretty loosely as stuff you don’t like in the code and need to change to keep up velocity. However, I’ve seen lots of articles lately discussing a precise definition of “technical debt.” I would sum them up as:
- Technical debt is incurred intentionally. Sloppy code or bad architecture is not debt.
- It is a business decision to incur technical debt.
- It is a business decision to pay down technical debt.
I hate this characterization of technical debt. I hate it because it’s damaging. It assumes a conversation like this happens:
Manager: “How long to do this feature?”
Programmer: “We can do that feature in 4 weeks properly, or 2 weeks if we take shortcuts that will hurt our velocity in the future.”
Manager: “OK, take a shortcut and get it down ASAP.”
… 2 weeks later …
Manager: “How long to do this feature?”
Programmer: “We must spend 2 weeks paying down our technical debt, then another 2 weeks to do the feature.”
Manager: “That sounds fine.”
Every muscle in my body twinges when I think about this. Quality is not something you can put off to later. The idea that a team would do a sloppy job but have the rigor to repay it later is unbelievable. The closest I’ve seen is rewriting a system after years of shortcuts, which often does not end well. This mentality goes along with “how many bugs you have should be a business decision”. This isn’t OK. Do not write something you do not plan on living with. Do not place the responsibility of doing a good job on the business. I find it sad that a programmer would think such behavior acceptable. This is your life. This is your code. Take some responsibility. Take pride in your work.
Or don’t, and sling garbage while getting paid a pretty penny. Just don’t pretend you’re respecting your craft.
(I just want to take a moment to give credit to the team at Cozy. We recently had a couple weeks of crunch. The team delivered fully tested code the entire time).
The tech debt is exactly about “Quality is something you can put off to later”. Whenever the equation is right:
[shortcut]+[value for shipping sooner]+[cleanup and proper deployment effort] > [proper deployment effort]+[any drawbacks of shipping later]
…you should take that shortcut.
If you can hardcode configuration for first deployments, do you really need that config file support?
If you have a weird production issue, do you have time to investigate, or a silly hack (periodic server restart, limit number of concurrent users, increase timeouts) will do for the time being?
Do you really want to create a full-featured framework before putting that requested feature on top of it, or can you somehow hack the feature up from semi-made pieces, it will not be reusable for other similar features, but at least you can start getting some feedback on this, and only THEN shape some sort of a proper framework?
Yes, most often you would want to choose a proper path straight away, but you don’t always have a luxury, or even the need for that.
Tech debt is not about “sloppy”, or “bug”, “poor quality”. Tech debt is about “shortcut”, “workaround”, “temporary fix”, “hack”. It is actually useful to know when you can use one of those.
Viktoras, it’s not a matter of “crap or full-featured framework.” It’s a matter of “can I live with this for the foreseeable future.” This is significantly different from “I will do something in a sloppy/wrong way and plan on changing it in the future.” The decision making about technical things is in the hands of the programmer. For example (I’ll make this a full blog post in the future), we needed to put up a warning banner in our site, for example if our email provider is having an outage (see my last blog post). There are many ways to do this. We decided on a static file we serve from our marketing site. This isn’t a gold-plated solution (something controllable by our administrative app, or another 3rd party service). Nor is it a hack job (editing source files and doing a deploy). It’s something I would have no trouble living with until it becomes a priority to expand capabilities. And it was done in a deliberate, responsible way. I don’t call that technical debt, I call it a good solution.
Another thing I have noticed about technical debt is, if your don’t clear it you are going to end up with a wallet full or credit cards and it will drive you further and further into debt. In most cases I find technical debt arising from untested code and poor unit testing. You end up with tasks that you think will take you so long to complete and then end up blowing out because of edge cases and bugs, giving you less time to implement the current solution properly. So the cycle continues, you have to write custom code to get around the bugs at the same time not break it for the things that rely on those bugs to be the way they are…. more code to trudge through. Well tested, structured and documented code although fundamentally flawed in its design will most always be easier to correct and/or re-write.
I completely agree, pay the price upfront for complete solutions. Now that being said sometimes you don’t get the time you need to do it right, you are hamstrung by the fact that if you don’t get the system going enough to get you over the line you could end up not having a job to complete. This is a tough balance, but as soon as you have some stability and reserve double down on fixing it.
well, the tech debt would be something like.. Imagine your car gets a strange rattle. You go to your mechanic and he says, “it’s your exhaust pipe holder, you need to replace it, but it’s gonna take a while to order a part and ship it, so just park your car here and come back in a week”. You say “no, I have this weekend trip planned, is there something we can do now?”. They say “yeah, we’ll put a strap on it meanwhile, just drive a little more careful and it should hold, but make sure to come back and do a proper fix”. Mechanic charges you now, and then a bit later.
That’s an example of “business” driven decision about the quality of product. In the end, it’s your property, if you want it working it NOW taking responsibility of shortcommings, it’s ok.
> That’s an example of “business” driven decision about the quality of product.
No, that’s an analogy.
And the reason it doesn’t hold up is that the roles you have in your analogy are totally mixed up. Good fodder for another post though maybe you understand the mixup now that it’s been pointed out?
Not understanding how it’s is mixed up, to me it’s:
Me, car owner – PO/Client
Car – product
Mechanic – dev team.
I believe we’re getting hung up on the intangibles. A single example won’t demonstrate what I believe Rob is observing (human patterns that influenced by repetition).
If developers continue to face pressure, and are forced to take shortcuts because a business decision was made, over time that behavior becomes the normal. It’s hard for someone to maintain quality when they’re constantly beat into taking shortcuts, when they find time to focus on quality, their mindset has already shifted and it becomes very difficult to adjust, if not impossible to do it without influence.
Unless someone is enabling developers to focus on quality while taking shortcuts (I’ve rarely observed proper enabling), then the developer will conform to the direction the pressure forces.
If you already have a good culture, decent process, good practices… then being faced with the analogy above, sure, it should be a no brainer. Take the shortcut, come back and get it fixed, it’s rarely that simple at scale (and requires that the customer wants to come back and get it fixed).
[…] my previous post about technical debt, I explained how modern definitions of technical debt are harmful. Now I turn my attention to […]
[…] Makauskas made the following metaphor in a comment on my last post. This is a pretty perfect stand-in for metaphors I’ve read in other articles that harmfully […]