The corollary to the adage "You can't manage what you don't measure" is "What you choose to measure will control where you focus and what you improve". Software metrics have been proposed for measuring many, many different aspects of an existing body of source code. Some of these metrics, such as Lines of Code and Comment Ratio, have a fairly obvious meaning and use; most are less self-explanatory. The following are some of the most significant and useful software metrics of the latter type.
McCabe Complexity Metrics
In his paper A Complexity Measure, IEEE Transactions on Software Engineering, Dec 1976, Thomas McCabe defined a set of metrics to characterize the complexity of a software module's internal control flow logic. Glen Myers suggested a revision to the calculation in An Extension to the Cyclomatic Measure of Program Complexity, SIGPLAN Notices, Oct 1977.
Cyclomatic Complexity (v(G))
Essential Complexity (ev(G))
- Measures - The complexity of a module's decision structure.
- Calculation - Count of linearly independent paths through a function or set of functions. An Imagix 4D option controls whether the original McCabe calculation or the Myers revision is used.
- Use - Higher cyclomatic complexities correlate with greater testing and maintenance requirements. Complexities above 20 also correspond to higher error rates.
- Extensions - For collections of functions (classes, files and directories), the complexities of the individual functions they contain are used to determine the Total, Average and Maximum cyclomatic complexity. Decision Density is the cyclomatic complexity per line of source code.
Further descriptions of these metrics, including examples and explanations of their implications for testing, are available in Structured Testing: A Testing Methodology Using the Cyclomatic Complexity Metric.
- Measures - The degree to which a module contains unstructured constructs.
- Calculation - Cyclomatic complexity of a module's remaining decision structure, once it has been reduced by fusing primitive, well-structured regions. In Imagix 4D, an option controls whether return statements are treated as structured or unstructured constructs.
- Use - This metric measures the degree of structuredness and the quality of the code. It is used to predict maintenance effort and to help in the modularization process.
- Extensions - Essential Density is the ratio of essential complexity to the overall cyclomatic complexity, indicating what portion of the cyclomatic complexity is a result of the module's structure.
Woodward, Hennell and Hedley Knots Metric
Following McCabe's publication of the Cyclomatic Complexity metric, some in the field, such as Myers and Hansen, continued and refined McCabe's focus on token counts. Others, including Woodward et al, looked to measure the internal structure of a module. In 1979, the Knots metrics was published as A Measure of Control Flow Complexity in Program Text
- Measures - The complexity and unstructuredness of a module's control flow.
- Calculation - Count of the intersections among the control flow paths through a function.
- Use - In pointing out areas of higher unstructuredness and the resultant challenges in understanding and testing, higher knots values may suggest the need to reorder or restructure, rather than just repartition, a module.
Welker Maintainability Index
The combination of multiple metrics into a single indicator of relative maintainability of a body of source code was originally defined by Oman and Hagemeister. Empirical studies by others led to a series of variants, and calculation of the maintainability index evolved over several years. Welker's 1995 proposal with Oman has evolved slightly into today's most widely used definition.
Maintainability Index (MI)
- Measures - The relative maintainability of a body of source code.
- Calculation - Complex, experience-based composite that combines measurements of the McCabe cyclomatic complexity, Halstead volume, lines of code and the comment density of the code.
- Use - Higher maintenance index values correspond to lower maintenance efforts. Under the standard Welker definition, software having no maintenance burden has an index of 171. Some variants normalize this to 100.
Chidamber and Kemerer Object Oriented Metrics
As a way to characterize the "object-orientedness" of a design, a suite of metrics was proposed by Shyam Chidamber and Chris Kemerer in their 1994 paper, A Metrics Suite for Object-Oriented Design. The six metrics are:
Weighted Methods Per Class (WMC)
Depth of Inheritance Tree (DIT)
- Measures - Some aspect of the scope of the methods making up a class.
- Calculation - Summation of the weighted methods of the class. Chidamber and Kemerer do not specify what weighting to apply to each method. Imagix 4D applies each module's Cyclomatic Complexity as the weight, and thus WMC becomes a measure of the complexity of the overall decision structure within the methods making up a class. Applying a unitary weight would result in WMC reflecting a simple method count for the class; in Imagix 4D, this count is available as the Number of Member Methods.
- Use - Higher WMC values correlate with increased development, testing and maintenance efforts. As a result of inheritance, the testing and maintenance efforts for the derived classes also increase as a result of higher WMC for a base class.
Number of Children (NOC)
- Measures - The inheritance upon which a class was built.
- Calculation - Maximum of number of levels in each of the class's inheritance paths.
- Use - While reuse potential goes up with the number of ancestors, so does design complexity, due to more methods and classes being involved. Studies have found that higher DIT counts correspond with greater error density and lower quality.
Coupling Between Object Classes (CBO)
- Measures - How widely a class is reused to build other classes.
- Calculation - Count of the classes that are directly derived from a specified class.
- Use - Larger NOC counts point to greater reuse of the class, and with it a need for increased testing. High NOCs may also flag a misuse of subclassing.
Response For a Class (RFC)
- Measures - How dependent a class is on other classes.
- Calculation - Count of the external classes whose members are called, set, read or used as types by members of the current class. In Imagix 4D, options control whether inherited members are included as part of the current class when calculating coupling and whether uses from external classes is included along with uses into external classes.
- Use - Excessive coupling limits the availability of a class for reuse, and also results in greater testing and maintenance efforts.
Lack of Cohesion in Methods (LCOM)
- Measures - The overall complexity of the calling hierarchy of the methods making up a class.
- Calculation - Count of the methods of a class and the methods that they directly call.
- Use - Larger RFC counts correlate with increased testing requirements.
- Measures - How widely member variables are used for sharing data between member functions.
- Calculation - Count of the pairs of class methods that don't access any of the same class variables reduced by the number of pairs that do. In Imagix 4D, an option controls whether inherited member variables are considered to be in the set of class variables.
- Alternatives - A second Imagix 4D option enables the use of alternative Cohesion calculations. Li and Henry proposed an alternative measure, re-defined by Hitz and Montazeri, that counts the number of disconnected method / variable groupings. A third measure, from Henderson-Sellers, indicates how widely a class's member functions access its member variables, without consideration of which specific functions and variables are involved.
- Use - A higher LCOM indicates lower cohesion. This correlates with weaker encapsulation, and is an indicator that the class is a candidate for disaggregation into subclasses.
Halstead Complexity Metrics
A pioneer in the field of software metrics, Maurice Halstead combined information science, psychology and his extensive experience to create a set of what he called Software Science Metrics. Unlike the McCabe complexity metrics, the Halstead metrics do not distinguish between conditional statements and straight-line statements. All the metrics are determined through mathematical relationships of four measures - distinct operators (n1), distinct operands (n2), total operators (N1) and total operands (N2).
Program Vocabulary (n)
Program Length (N)
- Measures - The breadth of operators and operands appearing in the program.
- Calculation - n = n1 + n2
Program Volume (V)
- Measures - The total usage of all operators and all operands appearing in the program.
- Calculation - N = N1 + N2
Program Difficulty (D)
- Measures - The size of information used to specify the program.
- Calculation - V = N * log2(n)
Intelligent Content (I)
- Measures - The ease of reading the program, also implies how succienctly the program was written.
- Calculation - D = (n1 / 2) * (N2 / n2)
- Extensions - Program Level is the inverse of Program Difficulty (L = 1 / D).
Mental Effort (E)
- Measures - The information content of the program.
- Calculation - I = (2 * n2 / (n1 * N2)) * V
- Measures - The effort in mental disciminations required to implement the program from the underlying algorithm.
- Calculation - E = D * V