Monday, January 25, 2010

NDepend

Patrick Smacchia kindly gave me the opportunity to use and evaluate his NDepend product.  NDepend is a static analysis tool meaning it can provides insight and guidance about one's work by inspecting assemblies and source code.  It identifies things like classes which may be better as structures by looking at the size of an instance of the class, the number of children, and the depth of inheritance.  It also graphically displays assembly dependencies and can do comparisons of an application between releases.  All in all a very cool tool!


First I started up NDepend to run it over a WPF desktop application I worked on in 2008.  I started by creating a new project.  It was very slick the new project open a .sln file to determine the assemblies to analyze.  NDepend understands there are application assemblies (assemblies compiled from the user's code) and tier assemblies (generally compiled references).  This picture shows what I mean.  After taking just 15 seconds to analyze 353,899 IL instructions NDepend showed an interactive view displaying many different views of the codebase at once which were all linked together, so if I drilled into something in one view or hovered over it there would be an effect in the other windows.  Being a noob this was a bit much for me and I opted to view a static HTML report.  The report didn't look so great in Chrome or FireFox but looked fine in IE8.  I read through the 50 page report awash in information.  I wish I had used the tool in 2008 to focus some of our refactoring efforts.  There are a lot of fantastic queries out of the box showing things that are blatantly wrong with the code we wrote.  Speaking of queries, NDepend has a very cool Code Query Language (CQL) one can use to write queries which throw errors or warnings during a build process.  NDepend comes with many queries out of the box which you can run or use as examples.  


Here is a query provided in the NDepend install showing types that could potentially be marked sealed:
// <Name>Class with no descendant should be sealed if possible</Name>
WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE
  
IsClass AND
  
NbChildren ==0 AND
  
!IsSealed AND
  
!IsStatic


Here is another query provided in the NDepend install showing classes that might be better as structures:

// <Name>Classes that are candidate to be turned into Structures</Name>
WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE 
  IsClass AND
  SizeOfInst <= 16 AND    // Structure instance must not be too big, else it degrades performance.
  NbChildren == 0 AND     // Must not have children
  DepthOfInheritance == 1 // Must derive directly from System.Object
  // AND IsSealed    : You might want to add this condition to restreint the set.
  // AND IsImmutable : Structures should be immutable type.
  // AND !IsPublic   : You might want to add this condition if you are developping a framework
  //                   with classes that are intended to be sub-classed by your clients.


These are two examples of things I would like to know but wouldn't like to take the effort to figure out.  NDepend makes time consuming code analysis tasks simple and shareable by providing the Code Query Language.

A couple months later I decided to use NDepend to analyze the ASP.NET solution I worked on in 2009.  I precompiled the application as recommended in the NDepend FAQ and browsed to that output instead of using the ASP.NET solution file to begin my analysis.  Unfortunately this project's code quality wasn't as high as the other project and there were 491,298 IL instructions for NDepend to analyze, although it only took 13 seconds. :)  Again I mostly skipped the UI and dove into the 492 page report.  Being a web app, some of the assemblies have funky names like App_Web_c55buezi which makes some items in the report harder to consume than the human friendly names from the desktop project.  Unfortunately I will not be working on this codebase anymore and did not have significant ownership of it so I didn't diligently read up all the goodness NDepend was giving me access to.

My lesson learned is that I need to run this fabulous tool over code I'm actively working on so I can take advantage of it and learn like I've learned from FxCop.  This tool is great because it has something for everyone.  From rules with specific recommendations on what to fix to strategic insights into your dependency structure.