NDepend: Application Metrics

A few days (maybe even a week ago now) I had an email in my inbox asking me if I’d like to have a copy of NDepend so I could maybe write something about it on my blog. I went through 3 stages – 1st – free software?! Hell yes, I’ll have that… 2nd, actually, I have Visual Studio 2010, I have code metrics already, do I need more? 3rd – presumably there is a reason that NDepend exists, maybe I should take this opportunity to get to know why and what it’s for.

So I said ‘yes’ and the next day I had NDepend installed.

Now, getting started is pretty easy, there are videos for that, and no one could deny that the Metrics view looks snazzy enough to befuddle any casual passers-by.

So, I’ve got it open, I’ve opened up one of my solutions and have been slapped in the face with a shed load of analysis and no clue as to what I should be looking at.

All the metrics are explained at http://www.ndepend.com/Metrics.aspx so I figured I might work my way through them, see if I can generate code that will hit those metrics and how and why it is there (I’ll be doing it all in VS 2010 – probably using the Visual NDepend app as my machine is a bit rubbishy :))

I’m going start with Application Metrics as they are first on that page, and, well, that’s a good enough reason really.

 

NbLinesOfCode

Pretty easy to see what it does, it counts the number of lines in the code. The main thing I’m interested in here is the Method - Lines of Code (LOC) metric. The more lines the harder to read, the harder to maintain and the harder to cope with. On my screen 60 lines fits, any more would involve scrolling, but I don’t want to be hit with a 60 line method, that’d be a huge pain to read. NDepend’s metric guidance states 20 lines is really the maximum that is maintainable, and I think I’d agree with that, I have rarely (if at all) seen a method with > 20 lines of code that couldn’t be refactored.

Personally I can’t really see much benefit of the LOC for the whole app / namespace etc, unless you wanted to show off to your mates :)

   1: namespace NDepend_01
   2: {
   3:     using System;
   4:  
   5:     public static class SimpleClass
   6:     {
   7:         public static T Add<T>(T first, T second)
   8:         {
   9:             return (dynamic) first + second;            
  10:         }
  11:         
  12:         public static T Subtract<T>(T first, T second)
  13:         {
  14:             return (dynamic) first - second;
  15:         }
  16:  
  17:         public static void IfLessThan(dynamic t1, dynamic t2){
  18:             if(t1 < t2)
  19:                 throw new ArgumentException();
  20:         }
  21:  
  22:         public static void IfLessThan(DateTime t1, DateTime t2){
  23:             if(t1 < t2)
  24:                 throw new ArgumentException();
  25:         }
  26:  
  27:         public static void IfLessThan(int t1, int t2){
  28:             if(t1 < t2)
  29:                 throw new ArgumentException();
  30:         }
  31:  
  32:         public static void DoSomething()
  33:         {
  34:             Console.WriteLine(Add(1, 2));
  35:             Console.WriteLine(Add(2.1, 4.5));
  36:             Console.WriteLine(Add("begin", "end"));
  37:  
  38:             Console.WriteLine(Subtract(1, 2));
  39:             Console.WriteLine(Subtract(2.1, 4.5));
  40:         }
  41:     }
  42: }

Ok, so this is the code I’ve used, I’ll be adding comments etc to see how the metrics change, but here it is for now..

image I’ve only highlighted the ‘DoSomething()’ method, if you look at the summary, you can see the ‘# lines of code (LOC)’ metric says ‘5’. So clearly the LOC for a method ignores the signature, the open / close curly braces and the spaces. It also states (though you can’t see it in that shot) that the LOC for ‘IfLessThan’ is 2, which it is… But I wonder, if I make ‘IfLessThan’ like so:

public static void IfLessThan(dynamic t1, dynamic t2){
    if(t1 < t2) throw new ArgumentException();
}

Will it only say 1?

image

Nope!

Still says 2, which is good, as that’s logically what we have…

 

 

NbLinesOfComment / PercentageComment

