Visualizing Technical Debt Repayment through Refactoring with NDepend
Note: This article is an English translation of my original article, which you can find here.
In this article, I will explore how NDepend can be used to repay technical debt through refactoring.
Introduction
I received a license from Patrick Smacchia, the creator of NDepend. However, my recent role has been more focused on infrastructure rather than application development, so I have not had the opportunity to use it in my work. Therefore, I decided to refactor some source code I had written in the past.
Here is the source code I tried to refactor; it is a simple desktop capture tool:
The code was written 15 years ago, so it is quite rudimentary, but I thought it would be perfect for practicing refactoring.
Patrick suggested that the feature to “set an old project as a baseline and compare it with the refactored project to visualize the extent of improvement” would be a good match. In this article, I will try this feature and show how to visualize improvements through refactoring.
What is NDepend?
NDepend is a static analysis tool for analyzing .NET code. Its main features include code quality and architecture visualization, and code change tracking.
Here is an article where Patrick talks about NDepend:
Analyzing the Source Code
Launch VisualNDepend.exe and analyze the VS project. The association with the VS project can be saved as an NDepend project.
The analysis results are visualized in the dashboard.
Setting the Baseline
First, set a baseline before refactoring.
Create a copy of the original source code `v1.0` and create `v2.0`. Then, create NDepend projects for both v1.0 and v2.0, and set v1.0 as the baseline for v2.0.
From now on, I will not modify v1.0 and refactor v2.0.
Exploring Hotspots
NDepend has powerful features to help identify areas that should be refactored.
Focus on the `Debt` (technical debt) in the dashboard.
Selecting `Types to Fix Priority` lists classes with low breakpoint `issues`.
The lower the breakpoint, the higher the investment value in improving code quality, and it serves as an indicator for determining priority.
Please refer to the official documentation for the concept of breakpoints:
This time, I will focus on fixing MainForm+Config with the lowest breakpoint and an E rating.
Please note that the rating is based on the SQALE method.
Refactoring Hotspots
Click `Issues` on the `MainForm+Config`, and a list of issues will be displayed.
Many issues stem from fields, so I will change them to properties.
v1.0
/// <summary>
/// Configuration
/// </summary>
private class Config {
/// <summary>
/// Image format
/// </summary>
public string ImageType;
/// <summary>
/// Image magnification
/// </summary>
public decimal Magnification;
}
v2.0
/// <summary>
/// Configuration
/// </summary>
private class Config {
/// <summary>
/// Image format
/// </summary>
public string ImageType { get; set; }
/// <summary>
/// Image magnification
/// </summary>
public decimal Magnification { get; set; }
}
After rebuilding and analyzing again, you can see how much debt has been repaid from the baseline. Other metrics, such as `Method Complexity`, are also visualized.
New debt created unintentionally
It is essential to ensure that refactoring does not create new debt.
I will repost the dashboard from earlier.
This shows that four new issues have emerged from the baseline. These are debts created during the refactoring process.
Clicking on `+4` will list the classes with issues.
Clicking on the `typeIssues` of the relevant class will display the issue.
All of these issues point out that the visibility of the properties is public, even though the MainForm+Config class is not public. Therefore, I will modify them to internal.
v2.0
private class Config {
/// <summary>
/// Image format
/// </summary>
internal string ImageType { get; set; }
/// <summary>
/// Image magnification
/// </summary>
internal decimal Magnification { get; set; }
}
After rebuilding and analyzing again, confirm that the new issues are resolved.
Visualizing Comparison with Baseline
As mentioned earlier, you can compare how much debt has been repaid from the baseline.
Additionally, you can compare various aspects.
For example, selecting [Diff] > [Code Diff Summary] > [Types where code] was changed from the menu will list the classes changed during refactoring.
Selecting [Diff Source] from the context menu will display the difference between the relevant class and the baseline.
Conclusion
In this article, I explained how to use NDepend to improve code quality by focusing on comparing with the baseline.
After trying it out, I felt that NDepend could provide the following benefits:
- The quantification of losses due to debt and repayments through refactoring, which can be used to appeal to the business side. In other words, it can be used as a basis for proposing refactoring.
- Improved developer motivation through visualization of code quality improvement achievement rates and the current code quality compared to target values.
Furthermore, NDepend has many other features and use cases. I would like to try other features in the future.