Getting started with NDepend
So, after quite some time, I have finally got my thumb out and added an NDepend project to my new .NET Extensions 2.0 solution, in order to get some analyzing done before releasing it.
The first thing that hit me was how easy it was to attach a new NDepend project to my solution. I just had to:
- Install Visual NDepend
- Open my .NET Extensions solution
- Under the new “NDepend” main menu item, select “Attach new NDepend project to solution”
- Select all projects of interested (I chose all of them)
- Press the OK button and pray to god.
Once NDepend is attached to your solution, the menu will change and look like this:
…but before that, it will perform a first-time analysis of all projects that it is set to handle. This is done automatically, so just bind NDepend to your solution, and it will perform the analysis…
…after which Firefox (or, naturally, your default browser of choice) will come to life and display a complete analysis summary, which is generated in a folder called NDependOut:
So, what the report has to say?
The report is divided into certain sections, of which more (to me) are more interesing than others.
Well…first of all, a complete textual summary of application metrics is presented:
Now, this summary contains a couple of interesting metrics.
Note, for instance, the comment ratio (51%). I have always taken pride in commenting my code, but lately, I have focused on writing readable code instead 🙂 However, I have decided to overdo the commenting in this project, since it must be understandable for users that only get their hands on the DLL.
Since .NET Extensions is mainly an extension project, I think that this summary is quite what I expected…even if I maybe could do with a bit more interfaces. Note that not much is going un “under the hood” – almost everything is public (in some cases for unit test purposes, which I will change #beginner-error).
Also, since I am of the belief that one should NEVER work directly towards an object’s fields, I am happy that I have no public fields at all 🙂
The last row (cut of) displays the method/function with the worst cyclomatic complexity:
However, when I analyze the method with the Visual Studio analyzer, it says that the method has a CC of 13! Turns out that 25 is the ILCC (Intermediate Language Code Complexity) – the resulting CC. However, I will write a new blog post later on, in which I’ll use this information to improve the GetHtml() method. Stay tuned 🙂
Assembly metrics + abstraction/stability summary
After the interesting application metrics summary come some assembly metrics (also quite interesting) as well as information about for the stability of the different assemblies.
First of all, everything is presented a textual grid:
This information is then displayed in various graphical components, such as the Visual NDepend view (in Visual Studio, you can use NDepend to navigate through this view)…
…as well as the Abstractness vs. Instability view…
Now, let’s stop for a moment and discuss this graph. The word “instability” first made me feel like I had written the worst piece of junk there is, but I think that the word is quite misleading.
As I’ve mentioned, the analyzed solution consists of a lot of extension and helper classes, which almost never are independent – they mostly depend on other base classes, since that is their purpose. If I have understood the term “instability” correctly, this is exactly what it means. The solution is instable since it depends on a lot of other components…
…but for this kind of solution, it is hard to have it any other way. After reflecting over the graph a bit, and enjoying the green color (except for the so far empty build project), I understood what view intends to display.
Dependencies, build order etc.
This part of the report is probably a lot more interesting if you intend to delve into a solution of which development you have not been a part of earlier on.
However, for this particular situation, this part of the report really did not give me anything that I did not already know.
Amazing final part – constraints
Finally, NDepend displayes an amazing part where the code is evaluated according to all existing constraints.
…this part displays a constraint that selects all functions that:
- Has more than 30 lines of code OR
- Has more than 200 IL instructions OR
- Has a cyclomatic complexity over 20 OR
- Has an IL cyclomatic complexity over 50 OR
- Has an IL nesting depth that is larger than 4 OR
- Has more than 5 parameters OR
- Has more than 8 variables OR
- Has more than 6 overloads
For instance, the first item in the list – Split() – is there because it has more than8 variables.
Some of the default constraints are perhaps a bit harse, but most of them are really useful. Just having a look at these constraints and at how your code applies to them gives you a deeper understanding of how you (or your team) writes code.
Finally, comes an exhausting, thorough grid with ALL the information you can imagine about every single type in the solution.
The “worst” cells in each category are highlighted, which makes it really easy to get an overview of the entire framework…although the information is quite massive.
Well, only having connected an NDepend project to my solution, I have barely scratched the surface of what NDepend can offer. To be able to extract this much info by just pressing a button, is quite impressive.
I wrote this blog post yesterday, and have rewritten large parts of it today. During that time span, my stance towards it has shifted a bit.
Yesterday, since I then did not understand parts of the report, I was under the impression that your own hobby project is not the best context in which to use NDepend…and that it comes to better use when working in a role (e.g. tech lead / lead developer) that require you be able to quickly extract data about the systems for which you are responsible. In such a context, NDepend is greaaat.
However, after getting some time to “feel” how NDepend “feels” for me as a developer, I have started to see benefits even for a solution such as this extensions solution. As I will show in a future blog post, I can use the information I extract from NDepend to detect the parts of my framework that are “worst”…and makes it easy to adjust them, re-analyze them and see how my implementation grows better.
It is a bit like comparing my iPhone with my iPad. ReSharper was like my phone – as soon as I started using it, I could not live without it. NDepend, on the other hand, is much like the iPad. At first, I really could not see the use, but after som time, it finds right into your day-to-day life and…after a while…becomes natural.
I will scratch myself further down into NDepend. Stay tunes.