Static Analysis Tooling for C# and .NET, NDepend in Depth
As a software architect I often have to analyze many applications code in order to perform a quality check.
Is the code looking good? What about its complexity and test coverage? Can I consider the code as maintainable with a good scalability?
Of course I won’t spend my whole time reading each source file, it would be too long and for sure useless. Hopefully a set of rules and tools can help if you are in this same situation.
For those using .NET as their main technology, you should check out each of these tools and see how they can improve your work experience:
- Sonar is a debt analyzer and supports more than 25 languages
- ReSharper is a productivity enhancer that offers code analysis and many more features
- JustCode is also productivity enhancer
- FxCop performs static analysis following best practices and recommendations
- NDepend offers static code analysis for .Net and focuses on relations between objects
Each of them has its pros and cons and has its specific field of use thus this is why in some cases Sonar can be a better choice than NDepend or ReSharper and vice versa!
In this article I will focus on NDepend.
What is NDepend?
NDepend is a static code analysis for .NET. It’s a commercial tool and you can try it for 14 days freely.
Patrick Smacchia created NDepend in 2004.
NDepend can be used in both standalone and Visual Studio integrated mode.
Personally I prefer Visual Studio Integrated mode since it has all the features and more, plus you can use your IDE features.
NDepend gives you a quick access to many metrics of your code and illustrates each metric or other aspect, i.e. assembly dependency, through graphical representation. This is a real plus!
For me the main feature of NDepend is its query language it is built upon: CQLinq.
CQLinq, meaning Code Query LINQ, is a query language that you can run on an abstracted model of your code. Basically you can query your code the same way you query views or tables from a database. For instance to get all methods having more than 30 lines of code I would simply open the CQLinq editor and write:
from m in Methods where m.NbLinesOfCode > 30 select m
In Visual Studio you will get this view, side by side the query and its graphical representation in the so called Code Metrics view:
Thanks to CQLinq there is not much left to do, all metrics can be translated into simple CQLinq queries and this is why NDepend is very powerful!
Also NDepend offers all its logic in an API that you can find in the lib folder of its installation: NDepend.API.dll
You can use NDepend API to build your own project analysis tool. For that, all you need is to include the NDepend.API.dll file in your project and then make a reference to the needed namespaces. For instance here is a piece of code that shows what you can do with this API.
from m in Methods
where m.NbLinesOfCode > 30
orderby m.ILCyclomaticComplexity descending
select new { m }
Can easily be deported into a C# function of your project:
using NDepend.CodeModel;
using NDepend.CodeQuery;
public List GetComplexMethods(ICodeBase codeBase)
{
var complexMethods = (from m in codeBase.Application.Methods
where m.NbLinesOfCode > 30
orderby m.ILCyclomaticComplexity descending
select m).ToList();
return complexMethods;
}
NDepend API documentation is accessible online.
Now all what you need is a bit of imagination to build the perfect analysis tool that fits your needs.
Built-in NDepend Metrics
NDepend comes with many preconfigured queries to match most of the common metrics rules. To explore the predefined rules open the rules explorer view:
And then you get this panel open:
Actually around 240 rules and more are already defined for you and ready to use.
However you should pay attention to what is defined. For instance according to NDepend rules here is the filter that defines a method to refactor and probably you can consider the filters as too restrictive or not enough:
from m in JustMyCode.Methods
where m.NbLinesOfCode > 30 ||
m.CyclomaticComplexity > 20 ||
m.ILCyclomaticComplexity > 50 ||
m.ILNestingDepth > 5 ||
m.NbParameters > 5 ||
m.NbVariables > 8 ||
m.NbOverloads > 6
select new { m }
Even though NDepend rules are quite close to what we could consider as baseline rules I strongly recommend that you spend a bit of time sharpening the pre-built rules or write your own queries! You just have to create your custom group and then create your queries.
Now you should be asking yourself what the heck is JustMyCode?
Don’t panic you are asking the good question! JustMyCode is just a filter that eliminates generated code that comes when using frameworks like Entity or any other.
Since it makes no real sense to check the quality of the code generated by other tools, JustMyCode should always be used in each of your queries.
You can extend the definition of JustMyCode by doing so:
notmycode
from m in Application.Namespaces.WithNameLike("NameSpace.Of.GeneratedCode").ChildMethods() select m
This way I say that all the code within the “NameSpace.Of.GeneratedCode” namespace is to consider as generated code. You can also filter by attributes, file names, naming convention, inheritance or whatever you need, very easy! By default NDepend considers as generated code contained in designer.cs files, in InitializeComponent method and few others like this.
Graphical Views
You have four graphical views in NDepend. Two of them actually focus on the same aspect of dependency. The third one is the metric code view that I quickly spoke about in the beginning. And the fourth one is simply the feature that helps you export the result of your CQLinq query into a graph.
Side by side code dependency matrix view and graph view:
If you are not familiar with these graphics don’t be frustrated, usually no body does! So NDepend has tooltips to help you understand the various values. Basically the matrix and the graph both help you to figure out how assemblies, namespaces, classes, methods depend on each other’s.
The graph view is more useful to show out a “spaghetti code” and the matrix view is more suited to check whether or not the code follows the principle of low coupling and high cohesion. So most of the time it’s better to analyze both graph and matrix.
I did not understand why the lines were so curvy in the dependency graph, even for small amount of nodes you get curvy lines instead of straight lines. I don’t think that it will make a huge difference in your daily life but I don’t see the point with all these curves, for me it adds unnecessary confusion and I would prefer to see straight lines most of the time. Look by yourself:
Here is what NDepend developer team said about it:
The graph algorithm comes from an older version of MsAgl. Actually we don't find the result that over-curly, but anyway, Graph is an important feature that will face major enhancements in the mid-term
Next, the metrics view displays proportionate blocs of different size according to the metric you selected. It can be number of lines of code, number of IL instructions or any option in the drop down:
The metric view used to give me headaches because when changing to # lines of code I had this message many times:
So as you can see even though the message is quite clear, it’s not helpful since it doesn’t tell you more about what is actually missing!
In case your are in the same situation, check manually that each project is configured to generate the pdb files in the assembly directory.
Continuous Integration
You can easily set up NDepend to be part of your build server in your continuous integration process. For that can either configure the command line as a build task or get the ready to use extension NDepend TFS 2010 integration on Codeplex.
NDepend is compatible with CCNet, TFS, Finalbuilder, Team City and probably many more, read about it here.
Open Source
I introduced NDepend by saying that it is a commercial tool. It’s not false but NDepend API is completely free to use in any of your project. Actually NDepend comes with a command line tool called “NDepend.PowerTools” and its source code:
As it is said in the documentation:
NDepend.PowerTools are a set of short open-source static analyzers, packed into the Visual Studio solution
So you are free to extend the code for your own usage.
One very cool feature of the PowerTools is the code duplicate detector.
I think that this feature should be fully integrated in NDepend UI and hopefully here is what NDepend said about it:
Certainly code cloning detection is a future flagship feature
Documentation
NDepend documentation is complete and up to date. It covers all the features of the tools and have many screenshot and examples. It also comes with a 3 minutes introduction video. But unfortunately the video is recorded for the version 4 of NDepend and the current release is the version 5. Also I think that Patrick Smacchia could have done better by recording more videos and as the developer team said:
More videos is definitively something we need to offer and will offer
Other features
Beyond all these good features I already introduced, NDepend also offers:
- Static HTML report
- Test coverage analyzer
- Continuous analysis
- Cirtical rules build failure
What is missing in NDepend?
For me NDepend is a great tool but still need some improvements.
Actually you can’t miss that nowadays apps combine different languages. Most of the time your app will be like a set of C#, or whatever your drug is, and JavaScript lines of code and for this reason your code analysis will for sure have to be polyglot or at least bilingual. And since NDepend does not understand JavaScript, you will have to get other tools to analyze all your code.
This can be a killer point for some users who would prefer a tool like Sonar which support different languages.
For instance in a C# ASP.NET SPA application, most of the code will probably be written in JavaScript and so I will have to complete NDepend C# report by using another tool.
And then the second missing feature would be the debt analyzer report_._ Patrick Smacchia has chosen to focus NDepend on facts and metrics from source code, which is good and an objective point view. But I think that a smarter interpretation of the analysis through a debt report would be very appreciated by many developers. We can excpect some improvement here according to Patrick Smacchia:
Same as code cloning, debt analysis is a future flagship feature
Final Word
As a .Net user, I found NDepend very powerful and quite easy to use. I really think that the CQLinq language and the NDepend library are actually the best features of the tool since I did not find any equivalent.
NDepend team is very active and we can expect many good features in the next releases.
Now just try it here