Dealing with technical debt while delivering— a 3 step technique with example
A 6 minutes story written on Oct 2017 by Adrian B.G.
As in the case of household techniques, you shouldn’t wait for the spring (or a sprint) to clean your codebase of the past horrors. By cleaning your code before doing a task you will make peace with the Ghost of the Past.
I started to use this technique while working on a legacy project, it evolved over the years in a natural way being driven by the need to improve the codebase while delivery new features.
We (almost) never had the time to “refactor the entire module”, we barely had time to “patch it up” and postpone the problem. We had classes suffering from all antipatterns at once, a plan to make the code more maintainable would stop the production for at least a few sprints === ⛔no go.
The only solution left was to slowly fix the problems between the tasks. Here are a few wins over a period of 1 year:
- split 4000LOC God classes
- extracted functionalities to other sub-projects as services
- many small improvements
It’s not much but we were under constant fire, doing daily releases and many A/B tests. Every small improvement will cut down the duration of the next task involving the same code.
Continuous refactoring 👩🏽🏭
Improving your project health on a daily basis is a good practice, most likely you do not need (or want) to rewrite your entire app, you just need to keep improving it.
By doing this the project will “heal itself”, the parts of the product that works, and never need change will remain written, the parts that change often will benefit from constant improvements.
Another thing to realize about these refactorings is that they take time. All the refactorings in Chapters 6 through 11 can be accomplished in a few minutes or an hour at most. We have worked at some of the big refactorings for months or years on running systems. When you have a system and it’s in production and you need to add functionality, you’ll have a hard time persuading managers that they should stop progress for a couple of months while you tidy up. Instead, you have to make like Hansel and Gretel and nibble around the edges, a little today, a little more tomorrow. (Refactoring— by Kent Beck and Martin Fowler)> Tidy a little a day and you’ll be tidying forever. Marie Kondo — who created the KonMari Method for simplifying, organizing, and storing.
You would be surprised to find out how many things Refactoring and Cleaning have in common, including the 3 steps I adopted and explained in this article.
First you have to discard as many things as you can to make room, then using a bunch of small techniques you tide the place and then you can buy new things, if needed.
Leave your code better than you found it! 🚀
Every time you modify a piece of code you have the option to generate or solve technical debt. When adding new features or fixing bugs I use the following technique:
- Remove the code that is not used (purge the dead code). This includes (but not limited to) not used features, comments, forgotten statements used for previous debug sessions and other “dispensables”.
- Refactor the code. There are 2 main reasons for doing this, improving the code Maintainability and Extensibility. There are a large number of refactoring techniques (including renaming variables). By doing this you also gain inside knowledge and have a good idea about how it works and how you could extend/fix it.
- Do the do. On a cleaner code that you now understand it’s easier to solve the task.
You do NOT need to wait for the managers to stop the production and schedule a full sprint to solve the technical debt, fixing the problems in small chunks you are creating a continuous improving process, it is a win-win-win situation.
Refactoring without automatic tests and/or a good QA team to back you up it’s an extreme sport, trust me (been there done that).
Before you make the time assessment for the task you have to read the code and take into account the new factors: time to clean, refactor and add unit tests if needed. Now multiply the result with 3 or 6 and you are good to go.
Changing lifestyle habits acquired over many years is often extremely difficult. — Marie Kondo
Practical example ⚓
You have a (legacy) TODO list module with only 2 functionalities: list all the TODO’s or fetch only the old (not done) ones. A new task arrives on your desk “add a new functionality: user ability to list the tasks scheduled in the next years”.
To maximize the technique effect, let’s presume that since you first wrote the module you have switched to JS6 and started to use Lodash(underscore). You will notice that it will highly improve the code quality.
The first snippet is the original code, the 2nd one is after we applied the first 2 steps of our technique: “1. Purge the dead code” and “2. Refactor”. After you move the common functionalities to avoid code duplication it’s very easy to add the new function (3rd snippet).
Best case scenario 🛌🏿
It would be great for the health of the project and your own to have unit tests coverage. Before you touch the code it would be awesome to check, add or create more unit tests, it will allow you to be merciless in first 2 stages (Cleaning and Refactoring).
In our example you need to write a series of tests to make sure the legacy code works, most probably you’ll find new bugs that you’ll fix in the refactoring stage.
When adding the new functionality you need to write some new tests to validate your work and have a better night sleep.
Now it is a good opportunity to learn new refactoring techniques. Remember: keep it small, work in small iterations and soon you will see big overall project improvements.
People cannot change their tidying habits without first changing their way of thinking. — Marie Kondo
- Find the code you need to change
- Purge the dead code
- Refactor the code
- Do your task
Other resources 📚
- “We need to rewrite the entire project, now we actually know what we are doing”. Before signing this contract read the footnotes, see what other devs are saying: Why You Should (Almost) Never Rewrite Your Software
- When is a BIG Rewrite the answer?
- Marie Kondo
- Design Patterns and Refactoring