I worry if "Technical
debt" is just a label we put on things so we don't have to think about
them. e.g. "We know this will create technical debt and we can come back
to it at some point in the future." This doesn't require that we do the
best to mitigate the consequences of that debt now though.
At its simplest, technical
debt is just a name for the consequences or side effects of the decisions
that are made (intentionally or accidentally) when developing software. Dealing
with technical debt therefore comes down to just dealing with the consequences
of past decisions. Fortunately, there are lots of ways developing software that
make it easier to deal with these consequences and lessen their impact.
- Have automated tests for
the system at a high level.
Regardless of what you call them, you need tests that
verify that the application/system works at a high level, not just at a
method/class level. When it is possible to verify that the system does what it
should it removes the risks associated with changing how it does it, that is
changing the code to remove the debt but without breaking the overall
functionality. This is key to avoiding regressions and negative side effects of addressing debt.
- Remember the boy scout
rule. (Leave the camp/code better than you found it.) If while working on
something you find some existing code that needs improving, and you can do
something to improve it without it being a major distraction from the task
that was your original focus, you should make such improvements. Of course this
depends on a working culture that allows code gardening.
- Allow code gardening.
Just
as with a real garden where you might tidy up some leaves, pull up a weed
or prune a rogue branch from a hedge as part of the general maintenance of the
garden, there are general maintenance tasks that can also be done to code. This
is very similar to the boy scout rule but with an important requirement that it
must be allowed for code unrelated to what you're supposed to be working on.
Suppose you were working on Feature Y and it involved modifying Class X. With
the boy scout rule, you may make other modifications to Class X that improve
it. With code gardening it's also potentially acceptable to make changes in the
completely unrelated Class Z. Say you just happened to glance across Class Z by
chance and noticed an improvement you could easily make. If code gardening is
allowed then you can improve it now. If code gardening is not allowed then the
best that might happen is a bug gets raised to improve Class Z at some point in
the future. The reality though is that it's a low priority bug and so never
makes it on to the schedule. The opportunity to make an incremental improvement
to the software is missed and so the slow degradation in overall quality
continues. It's important to note that for this to be possible it requires that
small frequent check-ins be allowed (not a one check-in per feature
policy) and a branching strategy used that allows such small improvements
to be easily made in isolation.
- Enforce code reviews on
non-trivial changes.
You can alleviate the risk of a low bus factor
on an area of code or something that no-one working on a project wants to risk
touching by using code reviews. Code reviews have a lot of benefits but the
important point here is that the person who signs off on a review agrees that
they will be able to support it in future, should the original author not be
available. This is not about assigning responsibility or blame. This is about
ensuring that the original code was clear enough that another developer can
understand what has been created. If no one is willing to sign off on a review
because they wouldn't be able to support maintaining it - improve the code
until someone agrees that they could.
- Use "why-and"
comments in code to explain intentional debt.
Comments in code are often a bad thing. All things being
equal, code should be self-explanatory. You shouldn't need code to explain what
a piece of code is doing or how it is doing it. Where there is a general need
for comments though is if why a piece of code was written the way it was isn't
clear. From a business perspective sometimes deadlines are critical. You may
have to put in a dirty hack to get something working to meet the deadline.
This is an example of where comments are useful. Just adding a comment that
acknowledges a hack (or other form of technical debt) has been made may be useful to help avoid people thinking
badly of you in the future isn't enough to actually help other developers or
the project. In such a scenario you should add the comment that acknowledges
WHY the intentional debt is there AND what should be done to address it. Addressing the
debt may mean more time is needed or waiting on a dependency. The important
thing is to provide information that will help when someone comes back to work
on the area of the debt. The aim is to avoid someone looking at the code and
asking "why is it like that?" and also to provide context and
information that will help when someone does have to modify it.
Just
a few points but they've helped me in numerous projects in the past. Let me know what you think or if you have any other tips to make working with technical debt easier.