Each developer is familiar with the situation when the implementation of a new opportunity in the system takes a lot of time, but the release is close, and the team leader or project manager is asked for the fifth time this day: “Well, when will it be ready?”. And then there is a difficult choice - to do everything right and not meet the deadline for release or implement the minimum working, but not perfect in terms of technical solutions, functionality. It is obvious that in most cases the second option will be chosen, since the release and provision of the result to customers here and now is more important than the purity of the code and system architecture. But it takes several months, and now the old not perfect technical solution interferes with the implementation of another functionality. And further such decisions will accumulate in a huge room. Dealing with this problem, it is very important to draw the right conclusions and choose the right solution. From this decision will depend on the fate of the entire project. In this article we will try to deal with the nature of technical debt and advise ways to eliminate it.
Nature of technical duty
The concept of technical duty was first introduced by Ward Cunningham (
Ward Cunningham ), a
wiki technology developer and one of the creators of
extreme programming . In 1992, in his
article, he formulated this concept as a metaphor for financial debt: just as with a financial loan, developers can get additional funds here and now through the use of fast and not optimal technical solutions, but will inevitably pay for them during further development, regardless of how this debt is paid - by gradual interest payments or in one payment.
But if the problem of technical debt was described 25 years ago and can be found on almost any project, why is there no project management technique that would avoid the very appearance of technical debt? The answer lies in the very concept of the project. One of the key differences of the project from other activities is the uniqueness of the final product. Where there is uniqueness, there is unpredictability, and it is this that causes changes in the design and makes it difficult for the initial design of the system.
Of course, you can try to build an architecture, envisioning possible changes, but here the team will encounter such a concept as “
Miller’s wallet ”: the rule whereby no more than nine “coins” can be “put” in a person’s short-term memory. And if the number of elements exceeds this value, then the brain tries to group the information so that their number is from five to nine.
You can try to divide the components into smaller ones to fit into this “wallet”, but this will not reduce the complexity, and the number of abstractions with this approach will grow at a catastrophic speed. And as you know, any problem can be solved by introducing an additional level of abstraction, except for the problem of too many levels of abstraction.
')
Other teams prefer to completely abandon the initial design, trying as much as possible to use universal tools in the course of development. On the one hand, it is simpler than trying to predict changes, and in the first stages the system will be quite flexible to changes. But over time, the complexity of the system, according to the
second rule of Lehmann , will inevitably grow, it will become less flexible, and changes may occur that run counter to the current architecture. In this case, developers will also spend more time solving architectural problems.
Anyway, the inevitability of changes on the project provokes the emergence of technical debt.
How to determine that the project has a technical debt problem
The most important indicator that the project has a problem with technical debt is, of course, the code itself. First of all, it should be said about the features of writing code. The fact is that writing and reading code are two completely different processes. When a developer writes code, he focuses only on the context of the task. But changing a separate section of code affects the overall picture of what is happening. In turn, before changing the written code, you need to have an idea not only about a specific section, but also about the whole picture. But when reading, the boundaries of contexts within which the code was written are erased in a general way. This difference between reading and writing code generates additional complexity that directly affects its quality.
What you should pay attention to:
- Parts of code that are often subject to change. Most likely, these areas require serious improvement.
- A large number of FIXME and TODO marks and a small number of comments in the code should alert. Modern IDEs have built-in support for working with such tags, so this is one of the fastest and most reliable ways to recognize weak points in the system.
- Lack of tests. Without them, developers are not sure that their changes will not disrupt the operation of the system. The team refers to the code that is not covered with tests like a house of cards, trying to avoid unnecessary and sometimes necessary changes.
- Lack of documentation. The situation is similar to the previous paragraph. The absence of regulated information forces the developer to think out the picture of what is happening, and there is a chance that he will have a wrong idea about the system. The situation is aggravated by the fact that in the overwhelming majority of cases, developers of different levels of training and competence are working on the project. And the difference in the understanding of the code complicates the process of reading and writing code even more.
- Outdated technology and development tools. Any library or module is updated, and to maintain older versions over time becomes more and more difficult.
- Lack of development standards. Each developer does what and how he wants.
Techniques for eliminating technical debt
- As with the treatment of any disease, the very first step to recovery is the recognition of oneself being sick. Indeed, in the first place, every project participant, from the customer to the developer, must recognize the problem of increasing technical debt. Not so long ago, I became a team leader on a major project that we inherited, and the work on technical debt was never carried out on it. Delving into a huge number of tasks, I constantly ran into tasks to eliminate technical debt, which were created by different people at different times, but were never implemented. This suggests that attempts to cope alone with technical debt comparable to the battle with windmills. It is very important that project participants are aware of this problem, because its solutions require only a systematic approach.
- Use flexible development methodologies ( Agile ). The main essence of the techniques is to divide the development into small, isolated iterations ranging in length from one to four weeks. Thus, the restriction of the “Miller's wallet” costs, because now in each iteration you need to work only with a limited flow of information, in which it is easier to manage complexity, and accordingly, technical debt.
- Enter the general and understandable to all regulations on working with technical debt. Create a backlog that will contain tasks for its payment. And when adding a new functionality or when planning the next iteration, take time to complete these tasks. You can try to allocate time only to perform these tasks, but then the development of a new functional will hang, and most likely you will encounter a misunderstanding on the part of the business. In our project, we decided to allocate 20% -30% of the time from the next iteration to pay off technical debt.
- Create metrics for which it will be convenient to monitor the implementation of technical debt. Such metrics are individual for each project. For example, for our project, we identified such metrics as the percentage of test coverage and documentation, code compliance with the accepted Style Guides, and the complexity of deploying the system on the developer’s local environment. Some of the metrics are collected automatically, some only subjectively by each developer. It is important that these metrics are accessible to everyone; every participant has seen progress and agrees with it.
Conclusion
The problem of technical debt is highly relevant at the moment, and for each project an individual approach to the problem of its elimination is required.
Do not be afraid of payments, because if you adopt the right strategy, then technical debt will become the force that will force your project to develop. It is work with technical debt that shows the level of maturity of both the project itself and the team that is working on it.