After close to 20 years building software products I’ve finally made peace with technical debt. I’ve arrived at a perspective and approach that I don’t see myself wavering from any time soon.
So what is that perspective? Technical debt is only a debt if you’ve consciously made a choice to defer some technical costs to a later date in order to achieve a shorter-term gain.
- Poor quality code isn’t technical debt, it is poor quality code.
- Legacy code that needs to be replaced at a later date isn’t a debt. Your new code is an investment. (we don’t view an older building with old furnishings as a debt)
- The amount of technical debt you take on is dependent on your situation – your goals, your team, your product.
For example, you might have decided to use a completely unscalable hosting solution in order to release your feature MVP. You may choose to use a certain technology over another because your team is familiar with it, even though you think the other technology would be better.
How did I arrive at this perspective?
When I was starting out as an engineer, like most young engineers, I saw any code smell or design change required as a Very Serious Problem that needed to be dealt with immediately. Any demands on my managers to improve this yielded no results. “Why aren’t they understanding this?” I thought.
It wasn’t until being involved in the development and release of over 60 software products, alongside countless features, that I’ve understood why they weren’t understanding me. It was when I was responsible for ensuring that an expense or investment (which is what every second spent writing code is), needs a return that it finally clicked.
Software products are a business. Every dollar spent, needs more than a dollar returned. It’s very bad business to spend more than will be returned, and trade offs are usually required to hit that magic point of quality and profit.
High performance teams get this and provide both quality work and returns extremely effectively.
You can take issue with this all you want but it is the reality. The sooner you accept it, the sooner you’ll be an outstanding engineer.
Here is an anecdote from a Netflix engineer;
When I joined Netflix I was assigned to add DASH support to the Silverlight web player. I spent weeks working on the new architecture, refactoring the streaming code, etc. One day my manager stopped by my desk and said that “I needed to wrap it up. It was taking too long.” I was still weeks away from being done. I explained to him that I was cleaning up a ton of technical debt and that’s why it was taking so long. He explained to me that they had different values on his team;
1. Most code will be rewritten every 2 to 3 years.
2. For code that doesn’t get rewritten often, preserving battle-tested code trumps paying down technical debt.
This perspective is reinforced by reading the thoughts of gurus like Martin Fowler, reading the comments of peers on HackerNews, and in-person discussions with colleagues.
How do you approach and manage technical debt?
The approach I’ve arrived at for managing technical debt is the following:
- Allocate time each sprint or month to reducing Technical Debt, doing preventative maintenance, refactoring poor quality code. This might be 0% it might be higher. You may decide to go for 0% on a case-by-case basis if you’re under pressure to release.
- Don’t pay off “debt” unless you have to. The market doesn’t give you points for refactoring working code into more beautifully structured working code (usually the refactoring breaks things anyway). You’re just spending money with no return except your intellectual satisfaction. If you want intellectual satisfaction of this form, contribute to open source, take up chess or start a hobby project.
- Engineers must take responsibility for Technical Debt. The engineers have the best visibility of how technical debt effects the product so they need to be the champions and doers when it comes to the removal of technical debt. Engineers need to convince their stakeholders of the benefits of removing specific technical debts (Tip: frame this as faster time-to-market, benefits for customers. E.g. less downtime or errors).
- It’s OK to “pay down” debt that has no future return to make engineers happier but account for it as team morale not benefit-to-product.
- Don’t take on easily avoided Technical Debt. Being under pressure to deliver doesn’t mean it’s ok to deliver poor quality code. Even when under pressure to deliver, taking an extra 5% time on a given scope of work can make it 100% easier to read and maintain three months from now.