Tuesday, October 13, 2009

Visual Studio Team System (VSTS) 2008 Code Metrics & Complexity

In today's discussion, let us discuss about different code metrics provided by VSTS. How to look at different values of these code metrics? We would also be discussing about how these metrics are calculated by Visual Studio.

A metric is actually a representation of quantatively specifying the maintainability of the code. You can have an idea about the code quality by just looking at the value of desired code metric.

Available Code Metrics:
There are following code metrics available by Visual Studio Team System 2008.

1. Lines of code
2. Cyclomatic Complexity
3. Class Coupling
4. Inheritance Depth
5. Maintainability Index

Let us discuss about each of the metric in detail:

Lines of Code:
Lines of code is not only used for sizing of a software system but also to define the quality and complexity of it. If you are writing your modules as small sub-systems then it might be a better design instead of writing big classes and their methods with multiple responsibilities.

Although people might argue in the effectiveness of using line of code as a tool for software estimation and sizing but it can surely be used a tool for representing code complexity. The bigger the code block the more difficult is to develop, maintain and test it.

The metric calculation excludes comments, white spaces, braces and declarations.

Depth of Inheritance:
This is the only purely class level metric available of the list. This specifies the number of levels of inheritance to the class under consideration starting from System.Object. (Note: All classes are implicitly inherited from System.Object). Numerically it is equal to number of classes between the class and System.Object plus one.

As you might have imagined, the smaller values would be better. This is because of complexities that come with adding layers to the inheritance hierarchy.

Class Coupling:
This is one of the object oriented code metric in VSTS. This is also based on industry standard code metric. It is equal to number of distinct classes that your class depends upon.

As we know from a long time “Our code should have low coupling and high adhesion”, so this metric is expected to have low value.

This metric can also be specified at method level. In that case, it would show the number of distinct classes this method is using. This doesn’t include the class that this method is part of. The metric for a class is the number of distinct classes used anywhere in the class. For the instance / class level variables use, it would show as coupled with the constructors of the class.

Though some people have this misunderstanding that Visual Studio Team System does not provide information, about classes of other assemblies, being used by any particular class, but this seems to be far from truth in practice.

You should remember that class level metric is not the summation of the metric values for all its methods. As I see it, this may be because of two reasons: First, the methods may be using some similar classes and for the calculation of metric only distinct class coupling is considered. Second, as we have seen the class level variables are shown as coupled with all the constructors, which is also repetitive for all constructors. The same discussion is true for the metric calculation for modules and namespaces.

Cyclomatic Complexity:
This metric was proposed by McCabe in 1976. The metric value is calculated by creating a control flow graph of the method. Its formula for a single connected graph may be presented as follows:

Cyclomatic Complexity = The number of edges - The number of nodes + 1

The value of cyclomatic complexity is basically the number of linearly independent paths through the source code. As you might have guessed, this might also be equal to the number of test cases for the module. The value of complexity should be controlled during design and development of modules. If a module has a complexity more than a specific value (generally 10 or 15), it is recommended to be divided into simpler modules. But this restriction might be relaxed if needed. It is recommended to write explanation under such cases of relaxations.

This metric may be calculated by assigning exact numerical value to various programming constructs e.g. loop (like for and while), branching (like if and switch).The lower the value the more maintainable, testable and understandable the code is.

The metric value of Cyclomatic complexity of a class is the sum of Cyclomatic Complexity of all its methods. In the same way, the metric for a namespace is the sum of metrics of all classes within the namespace.

Maintainability Index:
Of the available metrics, this is the only metric for which higher values are considered better. The formula for maintainability index as specified on Code Analysis and Code Metrics team blog is as follows:
Maintainability Index = MAX (0, (171 - 5.2 * log2 (Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * log2(Lines of Code))*100 / 171)
This is an updated version of Maintainability index formula as developed in Carnegie Mellon University. Compared to the original formula, this formula avoids negative metric value. Like other metrics, this formula also doesn’t take comments into consideration. The possible values for this metric can lie between 0 and 100. The higher the value the more maintainable the code is.

As you can infer from the formula that lower values of Halstead Volume and Cyclomatic Complexity favors high value of Maintainability Index resulting in more maintainable code.

There are three color icons based on this metric value. They are Green, Yellow and Red.
Green: 20-100
Yellow: 10 – 19
Red: 0 - 9

Halstead Volume is one of the oldest metrics to represent code complexity. This is used in the formula to take into consideration the computational complexity of the code. This method looks at the code in the form of tokens. There are two types of tokens i.e. Operators and Operands. Its formula is as follows:

V= N * log2 n (where N (Program Length) is the sum of total number of operators and operands in the code and n (Vocabulary Size) is the sum of number of unique operators and operands)
Halstead is a comprehensive metrics. It provides various other calculations to calculate program difficulty level, effort to implement, Time to implement and approximate number of delivered bugs.

Limitations of Code Metrics in VSTS:
1. Customized metric can not be defined.
2. Calculation of code metrics cannot be set as check-in policy.

Auto Generated Code:
Modern IDEs provide us the ability to generate code easily for repetitive tasks. But we don’t want this generated code to be included as part of the calculation for code metrics.

Actually, this would certainly not be considered for calculating metrics if it is decorated with CompilerGeneratedAttribute available in System.Runtime.CompilerServices namespace. If a method or a class is decorated with this attribute, this would not be used for calculation of metrics.

Surely, you can use this attribute for classes / methods that you don’t want to be used for calculation.

No comments: