This posting is part of my “Thoughts on Employment” series, detailing some lessons learned and general musings from my career as a software developer on what an employer can do to provide an effective, productive and attractive work environment for highly effective software development teams. For an introduction to the series and an index of postings in the series, please read my introduction post.
Martin Fowler has a good post explaining Technical Debt:
“You have a piece of functionality that you need to add to your system. You see two ways to do it, one is quick to do but is messy - you are sure that it will make further changes harder in the future. The other results in a cleaner design, but will take longer to put in place. … In this metaphor, doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into the better design. Although it costs to pay down the principal, we gain by reduced interest payments in the future.”
Before you can put together any plan for managing your tech debt, you have to know where it exists. Personally, I think Sonar is a great tool for this. Out of the box, it will use industry standard tools to find trouble spots using static analysis (like FxCop), unit test coverage, cyclomatic complexity, etc. But here where there's real power in this tool: it also lets users mark sections of code as problematic or in need of refactoring. It has tools for grouping problematic sections into action plans and for assigning responsibility to developers (and for developers to manage the items assigned to them). And, it's free, and pretty easy to integrate into your existing continuous build process.
But knowing is not enough. You need to have a plan for addressing the tech debt. There are two general groups to plan for: small, one-off items and large, architectural changes. For the big stuff, this needs to be in your product backlog/roadmap, as changing it represents a re-architecture of the system. So have an agreement between the product owners and the developers to allocate some amount of time in each release cycle to make under-the-hood changes like this. It's not likely something you can sell as a feature to a customer, but neither is paying down your mortgage. It's something you do to keep your codebase maintainable over time.
For the smaller stuff, you can address it as backlog items as well, or set aside dedicated time specifically to address these. At CSG, our releases were typically broken down into five iterations: three "development" iterations and two "hardening" iterations. During the dev iterations, we were focused on new functionality, but the hardening iterations were primarily QA focused, so dev work was sporadic, mostly bug fixes and usability enhancements falling out of the QA efforts. We used the spare dev cycles to address these less risky tech debt items - with the de facto tasks being filling gaps in unit tests.
At InRule, one Friday a month is set aside as "Tech Debt Paydown day", where developers pull items from the tech debt backlog and work as many as they can in the day. There's no pre-allocation of tasks at the start of the iteration, just time reduction from the dev capacity. We use a
UserVoice.com site (Update: we now use a Trello board) to track the tech debt backlog, which allows developers and others in the company to vote on which items they'd like to see addressed, and developers try to work from the items with the highest number of votes.