Code Metrics: An Introduction to Visual NDepend
In the second half of April I got an Email from Patrick Smacchia. I was very surprised, I mean, I’ve follow Patrick’s blog for some time and I though “this guy is really smart” so I was excited about getting in touch with him (starting from his side by the way), and while I’ve heard of his product Visual NDepend, I’ve actually never tried it and neither paid too much attention about the product itself. It was embarrassing because he was kind enough to offer me a Pro License to try it, evaluate it and see if it was functional and useful for me.
I said “Yes! Of course!”. Then started doing some research and reading and found about what was it for and how could I use it. Around that time, Scott Hanselman did his Hanselminutes Podcast 163 - Software Metrics with Patrick Smacchia so I was very excited and listened to the show about 3 times (sound was not that good, I think Patrick was not on a good phone line) and really got me into the code metrics thing.
So, here are my initial thoughts about Visual NDepend. I must say up front that I’m far from being an expert and that I have called this post “Introduction to Visual NDepend” for the same reason. I expect to use the tool more and be able to express myself in a more proper way in the near future.
I will start with the text from the Visual NDepend website:
NDepend is a tool that simplifies managing a complex .NET code base. Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code.
The result is better communication, improved quality, easier maintenance and faster development.
Also, from the website, here are the list of metrics NDepend can generate for you:
NbLinesOfCode, NbLinesOfComment, PercentageComment, NbILInstructions, NbAssemblies, NbNamespaces, NbTypes, NbMethods, NbFields, PercentageCoverage, NbLinesOfCodeCovered, NbLinesOfCodeNotCovered
NbLinesOfCode, NbLinesOfComment, PercentageComment, NbILInstructions, NbNamespaces, NbTypes, NbMethods, NbFields, Assembly level, Afferent coupling (Ca), Efferent coupling (Ce), Relational Cohesion(H), Instability (I), Abstractness (A), Distance from main sequence (D), PercentageCoverage, NbLinesOfCodeCovered, NbLinesOfCodeNotCovered
NbLinesOfCode, NbLinesOfComment, PercentageComment, NbILInstructions, NbTypes, NbMethods, NbFields, Namespace level, Afferent coupling at namespace level (NamespaceCa), Efferent coupling at namespace level (NamespaceCe), PercentageCoverage, NbLinesOfCodeCovered, NbLinesOfCodeNotCovered
NbLinesOfCode, NbLinesOfComment, PercentageComment, NbILInstructions, NbMethods, NbFields, NbInterfacesImplemented, Type level, Type rank, Afferent coupling at type level (TypeCa), Efferent coupling at type level (TypeCe), Lack of Cohesion Of Methods (LCOM), Lack of Cohesion Of Methods Henderson-Sellers (LCOM HS), Code Source Cyclomatic Complexity, IL Cyclomatic Complexity (ILCC), Size of instance, Association Between Class (ABC) Number of Children (NOC), Depth of Inheritance Tree (DIT), PercentageCoverage, NbLinesOfCodeCovered, NbLinesOfCodeNotCovered
NbLinesOfCode, NbLinesOfComment, PercentageComment, NbILInstructions, Method level, Method rank, Afferent coupling at method level (MethodCa), Efferent coupling at method level (MethodCe), Code Source Cyclomatic Complexity, IL Cyclomatic Complexity (ILCC), IL Nesting Depth, NbParameters, NbVariables, NbOverloads, PercentageCoverage, NbLinesOfCodeCovered, NbLinesOfCodeNotCovered, PercentageBranchCoverage
Size of instance, Afferent coupling at field level (FieldCa)
Now, what I did was start with a small project I have and run the tool to see what I could get with the default settings. The end result was stunning. Once you select the solution to work with, you get the following screen that shows all the projects in the solution and all the libraries it will analyze:
This is the analysis it will perform (which is of course customizable):
And the reporting options:
After running the analysis we get several results, for example:
Application Metrics
- Number of IL instructions: 13081
- Number of lines of code: 1952
- Number of lines of comment: 1184
- Percentage comment: 37
- Number of assemblies: 7
- Number of classes: 58
- Number of types: 60
- Number of abstract classes: 0
- Number of interfaces: 0
- Number of value types: 0
- Number of exception classes: 0
- Number of attribute classes: 0
- Number of delegate classes: 4
- Number of enumerations classes: 2
- Number of generic type definitions: 0
- Number of generic method definitions: 0
- Percentage of public types: 98.33%
- Percentage of public methods: 72.07%
- Percentage of classes with at least one public field: 0%
The numbers are interesting, but up to this point too general. So following with the results report we get more information:
The following view is kind of weird, but it shows graphically the size of the assemblies with its methods:
Also, the dependencies of the assemblies (in large projects this view is very important):
Assemblies build order
- CEO.PublicSite.DataEntities
- CEO.PublicSite.DataAccess
- CEO.PublicSite.BusinessLogic
- CEO.PublicSite.BusinessFacade
- CEO.PublicSite.WebControls
- CEO.PublicSite.Web
- CEO.PublicSite.Utilities
NDepend information and warnings
07/04/2009 21:46:04 Begin analysis with NDepend v2.12.1.3123
07/04/2009 21:46:04 Retrieve dependencies of your application.
Don't load a previous analysis to compare with.
Assemblies loaded from {C:\Windows\Microsoft.NET\Framework\v2.0.50727} mscorlib.dll v2.0.0.0 System.Data.dll v2.0.0.0 System.Configuration.dll v2.0.0.0 System.Xml.dll v2.0.0.0 System.dll v2.0.0.0 System.Web.dll v2.0.0.0
Assemblies loaded from {C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5} System.Web.Extensions.dll v3.5.0.0
Assemblies loaded from {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.Web\bin} CEO.PublicSite.BusinessFacade.dll v1.0.0.0 CEO.PublicSite.BusinessLogic.dll v1.0.0.0 CEO.PublicSite.Web.dll v1.0.0.0 CEO.PublicSite.DataAccess.dll v1.0.0.0 CEO.PublicSite.Utilities.dll v1.0.0.0 CEO.PublicSite.WebControls.dll v1.0.0.0 CEO.PublicSite.DataEntities.dll v1.0.0.0 Telerik.Web.UI.dll v2009.1.527.35
71 source files parsed ; all source files found ; all source files in-sync with PDB
0 CQL constraint has been extracted from code.
No dependency cycle detected in assemblies referencement graph.
07/04/2009 21:46:12 Analyse dependencies of your application.
07/04/2009 21:46:13 Building the report (standard).
WARNING: Assembly {CEO.PublicSite.Utilities} doesn't contain any type.
WARNING: No application or tier assembly found in directory {C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.BusinessFacade\bin\Debug}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.BusinessLogic\bin\Debug}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.DataEntities\bin\Debug}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.DataAccess\bin\Debug}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.Utilities\bin\Debug}
WARNING: No application or tier assembly found in directory {C:\Users\jrguay\Documents\Visual Studio 2008\Websites\CEO.PublicSite\CEO.PublicSite.WebControls\bin\Debug}
The result of the CQL Queries and constraints are quite large so I’ll include only one:
WARNING: The following CQL constraint is not satisfied. 10 methods on 895 tested match the condition. --> Group {Code Quality}
// <Name>Quick summary of methods to refactor</Name>
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
AND
// 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".
HasAttribute "OPTIONAL:NDepend.CQL.GeneratedAttribute")
And lastly in the report, some Type metrics:
Conclusions
- The results are quite impressive. The tool can give you a lot of metrics in different levels of the solution.
- The information about assemblies metrics can give you a very detailed idea in how the assembly is built, how big is it, how are the classes and methods constructed, how they are related to other assemblies and how the types are related to other types within/outside the assembly, and more.
- One of the most important views is the assembly dependencies, it tells you how each assembly is related to other assemblies by showing for every assembly which assemblies it depends on and which assemblies are referenced by.
- The CQL queries gives you information about the quality of the code based on metrics definitions. (this definitions can be customized).
- The type metrics provide detailed information about the types in the assemblies at different levels such as lines of code, lines of IL code, relation with other types, etc.
- This first review shows me a lot of power in the analysis and reporting capabilities of Visual NDepend (not to mention I didn’t customize any of the default settings).
I will continue to use the tool and write a second review of the integration with Visual Studio.
Thanks.