Pavel Titenkov / February 05, 2023
6 min read • ––– views
You’re familiar with debt, right? The money owed by one party to another. You get the cash you need now and then pay back later with some extra. The concept of debt is often used in software development, and I find this metaphor beautiful.
The term Technical Debt was introduced by Ward Cunningham to describe the engineering trade-offs, that software developers often make in order to meet timelines and customer expectations. These trade-offs have a tendency to accumulate over time and if you do not care about the technical debt you left behind, you will notice how it would slow you down (like paying interest on a constantly growing loan). Technical debt is often misunderstood and seen merely as a side-effect of the software development process, instead of a critical aspect that needs careful management. In this article, I aim to share my thoughts on this topic and dispel some common misconceptions I’ve encountered in my work experience with various organizations..
Any system must continually evolve or it becomes progressively less satisfactory (Lehman’s Law)
A steady flow of updates and modifications is crucial for a product’s survival. Without updates, a product becomes obsolete. These changes are necessary to ensure the system operates efficiently and evolves over time. However, as the number and complexity of updates grow, maintaining and modifying the system becomes increasingly challenging, leading to increased complexity. The result may be a vicious cycle in which increasing complexity leads to more changes, which in turn exacerbates the complexity of the system.
In my view, software craftsmanship is primarily about managing complexity. If you haven’t already, I highly recommend reading the Out of the Tar Pit paper - it’s one of the best works on 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), lack of predictability, organisational problems, key personnel dependencies, developer burnout, etc.
There is always a correlation between increased complexity and the accumulation of technical debt. Both lead to difficulties with the codebase and have similar symptoms. Both have common roots. Most of the time they are both consequences of making trade-offs.
Software development is a complicated and dynamic process. As a software engineer, you face numerous decision-making opportunities every day. Every choice and trade-off you make can influence the final outcome of the project
I can illustrate what this typically looks like. There is pressure to deliver features quickly. Someone gave promises to the customer, so the feature you work on today was supposed to be delivered yesterday. As a software engineer, you are tasked with not only meeting these deadlines but also ensuring the solution quality (as in, the solution you create is maintainable, scalable, and sustainable). In the process, you may need to make changes to older parts of the code, but doing so requires proper refactoring and testing. Does this scenario sound familiar to 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 in order to meet deadlines. Sometimes, it can be the only right decision, which ensures the company meets its financial goals and keeps growing. But this can come at a cost. As in, technical debt. By taking shortcuts, developers may temporarily meet short-term goals, but they also create long-term issues that will need to be addressed, often at a greater cost, down the road. It’s important to prioritize quality over immediate gains.
Another issue in many organizations is the practice of deferring crucial trade-off decisions to individuals without a good enough software engineering context. To effectively balance both short-term and long-term goals, it’s important for the engineering team to work closely with the business side and control this balance. A comprehensive understanding of both technical and business aspects is crucial in making good decisions that promote the success of the company. In most cases, it is easier to convey the business context rather than the technical one.
With borrowed money, you can do something sooner than you might do otherwise, however, you’ll be paying interest until you pay back everything. Taking 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 feels difficult for a team - be careful with technical debts. Try to encourage a good attitude to quality and build the right habits first. Simple steps like adhering to the Boy Scout Rule of “leaving code cleaner than when you found it” can go a long way. Encourage each team member to make it a habit to ask themselves “Does this make the code (or product/architecture/etc.) simpler?” before submitting a pull request.”
Keeping solutions and code clean requires sustained effort. Just as one cannot expect to get a six-pack of abs in a week in the gym, it’s not possible to clean up technical debt in one iteration (or quarter, whatever). It requires consistency and discipline and it takes time to see results.
In my experience, technical debt often goes unresolved. It’s crucial to prioritize avoiding it and focusing on delivering high-quality work instead of constantly adding to the technical debt.
A mess is not a technical debt. It’s the most common misconception I face when it comes to technical debt. Technical debts are based on difficult and carefully made decisions. They are rational. A mess is never rational. A mess is usually based on the unprofessionalism and laziness of developers.
Technical debt should not be used as a license to make a mess.
There are several good articles describing the difference in detail. Strive to avoid making a mess and don’t let others call the result of neglect and carelessness “technical debt”. Technical debt should never be used as an excuse for repeatedly ignoring quality in software development.
Quite often software engineering organisations are unaware they are taking out debts. The longer technical debt accumulates, the more challenging it will be to address. However, with the right approach and people - nothing is impossible!
Don’t try to fully eliminate technical debt. Rather focus on changing the team’s habits and creating a development culture, where laziness, negligence and indifference are not tolerated. Acknowledge and reward your team members’ efforts in cleaning up the mess. Keep technical debt under control and ensure that it does not become a major burden on the development process.
Avoid debts and good luck!
Subscribe to the newsletter
I'm trying to create helpful content for software developers and engineering managers. I will let you know when I publish new articles and share some exclusive newsletter-only content now and then.
No spam, unsubscribe at any time.