10 tips for dealing with technical debt
Technical debt is the future cost of developing digital products with a very short time-to-market but with an imperfect codebase. How to balance business goals with sustainable maintenance and keep your technical debt in check.
Article by
Vadim Kravcenko
Like a loan from the bank, you have to pay back technical debt at some point, and the longer you don't, the more expensive it gets. But completing every line of code bug-free in advance and preparing the architecture for every future scenario isn't the solution either. In practice, technical debt is inevitable, because every day you spend longer tinkering with the details of your software, you miss the chance to get immediate feedback from the market. Not only that, but you won't be able to sell your product until much later, and you won't make any money to pay your bills. As you can see, it's a dilemma. So what to do?
The most important thing is to be aware of technical debt and be specific about how much of it a project can tolerate in order to work. Think of it as part of your strategy and be clear about the consequences. If you factor in the resources needed for refactoring in the future from the start, you'll have a much easier time reducing the debt mountain.
The agile software development thing
It's not for nothing that many agencies, including Mindnow, strive for agility, because software is constantly evolving. Product Owners come up with new features, team members contribute their ideas, infrastructure needs to scale, and market requirements change anyway. This is completely normal.
Imagine a web app, with email and password login with a single personalized page. Less than a year later, users might want a mobile app with an Apple login and a built-in loyalty program. Times change. Users and their needs change. That's why the software has to change too!
What is often underestimated is that software with more and more features and customizations becomes more and more complex and difficult to maintain. If this becomes much more difficult than originally anticipated, technical debt actually becomes a problem.
So what to do? Here are my best tips and tricks for dealing with technical debt from my experience as a CTO and product team leader:
1 – A good start
At the latest, if you notice that your technical debt is increasing faster than expected, you should press the stop button and look for the causes. Often it's due to problems in the codebase. The best place to start looking is here:
Warnings and outdated packages
Code without documentation
Code with high cyclomatic complexity (i.e. a high number of linearly independent paths)
Modules with a high degree of change coupling (i.e., modules that require further changes in other modules when changes are made)
2 – Use visualization tools
There are great ways to get an overview, for example CodeScene. The tool is a complete solution for analyzing the codebase. It reveals hidden risks and helps to select the right features for refactoring. Special tip: Take small steps instead of completely scanning the entire project at once. The key to success is regularity throughout the year.
3 – Sensitization of agencies and customers
In addition to all the changes that come with new users and market demands, I also often experience feature requests like "the CEO wants this and it has to be ready by tomorrow". Maybe something like that sounds familiar to you, too. Of course, as an agency, you want to fulfill every customer request. But if the desired feature is developed too hastily, it is difficult to extend the API accordingly. The result: technical debt and higher costs in the long run.
I see it as agencies' job to explain future costs to clients. A short-term gain may hide additional costs in the long run. However, if this becomes clear, it is certainly easier for the CEO to understand that skipping testing, architecture, documentation and quality assurance may not be the best idea after all. In the best case, customers are even grateful to be made aware by their agency when a supposedly great idea might cause many extra hours and additional costs in the future.
4 – Define a good process
Make sure your development process is top-notch. Formulate detailed requirements in addition to an estimate of effort. Keep the whole team in the loop and make sure systems are in place that spell out responsibilities for each person. Define not only who works on what, but how. A well-designed process avoids architectural problems and untestable code. Even if it feels like more work at first - it absolutely pays off.
5 – Old code that works is a good thing
Developers new to the company, when they first look at the codebase, often get the thought "Oh, that's legacy code! That needs to be rewritten, I think I can improve it!" This kind of misinterpretation actually happens more often than not. Yet old code is something quite positive. Why? For one very simple reason: only good code gets old in the first place, while bad code is constantly being reworked. Old code that has remained the same over the years probably does exactly what it is supposed to. If something works, it's not technical debt, but simply a codebase that you should leave as is.
6 – Don't confuse technical debt with normal bugs.
Even the most talented developers are only human and can make mistakes. But that doesn't necessarily translate into technical debt. Such debts occur when a limited solution is intentionally developed instead of carefully coding everything right away. Ordinary technical errors that happened due to a wrong decision or a failed attempt are something else entirely. While it's better to plan for human errors in the project, this has nothing to do with faster time-to-market and belongs in a different drawer.
7 – Make a release checklist
When is a feature really ready? I would say when everything works as it was commissioned and when everything works as it was defined in the release checklist. The latter is a bit more thorough and also contains important points like:
Does each feature have at least X unit tests?
Has the code been reviewed by at least X developers?
Is each feature well documented?
The features of a software or digital product must be tiptop not only from a business perspective, but also from that of development.
8 – Proper documentation is the be-all and end-all
Documentation is extremely important, even if it is often difficult to motivate developers to do it. Working on the product itself is of course more exciting than documenting it, and some developers lose the fire to continue working on a feature after it is finished. For this reason, a rigorous process for proper documentation is advisable.
In addition to documentation aud, ensure that the team's bus factor is greater than 1. Just imagine if a developer is gone from one day to the next - and thus all undocumented knowledge. Sudden unforeseen events like accepting a job offer, moving to another city, or - hopefully not - getting hit by a bus can happen. With good documentation, such events are far less fatal to the success of the project.
9 – Plan resources for solving problems
Product Owners want to keep the team's velocity as high as possible during the sprint, and that's understandable. Nevertheless, they also need to allow enough time for legacy issues. New features alone don't make a release - there are still a number of improvements to the codebase that are just as important.
Resolving issues like refactoring, testing and documentation requires resources and these want to be well planned. I recommend creating a separate tag for this in your project management tool (my favorite is Linear.app). This way, problems that still need to be solved are clearly visible to everyone and will be remembered. If the focus of the sprints is on speed alone, technical debt increases and the whole project slows down.
10 – Track metrics over time
I don't usually specify in detail which metrics are tracked in terms of code and when. Developers tend to then tweak those very metrics and stiff themselves. Instead, I make sure the team knows that over time the following is being looked at:
How many new bugs are related to the new features versus the old features?
Who is responsible for most of the code?
What about complexity and code coupling? (See tip 1)
Is the knowledge properly distributed in the team? (Documentation & bus factor, see tip 8)
Less than perfect code is fine as long as you know where you stand
Technical debt is not bad in all respects. Imagine you meticulously follow all the tips and write the perfect code without any error. You may work on it for years, and in the meantime, your competition has launched an even better solution, even though their code was much worse than yours when you entered the market.
Getting immediate feedback from the market is not only valuable in itself, but also well worth the technical debt. Since conditions change quickly, it's wise to release an alpha version as early as possible, as long as you remember that this step comes with fixing problems in the future. However, if you plan accordingly and follow my ten tips, you'll definitely keep your technical debt under control.
Mindnow AG
Weite Gasse 13
5400 Baden