Tech debt: everyone has it, and every developer worthy of their title wants to pay it off, but how do you organize this process?
We implement crop rotation
In my previous article, I compared technical debt repayment to the importance of crop rotation in agriculture. If you continue to process a field (codebase) season after season in order to get a large harvest (complete projects, add features, etc.), and do not give this field a season for recovery (payment of technical debt), then it gradually begins to lose its quality and productivity.
This metaphor remains appropriate for software development; in addition, it contains hints of possible strategies that can be used to pay off technical debt.
There is a surprisingly wide range of ways to pay off debt. And this is very useful as it gives us a lot of planning options.
For the purposes of this article, we will assume that you are working in an agile development methodology, but many of the principles, if creatively refined, apply to other methodologies.
Dedicated sprints to pay off technical debt
In complete analogy with crop rotation, we can stop working on features every fourth sprint or so, allocating it only to pay off technical debt.
Pros:
- Developers share a common drive to focus solely on paying technical debt
- Developers can coordinate to pay off larger chunks of technical debt by working in tandem
- Businesses are motivated to study technical debt results that demonstrate the importance of work and the remaining volume.
Minuses:
- Merge conflicts begin to arise as employees make larger volumes of architectural changes.
- With this chaos and instability, it can be difficult to tell if something is broken if there is no good test coverage.
- Just because you are working on technical debt, support incidents never go away. Without staff to help with the escalation of support requests, technical debt is guaranteed to be hampered by support.
Dedicated Capacity for technical debt repayment
In this model, the agile team reserves a certain number of points or a percentage of the total sprint capacity to pay technical debt on an ongoing basis. For example, in each sprint, a team can take 5 storypoins of various debt repayment jobs.
Pros:
- This ensures that paying off technical debt is part of the ongoing culture of the organization.
- Ongoing technical debt work may prevent the need for more work in the future.
Minuses:
- If changes need to be made to the sprint, working on technical debt will be the most likely candidate for removal from the sprint.
- By limiting your work on technical debt to small amounts, you make it harder to eliminate the sometimes large chunks of technical debt.
Dedicating employees to pay off technical debt
This is a hybrid of the last two options. Each sprint selects one developer to work on the technical debt while everyone else continues with their normal work.
Pros:
- , , .
- , ,
:
- ,
- , , capacity
In this model, when developers plan their work, they add to the plan the cleanup of neighboring code and the payment of detectable technical debt that is already in the work area. This is in line with the Boy Scouts principle : always leave the parking lot (codebase) cleaner than it was before you.
In other words, this implies that when you touch the code, it should get better. In the code that is touched most often, you need to pay the highest percentage of the technical debt, so it makes sense to pay off the debt in the areas of the code that you are working on.
A similar concept is found in Malcolm Gladwell's book The Tipping Point.for an example from the New York subway. The City Transportation Authority found that by uncoupling subway cars, cleaning them of graffiti and ensuring that there is no graffiti at all times, you can save on the effect of broken windows , in which people believe that the condition of the cars does not bother anyone and the crime rate can increase. By reducing the number of rabbits and graffiti, the agency could also reduce the number of violent crimes on the subway.
If we transfer the same principle to our codebase, then we need to make it so that when you touch areas of the code, they are cleaned up and the technical debt is paid.
You probably guessed from what you read above that I am a fan of this approach, but let's still consider its pros and cons.
Pros:
- Tech debt pays off in areas that developers naturally touch more often
- You no longer need to "allocate space" to pay technical debt, it's just part of the workflow
- Merge conflicts are minimized because changes are made only in isolated areas.
Minuses:
- There is no special opportunity to make large changes that affect the entire system
- It causes "inflation" of storypoints due to the fact that additional work needs to be done with each ticket. This reduces the amount of work that can be done in each sprint.
Major code revisions
Above, I talked about the strategy of paying off technical debt by gradually replacing parts of the system, as in the thought experiment with Theseus' ship , but what if that is not enough? What if you don't have time to replace all the software piece by piece and need to make more radical changes?
Here are some ideas to help you:
Breaking an application into smaller applications
With this methodology, we split the monolithic application into smaller applications. Often, this approach is complemented by Domain Driven Design and / or microservices, but its main point is that if the application is too large to replace, it can be divided into smaller parts, the replacement of which is realistic, after which each one can be replaced. part one after the other.
You can also implement this scheme using the Strangler Application template by Martin Fowler, in which a new application is created, receiving the same requests as the old one, and making calls to legacy systems until a modern replacement is ready for each of them.
Pros:
:
- ,
capacity
In this model, developers can use slack or technical debt time to work on long-term projects, such as replacing part or all of an application. Once sufficient progress has been made and the work can be started in earnest, these tasks begin to be implemented into a sprint or sprint series for formal implementation and delivery.
Following this pattern, I have been very successful in porting JavaScript applications to TypeScript , including spending time outside of work (not necessarily, but I decided to do so) and waiting for the online regression testing frameworks to come out.
Pros:
- Potentially defective prototypes that are not tied to formal QA / supply cycles can be identified and addressed
- When the work is ready to be included in the sprint, it is already usually a very concentrated work, in which most of the unknown variables are solved.
Minuses:
- It can be difficult to find a significant amount of off-schedule prototyping time unless your organization wants to reduce resource allocation to other projects.
Full transition to the new application
In this model, all work on the old application stops, except for the fixing of critical bugs, and work begins on the application, which will become its complete replacement. This is what people usually mean when they talk about rewriting an application.
Pros:
- Employees can focus on the new system without really considering the existing one.
- The total execution time may be less
Minuses:
- With very short delivery times, the business may feel like they are wasting money on the project.
- Delays in deadlines can interfere with the delivery of the required work
- In fact, this approach turns into an all-or-nothing principle.
- May not fully consider all risks before investing in a new platform project
findings
Consider these options for continually updating applications, as well as more radical options. In my opinion, there is no single best option, you need to look for the one that is most optimal for your team, product and organization. Evaluate these approaches and determine which options work best for you when preparing a “crop rotation” to keep your codebase healthy over the long term.