While we've already briefly spoken about Code Metrics when we announced it, I thought I would discuss it in a little more depth, in particular the metrics it provides.
As mentioned previously, Code Metrics is a new tool window that helps users find and act upon complex and unmaintainable areas within an application.
The following shows the results of running Code Metrics over a fictional business application:
As you can see from above, for Visual Studio 2008, we're providing five metrics. These are detailed below.
At each level, this indicates the total number of dependencies that the item has on other types. This number excludes primitive and built-in types such as Int32, String and Object. The higher this number, the more likely changes in other types will ripple though this item. A lower value at the type level can indicate candidates for possible reuse.
The following shows how coupling is calculated:
For example, as you can see above, Account is coupled to two other types, Address and Order, whereas Country is not dependent on any other type.
Depth of Inheritance
At the type level, depth of inheritance indicates the number of types that are above the type in the inheritance tree. For example, a type that derives directly from Object would have a depth of inheritance of 1. At the namespace and project level, this indicates the highest depth of inheritance of all the types contained within it. This number does not take into consideration the depth of any implemented interfaces. Deep inheritance trees can indicate an over-engineering of a problem and can increase the complexity of testing and maintaining an application.
The following shows how depth is calculated:
For example, in the above inheritance hierarchy, ListControl and Label have a depth of inheritance of 3, whereas Component has a depth of inheritance of 1.
At each level, this measures the total number of individual paths through the code. This is basically calculated by counting the number of decision points (such as if blocks, switch cases, and do, while, foreach and for loops) and adding 1. This number is also a good indication on the number of unit tests it will take to achieve full line coverage. Lower is typically better.
The following shows how complexity is calculated:
Lines of Code
At each level, this is a measure of the total number of executable lines of code. This excludes white space, comments, braces and the declarations of members, types and namespaces themselves. Lower is typically better.
The following shows how the lines are calculated:
At the member and type level, this is an index from 0 to 100 indicating the overall maintainability of the member or type. At the namespace and assembly level, this is an average of the maintainability index of all types contained within it. This index is based on several other metrics, including Halstead Volume (which factors in the number and use of operands and operators), Cyclomatic Complexity and Lines of Code. A low number indicates code that is complex and hard to maintain.
The Maintainability Index column also includes a icon that gives a quick indication as to the overall maintainability and complexity of a particular item. The following table shows the range at which an icon is shown:
Between 20 and 100 inclusive
Between 10 and 19 inclusive
Between 0 and 9 inclusive