The release of Visual Studio 2008 brought along Code Metrics to the IDE‘s ‘out-of-the-box’ functionality (I’ve been overusing that phrase thanks to our resident CRM Consultant at work!). This was a major boon for .NET developers to get a clear idea of health of what they write, Visual Studio 2005 gave FxCop integration that provided much needed static code analysis for .NET assemblies. Together these tools provide a peek into the deep depths of the project your working on, it benchmarks the correctness, performance and security implications, localisation, design issues amongst other metrics. Damn useful if you’ve inherited – as I often do in my consultancy life – someone else’s code base with little or no documentation. They say code is the best documentation right? (oh gosh, not one of those projects!)
Whilst both the metrics in VSNET and FxCop give you a low level understanding of your code – based on framework guidelines, what if you want more in depth understanding of what your ‘working with’ rather than how you use the .NET framework? How many methods derive from a certain control – remember we’re doing static analysis here, no Resharper loving! Or how maintainable the assemblies are. What are the methods with more than 30 lines of code? (hint: need to refactor!)
This is where NDepend comes in. NDepend is a static code analysis tool on steroids – and I’m not exaggerating here. You will love NDepend long time as I do right now.
Load up NDepend, point to your assemblies, then let NDepend think a little and it will spit out a plethora of information for you to take in.
The NDepend UI – VisualNDepend
There is however one caveat, the first time you use it – and I know this will happen to the majority of users, you’ll probably get overwhelmed with what you’ll be displayed with:
NDepend Paint.NET Analysis
So you can reproduce this with the trial of NDepend, I’m looking at the latest Paint.NET release. But once you get over your initial sense of wonder and disbelief you can start to demystify the UI and the beauty of NDepend. Dont worry, theres plenty of documentation and help to get you on your way, I’ll cover those later
First, we have a Class Browser to the left that lists all the assemblies that are being anaylsed – this includes the assemblies you selected (black!) and the assemblies that were added automajically by NDepend as dependencies (blue).
To the right of the class browser is our Metrics visual representation (those black balls actually mean something – Marty!). We can tell NDepend to show us (visually via the Code Metrics display) the top 10,20,50-5000 methods. Double click on any item in the view and it will automatically jump to the source (in the working VS.NET instance if available) for you to inspect further. Theres also deep integration with Visual Studio too – again later!
Underneath the Metrics window we have the Dependency Graph on the left and the Dependency Matrix on the right. This view gives us an idea of the coupling between the assemblies in our list.
The World of CQL
Then we have – what makes me get jiggy wif it, the CQL Query window. CQL is Code Query Language, and its just as your thinking, its SQL for Code. Armed with a basic understanding of CQL you can get some really useful information about your project – infact the report that gets generated by NDepend already contains a bunch of metrics for you and comes with over 85 metrics to begin with in a heavily documented specification – with examples. Writing a simple bit of CQL like the one below, will give you a representation of all public methods that contain more than 30 lines of code.
SELECT METHODS WHERE NbLinesOfCode > 30 AND IsPublic
Neat huh? Thats only an example from the features page, there’s lots more. We can even setup a constraint to notify us when we exceed a threshold.
WARN IF Count > 0 IN SELECT METHODS WHERE NbILInstructions > 200 ORDER BY NbILInstructions DESC
This will warn us when we have methods that exceed 200 IL instructions. You can even combine a bunch of them and workout a metric to benchmark which methods you need to refactor, heres one from the report that gets autogenerated by the VisualNDepend tool:
WARN IF Count > 0 IN SELECT TOP 10 METHODS /*OUT OF "YourGeneratedCode" */ WHERE
// Metrics' definitions
( NbLinesOfCode > 30 OR // http://www.ndepend.com/Metrics.aspx#NbLinesOfCode
NbILInstructions > 200 OR // http://www.ndepend.com/Metrics.aspx#NbILInstructions
CyclomaticComplexity > 20 OR // http://www.ndepend.com/Metrics.aspx#CC
ILCyclomaticComplexity > 50 OR // http://www.ndepend.com/Metrics.aspx#ILCC
ILNestingDepth > 4 OR // http://www.ndepend.com/Metrics.aspx#ILNestingDepth
NbParameters > 5 OR // http://www.ndepend.com/Metrics.aspx#NbParameters
NbVariables > 8 OR // http://www.ndepend.com/Metrics.aspx#NbVariables
NbOverloads > 6 ) // http://www.ndepend.com/Metrics.aspx#NbOverloads
// Here are some ways to avoid taking account of generated methods.
!( NameIs "InitializeComponent()" OR
// NDepend.CQL.GeneratedAttribute is defined in the redistributable assembly $NDependInstallDir$\Lib\NDepend.CQL.dll
// You can define your own attribute to mark "Generated".
Whats more, because NDepend is language neutral you can query any managed assembly. Theres so much goodness you can get from CQL, most of your needs are already documented in the specifications.
Healthy coder == healthy code right?
NDepend also gives us a representation of what state the code is in with the generated report.
Paint.NET Abstractness vs Stability
This metric – based on Robert C Martin’s Abstractness vs Stability paper. To quote the paper’s Abstract directly:
This paper describes a set of metrics that can be used to measure the quality of an object-oriented design in terms of the interdependence between the subsystems of that design. Designs which are highly interdependent tend to be rigid, unreusable and hard to maintain.
Yet interdependence is necessary if the subsystems of the design are to collaborate. Thus, some forms of dependency must be desirable,
and other forms must be undesirable. This paper proposes a design pattern in which all the dependencies are of the desirable form. Finally, this paper describes a set of metrics that measure the conformance of a design to the desirable pattern.
In the case of Paint.NET we can see that we’re all over the bottom corner of the image. What does this mean?
First we have the two ends of the scale.
- Y – Abstractness
This measures how abstract the assembly is, can it be extended without recompiling? Lots of interfaces and base classes help here.
- X – Instability
Measures how much this assembly is utilised by its public interface. For most third party component (from vendors) they’ll fall into the less instability area, so you have to ensure that any changes are properly managed to avoid breaking clients.
Then we have two zones.
- Zone of uselessness
This is when an assembly is very abstract and extensible but no-one uses it you’ll find it closer to this area.
- Zone of Pain
This is when an assembly is referenced (or have lots of dependants) and is not very extensible – no abstract implementations.
One thing to note though, the words ‘Pain’ and ‘Uselessness’ may be a bit harsh in its wording. If you – like me – have a core ‘framework’ that you write have it locked down and reference it muliple projects then they should indeed fall into the ‘Zone of Pain’ assuming that you have ensured its stability and realise the consequences of breakages later on. Most third party products will fall into here – we’re talking your UI Controls, Sharp components etc.
Ideally you’d want to be hovering in the green area cosey with the line in the middle for your core product.
Would you like Documentation with that?
As mentioned earlier, NDepend comes with lots of help, firstly we have – what I used, the Getting Started screencasts, tutorials, CQL Documentation with *actual* usable examples.
Scott Hanselman has also released a nice cheatsheet for NDepend that will go well hanging next to your PC.
Integrating NDepend to Integration Server
At home (and at work) we use Jetbrains TeamCity, you can easily integrate NDepend into TeamCity by following Laurent Kempé directions.
If you use CruiseControl.NET, you’ll find Robin Curry‘s guide on integrating NDepend to NAnt and CruiseControl.NET useful.
Integration with your favourite tools
NDepend fully integrates with Visual Studio and Reflector.
NDepend Options Integration
The integration in Reflector – which reflect that of Visual Studio integration.
NDepend Reflector Integration
Gives you one click access to some common metrics.
If you want to get a good understanding of your project – or someone elses, metrics will help you greatly to give you an impression of the health of the project and NDepend will come in quite handy for you. We only _barely_ scratched the surface with this blog post, I’ve spent a good chuck of a week using NDepend and find it ubber useful in my work life – partly because it involves reparing the mess others have left – but it also serves as a good reminder of how you should write code.
Fine Print: Full Disclosure
I was offered a license to NDepend by Patrick Smacchia and given the chance to write my thoughts on this product, I was not paid to review this product – feel free to send some moola if you want to though 😉