Technical Debt

Pavel Titenkov

Pavel Titenkov / February 05, 2023

5 min read––– views

cover

We're all familiar with debt, right? It's like borrowing money—you get what you need now and pay a bit extra later. This concept isn't just for finances; it's a neat way to understand what happens in software development.

Ward Cunningham came up with the term Technical Debt to talk about the choices software developers make to meet deadlines and keep customers happy. These choices add up over time, just like paying interest on a growing loan. If you don't deal with this technical debt, it can slow you down.

But here's the thing: lots of folks see technical debt as just a side effect of making software, not something that needs careful handling. In this article, I want to share my thoughts and clear up some common misunderstandings.

Increasing complexity

Any system must continually evolve or it becomes progressively less satisfactory (Lehman’s Law)

A product's survival hinges on a constant flow of updates and modifications. Without them, a product quickly becomes outdated. While these changes are vital for efficient operation and evolution, the growing number and complexity of updates create a challenge. This challenge often spirals into increased complexity, creating a loop where complexity begets more changes, further complicating the system.

In my perspective, software maintenance is primarily about handling complexity. If you haven’t already, I highly recommend reading the Out of the Tar Pit paper - it’s one of the best papers about software development I’ve come across. Maintaining simplicity in a growing system can be challenging, but it’s important to keep complexity under control and minimize accidental complexity whenever possible. Uncontrolled complexity results in slowness (time to market), unpredictability, organisational challenges, key personnel dependencies, developer burnout, etc.

There is always a correlation between increased complexity and the accumulation of technical debt. They share common roots and are frequently consequences of necessary trade-offs.

Trade-off

Software development is a complex and dynamic process. As a software engineer, you encounter multiple decision points every day. Each choice and trade-off you make has the potential to influence the future of the product.

I can paint a familiar picture of it. There is pressure to deliver features. Commitments have been made to the customer, and the feature you're currently working on was expected in production yesterday. As a software engineer, your challenge is not just to meet these urgent deadlines but also to guarantee the quality of the solution—ensuring it's maintainable, scalable, and sustainable.

In the midst of this, you might find yourself needing to tweak older code. Yet, making these changes requires careful refactoring and testing, but you have no time left for that. Does this situation resonate with you? It’s tricky to balance.

Strike the right balance between short-term and long-term goals. The balance between deadlines and quality.

It’s all too easy to prioritize short-term goals and take shortcuts to meet deadlines. Sometimes, this might be the only viable decision, which ensures the company meets its financial goals and keeps growing. But this approach comes at a cost - as in, technical debt. While shortcuts may help to meet immediate objectives, they often result in long-term issues that will eventually require attention, often at a higher cost.

Another challenge in many organizations is the habit of delegating critical trade-off decisions to individuals without a sufficient software engineering context. A good understanding of both technical and business aspects is crucial in making decisions that contribute to the company's success. In most cases, it is easier to convey the business context rather than the technical one.

Discipline

With borrowed money, you can do something sooner than you might do otherwise, however, you’ll be paying interest until everything is settled. Handling a debt demands discipline. You have to efficiently control the expenses and most likely optimize some of them. It works the same way in software development.

If discipline seems challenging for a team - be careful with technical debts. Try to form the right habits first. Simple things like embracing the Boy Scout Rule, "leave code cleaner than when you found it," can yield significant benefits. Encourage team members to routinely ask, “Does it make the code (or product/architecture/etc.) simpler?” before submitting a pull request.

Maintaining solutions and code clean requires continuous effort. Much like sculpting a six-pack in the gym doesn't happen in a week, clearing technical debt isn't a one-shot endeavour. It demands consistency and discipline and it takes time to see results.

In my experience, technical debt often stays unresolved. It's pivotal to prioritize prevention over cure.

Mess

It's important to clarify a common misconception: a mess is not equivalent to technical debt. Technical debt is based on carefully made decisions. They are rational. Conversely, a mess is never rational; it typically stems from unprofessionalism and laziness.

Technical debt should not be used as a license to make a mess.

Try to proactively prevent the mess and avoid categorizing the outcome of neglect and carelessness as "technical debt." Technical debt should never serve as an excuse for that.

Epilogue

In many cases, software engineering organizations may be unaware that they are accumulating debts. The longer technical debt persists, the more challenging it becomes to address.

The key is not to aim for the complete elimination of technical debt. Rather focus on changing the team’s habits and creating a development culture, where laziness, negligence and indifference are not tolerated. Recognize and reward your team members' efforts in cleaning up the mess. Keep technical debt under control to prevent it from becoming a significant burden on the development process.

Avoid unnecessary debts, and best of luck!

Credits