So You Have Technical Debt?
Does this sound like you? Scores of different folks have been working on the codebase for a decade now. Admirably, the company has made money and grown over the years. But, the dev team knows there is a great deal of technical debt. Due to various small runs at making improvements over the years, some areas of the code are in better shape than others. Management knows that somehow, requests for seemingly similar-sized features require dramatically different implementation times and skill level in different parts of the app. (And by skill level, we euphemistically mean the amount of experience in that part of the “forest.”) Management has asked for help to “get out from under” the technical debt – even though it is a rather nebulous term. They correlate technical debt to moving slower, to more expensive features, to hard-to-change systems.
Where to Start?
Anecdotally, the dev team might have an instinctive feel for what needs to be attacked. But there should be more input than “gut feel” in terms of deciding where to expend energy at removing the technical debt. Do we just tackle the items with the highest amount of technical debt? Refactoring our way to a better codebase? In general, the answer is “no.” Instead, we somehow need to consider the “cross-product” between the amount of technical debt and the business needs. Consider your system in terms of components and chunks of major feature sets. You could quantitatively determine the demand for changes to the components as being made up of feature requests and bugs. Add in some business ranking to the picture and you could “measure” where the highest level of need lies for making code changes. And, if you were to aggregate the information by component, you could see a ranked list of the top things to work on – from the business perspective. Then, as you work in an area with technical debt, you can make fixes to improve the code. But is that enough? Now imagine being able to overlay the technical debt for those same areas or components. You see, you have to also consider the “interest” that accrues with technical debt. (See sidebar on this topic) If you see an area that has the need for a lot of change and it is also one with high technical debt, there is the place you should focus refactoring efforts on (or sometimes a wholesale re-write or re-design if warranted).
Measurement & Control
There are various tools out there to help measure aspects that correlate to technical debt. SonarQube is one such system that you can install and use. When I was at TogetherSoft, I had the team build in some of my favorite audits and metrics – this stemmed from the days (dare I say late 80s and 90s?) when I first used tools like PC-Lint and other code metrics and quality checkers for C and C++. I did some comparison of Sonar vs. Together for four components of a system, and found a startling correlation between Technical Debt & Halstead’s Difficulty metric:
While pure numbers can point you in the right direction, I also use some visual cues that show overall class model shape, and dependencies between packages using tools that reverse engineer the code into UML diagrams. I even like to think of the thumbnails as a sort of code-equivalent to the Rorschach ink blot psychological tests. Each overview also shows the technical debt, and a comment from me:
|A – 1,220 daysWide and squat||B – 853 daysÜber long classes, tall & narrow|
|C – 349 daysReasonable shape, but rather large and complex||D – 62 daysSimple shape, manageable size|
In case you are wondering, the blue lines are the dependencies between classes. In the thumbnails, sometimes you can see long, tall, rectangles representing huge classes. And when you see triangular, or umbrella-like “canopy” shapes in the image, you know there is either a lot of inheritance (i.e., the top apex is a parent class), or a tremendous amount of other types of dependencies (i.e., the apex is included in many other classes).
Useful Technical Debt Metrics
Most of us would think the left-hand component is “better” than the one on the right. And we would be right. Whether using Sonar’s info, or Together’s metrics, we get the same picture. The package on the right is the one labeled gui in the metrics table below:
There are extremely high values for:
- Coupling Between Objects (CBO) – we all know coupling is bad, as it thwarts reuse, and increases likelihood of unintended consequences in code changes. With high coupling comes high cost of testing.
- Cyclomatic Complexity (CC) – this counts the number of pathways through the code. The greater the complexity, the harder to comprehend, change, and test all the myriad of combinations.
- Data Abstraction Complexity (DAC) – implying there are a high amount of other custom data types/classes involved (not simple primitives)
- The Depth of Inheritance (DOIH) – which means a lot of specialization. And inheritance is it’s own form of coupling in that a change to a super class “trickles down” through the child classes.
The Best Medicine
Couple the objective and subjective measures with the demand for bugs/features, and developer “instinct,” and you can methodically begin to improve your current situation. What should one do to stay out of this sort of mess? Abstinence. Avoidance. Just say “no.” Learn. Don’t let the short-term view be at the expense of the long-term health of the system. Short-term, purposeful technical debt is okay, as long as you remove it in the next sprint/release. Admittedly, it is a balancing act. The worst thing you can do is nothing. Unless you are ignorant, then ignorance is bliss, until you go out of business because a competitor can build a better system faster, and keep responding more easily to meet market demand. Jon Kern is a developer, software architect, and team leader/coach that keeps the people and the business in sharp focus. Aerospace engineer-turned software expert, co-author of Agile Manifesto for Software Development and Java Design. Jon helps develop mission-critical software. His insights are critical factors in producing solutions with significant impact to business value, quality, budget, and schedule. He brings experts from around the world to work on the project team as needed. Jon engages with the client’s developers and mentors them on agile and distributed development processes, techniques, & tools. But more importantly, Jon leaves behind a team that is much more valuable to the company.