Static code analysis with NDepend
[Disclaimer: Patrick Smacchia from the NDepend team approached me and offered me a licence for NDepend if I would blog about my experiences with the tool. However, all opinions are my own.]
Static code analysis is a powerful tool to understand and improve your codebase, using a variety of techniques to help find issues or vulnerabilities before you execute your code. NDepend is a popular tool for doing this on .NET code, with deep Visual Studio integration. I was interested to see what I could learn about a fairly substantial commercial codebase that has been developed over a few years.
To start, I downloaded the plugin from https://www.ndepend.com/ (downloading from the Visual Studio Marketplace just points you to the website). For reference, I was using version 2018.1.1. There are a couple of installation gotchas: the download is just a zip file with no README, and when you install the VS extension, it introduces a dependency on the files you unzipped, so make sure you extract to somewhere permanent rather than a temp directory! The developer also suggests that you don’t use the Program Files folder. I’d recommend reviewing https://www.ndepend.com/docs/getting-started-with-ndepend before you get going as it gives a few useful pointers, and would probably benefit from being more visible during the download/installation process.
To start, I created a new NDepend project and ran a full analysis of the codebase, which took roughly 45 seconds for around 32,000 lines. After that I was presented with a dashboard in Visual Studio and an HTML report to explore.
As you can see, there’s immediately plenty of data to check out! I was happy to see that our tech debt rating was looking pretty healthy at a B grade, with not too much estimated time to reach an A. I briefly scanned the HTML report, including the diagrams at the top:
- a dependency graph shows the links between various assemblies, although ours was too hectic to be useful;
- similarly, a dependency matrix presented the same information in a different way, although didn’t include information about all the assemblies; both diagrams invited me to use the full interactive version instead
- a treemap metric view quickly highlighted areas with high cyclomatic compexity, which was a great way to start identifying problem areas
- an abstractness vs instability chart, which showed which parts of the codebase might be harder to maintain. This one was interactive which was nice to see.
I assume these are presented first to try to highlight some of the visualisations you are able to produce, but it didn’t really guide you to where to find the interactive versions or any more that might be available without digging through some documentation. It was also a bit of a shame that by default they opened a “scaled” version, which then opened in a dialog that went outside the visible screen, making it harder to navigate and close than just opening the full versions, which Chrome scaled automatically for me.
However, the HTML report is only supposed to be a summary, and most of the power is in the Visual Studio extension, so I headed back there to take a look at some of the errors I’d noticed in the report. Two “quality gates” had failed, so I was keen to see what they might be. Clicking on the failed number took me straight to the Queries and Rules Explorer to show me where the failures were (“Critical Rules Violated” and “Debt Rating per Namespace” were the offenders). The way that NDepend works is by applying series a rules against your codebase. It ships with lots of presets, but you have the ability to customise and extend the rules based on your own opinions. They’re written in a LINQ-like query format, which should feel quite natural to C# programmers.
I really appreciated the explanations provided with each rule that had been broken; hovering on a rule brought up a summary with a description of what the rule meant, why it was important/would improve your code if you fixed it, and instructions on how to fix it. Double clicking a rule showed a list of files where it was violated, and other relevant info. Hovering on a file reveals a nice summary of stats about that file; for example, this was one of our worst offenders for complexity:
Calculations such as the breaking point help to drive decisions about how critical it is to fix the issues that NDepend is highlighting, and the links to the documentation are useful to clarify any points you might want more information on.
I thought I would try to pick some low-hanging fruit off and fix one of the critical rules that was broken. NDepend will not automatically fix code for you, but it will take you to where you need to make changes. Unfortunately, when I fixed an issue, it didn’t disappear from the list immediately; you must first rebuild the code and then run the analysis again. A nice touch would be to have the list update in real-time to show progress towards fixing problems. However, NDepend does keep snapshots of each time you run the analysis, so you can compare against the baseline (when you first ran the analysis) to see how your codebase is changing over time.
There are lots of rules to explore and problems to fix, but I also wanted to see what other tools NDepend gives you to dig into your codebase. It provides various dependency graphs and matrices to understand the relationships between classes in your code. I particularly liked the treemap for easily and quickly visualising where certain issues are in your code and how prevalent they are, and then being to drill straight into them as well.
NDepend is clearly a very powerful tool with many facets that will take a while to dig into all of them, but things like contextual help and well-linked documentation in Visual Studio help you to explore your way around. It is a helpful companion to drive code quality up and improve your knowledge around potential code issues and the impact they can have. You can also integrate it with your CI to ensure that metrics are visible and can therefore be worked on to track and improve them over time. There’s so much more that I haven’t had chance to go into for this blog post, but hopefully this has given you a good taste of NDepend’s potential. Unfortunately it does come at a bit of a cost, but you can download it from https://www.ndepend.com/ and start a free trial before committing to explore it for yourself. Here’s to better quality code!