StudioTools: Code Metrics
This view adds a variety of commonly used code metrics to Visual Studio.
By sorting and filter you can find problem areas in your code such
as overly complex classes or methods with too many parameters.
Viewing solution metrics
The Code Metrics view is accessed through the StudioTools menu. Click the
refresh button in the Code Metrics toolbar to calculate metrics for your solution.
This will essentially do a debug build and analyze the compiled projects.
Code Metrics
The report shows each method in your solution and the various metrics for each one. You can click
to navigate to any of the displayed metrics
For most metrics,
an aggregate or average value is shown at the type, namespace, and assembly level. Some metrics (like number of parameters) only make sense at the method level however. The various metrics and their behaviors are
described in the text that follows.
Sorting
As you might expect, you can click on any column to sort by that metric. For instance, you can find the
least maintainable code by clicking on the Maintainability column to sort the worst methods to the top.
Note that sorting happens at each level of the hierarchy, as well as within. Click again to reverse the sort
order.
Filtering
You can use the filter bar to select which namespaces and assemblies you want to
include in your metrics report. Just click on the filter bar, then check (or uncheck)
the appropriate items. These will be remembered between runs. For instance, you may not
want to included your unit test assemblies or third party code in your report.
Grouping
Similarly you can use the grouping functions on the tool bar to group the displayed results
by assembly, namespace, type, or any combination of the above. If you turn off all of the grouping
you will see only methods.
Export to XML
The export to XML button will save off your currently displayed metrics to an XML file. You can use this
to generate reports or track progress over time. If you are using the filtering function, this will effect
the output of the report.
The Metrics
The following metrics are visible through Code Metrics. You can right click
in the Code Metrics window to select which ones are shown.
Coupling
Coupling indicates the distinct number of dependencies a
an element has on other types. Coupling is thus a
measure of how stand alone a program element can be.
Coupling excludes primitives types such as int, string, and object.
For methods, this counts the distinct number of types
a method uses in its code body, including parameters,
return value, variables, and calls.
For types, this counts the distinct number of types
used in all constituent methods, as well as the distinct types
used in fields.
Rolling up from types to namespaces, and then to assemblies is
a combined distinct count of all types and methods used. This is
different than a sum to avoid double counting.
Cyclomatic Complexity
Cyclomatic complexity represents the number of paths
possible through code by looking at branches and conditions.
More paths indicates a larger test surface and makes
code harder to understand.
This is computed by looking to the emitted MSIL instructions
and counting the number of different branch and jump instructions
including conditionals, breaks, returns, and paths through exception
handlers. There is always at least one path through the code
for any method with a body, and additional branches and conditions
add more paths.
This method of counting analyzes your code based on the actual
generated assembly, not just your source and so gives you a
more thorough scoring of how the complex the code is to
the .NET runtime.
Types, namespaces, and assemblies average the complexity of
their constituent methods.
Executable Lines of Code (LoC)
Executable lines of code are computed by reading
your compiled assemblies and .pdb debug files to find
those lines that .NET considers to be real, executable code.
This is a more accurate metric than simply source lines, as it
tells you what is going to run. At first glance however, some counts may
not appear correct because what looks like several lines to us is
really a single executable statement by the time the compiler sees it.
Number of Parameters
Number of parameters for a method, not including the
return value. A large number of parameters makes methods difficult to
use and encourages errors via passing nulls in place of
proper parameter values.
Inheritance Depth
Inheritance depth counts how deep a type is within the inheritance
tree All objects initially inherit from System.Object, which is defined
to have a depth of 0. Each use of inheritance into a new sub type
increments this depth by one.
Deep inheritance trees can lead to complex code that requires understanding
multiple base types in multiple files to understand and work with a type.
Depth of inheritance is defined only one types, not methods, namespaces,
or assemblies.
Number of Instructions
Number of instructions counts the amount of MSIL generated
for your methods. NOP instructions are excluded from the count.
Instructions are the fundamental unit of processing for the
.NET runtime. Large numbers of instructions in a method take
longer to run through the JIT compiler and increase the
size of your assembly on disk and in memory.
Maintainability Index
Maintainability combines line count, complexity, and
code volume to provide a synthetic score between 0 and 100
that indicates how easy code is to maintain.
Maintainability uses Halstead metrics, which require the
definition of operators and operands.
Operators are defined to be any MSIL instruction except nop.
Call instructions count the target method as the operator,
and contribute the target method's type as an operand.
New object instructions count the target type as an operator
and an operand.
Operands are defined to be any type used in a field, parameter,
or variable.
For namespaces and assemblies, the average complexity, volume,
and lines of code are used to roll up maintainability. The
formula for maintainability is logarithmic, so don't expect
the numbers to add up like sums.
You can think of the score as a percentage grade, numbers
closer to 100 are better.
Number of Variables
Number of variables counts the variables used
in your methods and fields used in your types.
Type level variables use sums all method variables
with the fields in the type.
Large numbers of variables make methods more complex
and testing more difficult as the total number of potential
state combinations increases with each variable.