Measurement of Software Complexity with Testwell CMT++ Testwell CMTJava
[Link]
en_software_complexity_metrics 20121025
Code Complexity Measurements
Code Complexity Measurement Tools
Testwell CMT++ Testwell CMTJava for C, C++ (and C#) for Java
[Link]
Code Complexity Measurements
Code complexity correlates with the defect rate and robustness of the application program
[Link]
Code Complexity Measurements
Code with good complexity:
contains less errors
is easier and faster to test
is easier to understand
is easier to maintain
[Link]
Code Complexity Measurements
Code complexity metrics are used to locate complex code To obtain a high quality software with low cost of testing and maintenance, the code complexity should be measured as early as possible in coding. developer can adapt his code when recommended values are exceeded.
[Link]
Code Complexity Measurements
Metrics shown by Testwell CMT++ / CMTJava:
Lines of Code metrics
McCabe Cyclomatic number
Halstead Metrics
Maintainability Index
[Link]
Lines of code metrics
[Link]
Lines of code metrics
Most traditional measures used to quantify software complexity. They are simple, easy to count, and very easy to understand. They do not, however, take into account the intelligence content and the layout of the code. Testwell CMT++ calculates the following lines-of-code metrics: LOCphy: number of physical lines LOCbl: number of blank lines (a blank line inside a comment block is considered to be a comment line) LOCpro: number of program lines (declarations, definitions, directives, and code) LOCcom: number of comment lines
[Link]
Lines of code metrics
Recommandations: Function length should be 4 to 40 program lines. A function definition contains at least a prototype, one line of code, and a pair of braces, which makes 4 lines. A function longer than 40 program lines probably implements many functions. (Exeption: Functions containing one selection statement with many branches) Decomposing them into smaler functions often decreases readability.
[Link]
Lines of code metrics
Recommandations: File length should be 4 to 400 program lines. The smallest entity that may reasonably occupy a whole source file is a function, and the minimum length of a function is 4 lines. Files longer than 400 program lines (10..40 functions) are usually too long to be understood as a whole.
[Link]
10
Lines of code metrics
Recommandations: Comments At least 30 % and at most 75 % of a file should be comments. If less than one third of a file is comments the file is either very trivial or poorly explained. If more than 75% of a file are comments, the file is not a program but a document. (Exeption: In a well-documented header file percentage of comments may sometimes exceed 75%)
[Link]
11
McCabe Cyclomatic Number
[Link]
12
McCabe Cyclomatic Number
The cyclomatic complexity v(G) has been introduced by Thomas McCabe in 1976. Measures the number of linearly-independent paths through a program module (Control Flow). The McCabe complexity is one of the more widely-accepted software metrics, it is intended to be independent of language and language format.
Considered as a broad measure of soundness and confidence for a program.
[Link]
13
McCabe Cyclomatic Number
v(G) is the number of conditional branches. v(G) = 1 for a program consisting of only sequential statements. For a single function; v(G) is one less than the number of conditional branching points in the function. The greater the cyclomatic number is the more execution paths there are through the function, and the harder it is to understand.
[Link]
14
McCabe Cyclomatic Number
How McCabe Metrics are calculated with CMT++: Increase of McCabe cyclomatic number v(G) by one: if-statement (introduces a new branch to the program) Iteration constructs such as for- and while-loops Each case ...: part in the switch-statement Each catch (...) part in a try-block Construction exprl ? expr2 : expr3.
[Link]
15
McCabe Cyclomatic Number
In CMT++ the branches generated by conditional compilation directives are also counted to v(G). (Even if conditional compilation directives do not add branches to the control flow of the executable program, they increase the complexity of the program file that the user sees and edits.) v(G) is insensitive to unconditional branches like goto-, returnand break-statements although they surely increase complexity.
[Link]
16
McCabe Cyclomatic Number
In summary, the following language constructs increase the cyclomatic number by one: if (...) case ...: || #ifdef for (...) catch (...) ? #ifndef while (...) && #if #elif
[Link]
17
McCabe Cyclomatic Number
For dynamic testing, the cyclomatic number v(G) is one of the most important complexity measures. Because the cyclomatic number describes the control flow complexity, it is obvious that modules and functions having high cyclomatic number need more test cases than modules having a lower cyclomatic number. Rule: each function should have at least as many test cases as indicated by its cyclomatic number.
[Link]
18
McCabe Cyclomatic Number
Recommandations: The cyclomatic number of a function should be less than 15. If a function has a cyclomatic number of 15, there are at least 15 (but probably more) execution paths through it. More than 15 paths are hard to identify and test. Functions containing one selection statement with many branches make up an exception. A reasonable upper limit Cyclomatic number of a file is 100.
[Link]
19
Halstead Metrics
[Link]
20
Halstead metrics
Developed by Maurice Halstead (sen.) Introduced 1977 Used and experimented extensively since that time They are one of the oldest measures of program complexity Strong indicators of code complexity. Often used as a maintenance metric.
[Link]
21
Halstead metrics
B D E L N N1 N2 n n1 n2 T V
Estimated number of bugs difficulty level, error proneness effort to implement program level program length number of operators number of operands vocabulary size (n1+n2) number of unique operators number of unique operands implementation time / time to understand volume: size of the implementation of an algorithm
[Link]
22
Halstead metrics
Halsteads metrics is based on interpreting the source code as a sequence of tokens and classifying each token to be an operator or an operand. Then is counted number of unique (distinct) operators (n1) number of unique (distinct) operands (n2) total number of operators (N1) total number of operands (N2)
All other Halstead measures are derived from these four quantities with certain fixed formulas as described later.
[Link]
23
Halstead metrics
Operands: IDENTIFIER all identifiers that are not reserved words TYPENAME TYPESPEC (type specifiers) Reserved words that specify type: bool, char, double, float, int, long, short, signed, unsigned, void. This class also includes some compiler specific nonstandard keywords. CONSTANT Character, numeric or string constants.
[Link]
24
Halstead metrics
Operators (1/2): SCSPEC (storage class specifiers) Reserved words that specify storage class: auto, extern, inlin, register, static, typedef, virtual, mtuable. TYPE_QUAL (type qualifiers) Reserved words that qualify type: const, friend volatile. RESERVED Other reserved words of C++: asm, break, case, class, continue, default, delete, do, else, enum, for, goto, if, new, operator, private, protected, public, return, sizeof, struct, switch, this, union, while, namespace, using, try, catch, throw, const_cast, static_cast, dynamic_cast, reinterpret_cast, typeid, template, explicit, true, false, typename. This class also includes some compiler specific nonstandard keywords.
[Link]
25
Halstead metrics
Operators (2/2):
OPERATOR ! != &= () , / /= <= = ? [] ~ts
% * -: == ^
%= *= -= :: > ^=
& + -> < >= {}
&& ++ . << >> |
|| += ... <<= >>= |=
[Link]
26
Halstead metrics
The following control structures case ...: for (...) if (...) seitch (...) while for (...) and catch (...) are treated in a special way. The colon and the parentheses are considered to be a part of the constructs. The case and the colon or the for (...) if (...) switch (...) while for (...) and catch (...) and the parentheses are counted together as one operator.
[Link]
27
Halstead metrics
Program length (N) The program length (N) is the sum of the total number of operators and operands in the program: N = N1 + N2 Vocabulary size (n) The vocabulary size (n) is the sum of the number of unique operators and operands: n = n1 + n2
[Link]
28
Halstead metrics
Program volume (V) = information content of the program It is calculated as the program lengh times the 2-base logarithm of the vocabulary size (n): V = N * log2(n)
Halstead's volume (V) describes the size of the implementation of an algorithm.
[Link]
29
Halstead metrics
Recommandations: The volume of a function should be at least 20 and at most 1000. The volume of a parameterless one-line function that is not empty; is about 20. A volume greater than 1000 tells that the function probably does too many things.
The volume of a file should be at least 100 and at most 8000. These limits are based on volumes measured for files whose LOCpro and v(G) are near their recommended limits.
[Link]
30
Halstead metrics
Difficulty level (D) The difficulty level or error proneness (D) of the program is proportional to the number of unique operators in the program. D is also proportional to the ration between the total number of operands and the number of unique operands. (i.e. if the same operands are used many times in the program, it is more prone to errors)
D = ( n1 / 2 ) * ( N2 / n2 )
[Link]
31
Halstead metrics
Program level (L) The program level (L) is the inverse of the error proneness of the program. I.e. A low level program is more prone to errors than a high level program.
L=1/D
[Link]
32
Halstead metrics
Effort to implement (E) The effort to implement (E) or understand a program is proportional to the volume and to the difficulty level of the program. E=V*D
[Link]
33
Halstead metrics
Time to implement (T) The time to implement or understand a program (T) is proportional to the effort. Halstead has found that dividing the effort by 18 give an approximation for the time in seconds. T = E / 18
[Link]
34
Halstead metrics
Number of delivered bugs (B) The number of delivered bugs (B) correlates with the overall complexity of the software. B= E
2/3
3000
Estimate for the number of errors in the implementation. Delivered bugs in a file should be less than 2. Experiences have shown that, when programming with C or C++, a source file almost always contains more errors than B suggests.
[Link]
35
Halstead metrics
B is an important metric for dynamic testing: The number of delivered bugs approximates the number of errors in a module. As a goal at least that many errors should be found from the module in its testing.
[Link]
36
Maintainability Index (MI)
[Link]
37
Maintainability Index (MI)
Maintainability Index: Calculated with certain formulae from lines-of-code measures, McCabe measure and Halstead measures. Indicates when it becomes cheaper and/or less risky to rewrite the code instead to change it.
[Link]
38
Maintainability Index (MI)
Two variants of Maintainability Index: One that contains comments (MI) and one that does not contain comments (MIwoc). Actually there are three measures: MIwoc: Maintainability Index without comments MIcw: Maintainability Index comment weight MI: Maintainability Index = MIwoc + MIcw
[Link]
39
Maintainability Index (MI)
MIwoc = 171 - 5.2 * ln(aveV) -0.23 * aveG -16.2 * ln(aveLOC)
aveV = average Halstead Volume V per module aveG = average extended cyclomatic complexity v(G) per module aveLOC = average count of lines LOCphy per module perCM = average percent of lines of comments per Module
[Link]
40
Maintainability Index (MI)
MIcw = 50 * sin(2,4*perCM)
perCM = average percent of lines of comments per module
MI = MIwoc + MIcw
[Link]
41
Maintainability Index (MI)
Maintainability Index (MI, with comments) values:
85 and more 65-85 < 65
Good maintainability Moderate maintainability Difficult to maintain with really bad pieces of code (big, uncommented, unstructured) the MI value can be even negative
[Link]
42
Testwell CMT++/ CMTJava
[Link]
43
Testwell CMT++/ CMTJava
[Link]
44
Verybench for Testwell CMT++/ CMTJava
Verybench: Graphical front-end for Testwell Complexity Measurement Tools
[Link]
45
Verybench for Testwell CMT++/ CMTJava
Snapshots Overview shows the course of the measured source codes quality over time by stating the alarm ratios of the latest six snapshots.
[Link]
46
Verybench for Testwell CMT++/ CMTJava
Alarm-Limits Overview integrates all configurable Alarm Limits into a Radar Chart for each file and function. Every axis represents a different alarming metric with its configurable lower and higher Alarm Limits.
The Radar Chart basically shows the deviation of a metrics current value from its lower and higher Alarm Limits.
[Link] 47
Verybench for Testwell CMT++/ CMTJava
Distribution of Metrics shown on file and function levels for: V (Program Volume) c% (Comment Ratio) LOCpro (Program Lines of Code) v(G) (McCabe Cyclomatic Number) In addion B (Estimated Number of Bugs) is shown on file level
[Link]
48
Verybench for Testwell CMT++/ CMTJava
Metrics View overview over all (both alarming and non-alraming) metrics of the mesured files and functions
[Link]
49
Thank You
Thank you for your time! Your Verifysoft Team
[Link]
50