Ahh the divisor of many a team – one guy is super verbose, another is seemingly unaware comments can be included let alone that they should. Neither extreme is great (in my opinion) as at some point the code will change and the changer will either not be bothered to update the comments, or the code will lose the ease of readability the original developer developed (yes, I am aware that sentence is poorly written).

Anyhews, NDepend guidance is that <20% comments should have more, >40% is probably too much. Comments are a tricky beast, any comment is really only good if it’s kept up to date. I personally think xml commenting for public methods is a must, and this metric doesn’t really give me that (just point out, I may be able to do that via the Code Query Language (CQL), but I’m just starting out here).

In my example I have zero comments, and that’s what all the metrics show… So let’s add some, ‘Add’ now becomes:

/// <summary>Adds an instance of one type to another instance of the same type.</summary>
/// <typeparam name="T">The <see cref="Type"/> to add.</typeparam>
/// <param name="first">The parameter being added to.</param>
/// <param name="second">The parameter added to <paramref name="first"/>.</param>
/// <returns><paramref name="first"/> + <paramref name="second"/></returns>
public static T Add<T>(T first, T second)
{
    //Adds 1 to another
    return (dynamic) first + second;            
}

What do we get?

image Percentage comment = 50%, so – we’re not taking into account the XML comments at the top, which (on reflection) is really what I’d expect. The overall stats (for the type) does show the XML comments, but no diff between XML and normal code comments.

NbILInstructions

We all know our .NET code (be it C#, VB, F# etc) compiles to IL code, some of us even disassemble our dlls to look at the code (of course some don’t!), but we rarely check on the size of the IL, and some might say – why bother? I guess that the IL is indicative of the complexity of the code. You may only have one LOC in your app, but it could be a seriously complicated line – one that expands to 20/30 lines of IL (maybe more, likely less). Apparently you should expect ~ 7 lines of IL for one line of code, methods with > 100 IL lines are probably complicated beasts.

I have 3 overloads for the IfLessThan method, one that takes int, one that takes DateTime and one that takes 'dynamic’. The actual LOC for each of these is 2, but the IL code? Wowsers! For the int and DateTime versions – we get 12 IL Instructions, which is 6 per LOC (near the ol’ 7 per LOC magic number), but the dynamic version has a wopping 65 lines of IL ~ 32 IL instructions per LOC… ouch!

image

image Just goes to show, those features which look like small changes in code can have big IL changes!

NbAssemblies / NbNamespaces / NbTypes

Counting the number of assemblies, namespaces and types in your code – good for a ‘Code’ Top Trumps?

NbMethods / NbFields

Large numbers of methods in a type could potentially prove complicated to manage, more than 20 is the recommendation, I guess this comes down to what the type does. Meh. Same deal with fields, (again 20 seen as a good limit), depends on you as to how you deal with this.

NDepend is giving me ‘6’ fields for the overall assembly, which I find curious as there are no fields declared, I presume it’s treating the methods as a field… Easy enough to test, remove a method, see if it goes down… No, it doesn’t. hmm where are the fields? I’ll ask the guys who wrote it and update this post (or at least explain it in the next post)…

PercentageCoverage

Unfortunately I can’t test this at the moment, but let’s face it, it’s one of the more obvious metrics. The closer to 100% the better – or is it? Does 100% coverage = 100% of cases covered? I suspect not, though not really a good time to discuss here.

 

 

BIIIIG post… I’m gonna look at hitting the other metrics next, (not sure which – type, method etc) and work my way up to the assembly metrics later.. I realise that a lot of this is basic sense, but – well – lets face it you didn’t need to read this far :) The other metrics are the more complex metrics (well, some) cyclomatic complexity etc, so I’ll probably do those in shorter bursts…

Bye then!

Print | posted @ Friday, August 20, 2010 5:22 AM

Comments on this entry:

No comments posted yet.

Post A Comment
Title:
Name:
Email:
Comment:
Verification: