Visual Studio 2010–New and little-know features–Part 2–Code Metrics


carpenterruler

Table of Contents for this series.

Code Metrics in Visual Studio

What is it?

One of the really nice features that shipped with Visual Studio 2010 Premium and Ultimate is the Code Metrics tooling. This tooling has been in the Visual Studio product line since Visual Studio Team System 2008 – Developer Edition  For those not familiar with the term:

“Code metrics is a set of software measures that provide developers better insight into the code they are developing. By taking advantage of code metrics, developers can understand which types and/or methods should be reworked or more thoroughly tested. Development teams can identify potential risks, understand the current state of a project, and track progress during software development.”     
                                                       – Visual Studio 2010 Code Metrics page on MSDN

From a Visual Studio perspective, the code metrics provided are Maintainability Index, Cyclomatic Complexity, Depth of Inheritance, Class Coupling and Lines of Code

Supported Visual Studio Versions:

  • Visual Studio Team System 2008 – Developer Edition
  • Visual Studio 2010 Premium
  • Visual Studio 2010 Ultimate
  • Visual Studio 2012 [aka VS 11] Premium
  • Visual Studio 2012 [aka VS 11] Ultimate

How do I get these metrics?

These metrics can be triggered by opening a project or solution in a supported version of Visual Studio and using the Analyze | Calculate Code Metrics for [current project name | Solution]. Also see How to: Generate Code Metrics Data on MSDN.

SNAGHTMLa32874d

          Figure 1 – Trigger Code Metrics by using the Analyze | Calculate Code Metrics menu item

I’m not going to go too an in-depth treatise on each of the metrics, but I will describe how each is useful by itself and also within the whole.  I’ll also provide deeper links if you’d like some stimulating bed-time reading.


Lines of Code:

What is it?

The Lines of Code metric describes the approximate lines of active code in a method or class.  The calculation is based on the IL code and not the text version of the code. Since it is based on IL, comments and whitespace are not counted.  The compiler may also reduce the number of lines in the IL due to compiler optimizations.

What do I do with it?

A high value may indicate a method or class that is doing too many things and violating the Single Responsibility Principle. This code may be a candidate for refactoring into multiple, smaller units of code.  This metric by itself is not the best indicator of code quality.  You must use this along with other metrics, like Cyclomatic Complexity and Class Coupling to make a final determination.

More information:


Class Coupling

What is it?

One can state that any “…two objects are coupled if and only if at least one of them acts upon the other”1.  Class coupling measure the number of classes this method relies upon.  This could be through parameters, local variables, return types, method calls, generics and a host of other mechanisms.

What do I do with it?

The higher the value the more a class or method can be affected by code changes within other parts of the system.  The more classes you rely upon, the more opportunities for your behavior to change due to factors outside of your control. I call this the “blast radius of change”.  The higher the class coupling value, the more likely this method will be affected by other edits and the more testing you have to do to ensure correct functionality after each change.

Classes with a high value are also harder to reuse in other areas or applications since you have to bring along all of the classes that you depend upon.

More information:


Depth if Inheritance:

What is it?

In OO design, we use classes to model the system.  These classes are defined in a hierarchy.  In the .Net framework, all classes ultimately derive from a single parent called Object. The Object class is the root of the inheritance tree. Depth of Inheritance measures the distance the measured class is from it’s root ancestor.  So if I create a new class Vehicle that doesn’t inherit from anything but Object , my Depth of Inheritance is zero because I’m directly on top of Object.  If I then create a class Bicycle that inherits from Vehicle, Bicycle’s Depth of Inheritance metric is 1 since it is one ancestor away from Object.

What do I do with it?

When looking at this metric you have to think about how it affects your code.  In the example above, my Bicycle class could be affected by changes directly within its code.  It could also be affected by changes to Vehicle’s code.  So every time you inherit from another class, you increase the risk that your behavior will change due to changes in the inherited class or one of the classes it inherits from.

The higher the value in this metric the more difficult it is to understand exactly what the code does since any method’s behavior can be defined/redefined in any of the class’ ancestors.  It is also more difficult to fined exactly where a behavior is defined/redefined in the inheritance tree.

More information:


Cyclomatic Complexity:

What is it?

This metric is one of the least understood for most people.  It’s got a funny name that isn’t really simple to understand, unlike Lines of Code or Depth of Inheritance.

This metric is basically the number of decisions that are made within our source code.  Another way to put it is to say that it is the number of distinct paths through a given piece of code.

What do I do with it?

Given these definitions, we can now understand that a lower number is better than a higher one since it is easier for us to keep a smaller set of logic in our head than a larger set. This also leads to fewer errors because we didn’t completely understand what the code was doing prior to making our changes.

You should look at the average value of the methods in a given class and compare the higher values to those of the rest of the class.  If any given method is significantly higher than its neighbors then it is probably somewhere you should investigate for refactoring.

You should also set an upper limit on what is acceptable complexity in your codebase.  I have seen references to a value of 10 being a good “max” value and I can understand why.  A method that has more than 10 decisions within it becomes difficult to keep straight while coding and therefore would be more likely to have errors introduced during maintenance.

You may also want to take the Lines of Code metric into account as well. 

  • Methods that have high line counts and high Cyclomatic Complexity tend to have the lowest reliability in the system. 
  • Methods that have low line counts but high Cyclomatic Complexity are generally less reliable and harder to maintain because the code is usually terse.

More information:


Maintainability Index:

What is it?

This metric describes the overall maintainability of the system reviewed.  It is based on a formula that returns a value between 0 and 100 that describes the overall maintainability of the code base and is based (in part) on the other 4 metrics described here.

A higher value indicates a system that is easier to maintain which should help to reduce the introduction of bugs during the maintenance cycle. Along with a numeric value, this column also presents a “stoplight” indicator to give the developer a quick indication of trouble spots in the code base. The breakdown of the stoplight values are:

  • 0-9 = Red
  • 10-19 = Yellow
  • 20-100 = Green

SNAGHTML732efef

What do I do with it?

I tend to use this metric in a couple of different ways depending on my current needs.

  1. If I have to make modifications to a code base that I am unfamiliar with, I will use this metric to find the methods that I should be wary of.  Low maintainability means that it may be an overly complex or large method that is prone to logic errors.
  2. If I have an opportunity to refactor my code I will use this metric to target the code most in need of refactoring. This is an area that can use unit tests to help mitigate the risk inherent in refactoring complex code.

More information:

 

Table of Contents for this series.