COMMAND FORMAT -- MCCABE : Calculate the McCabe

advertisement
1
COMMAND FORMAT
-- MCCABE : Calculate the McCabe complexity measures.
-- Version 3.01-1.1
subtype FILE_NAME is STRING;
subtype MAX_VALUE is INTEGER range 1 .. 99;
procedure MCCABE(
SOURCE_FILE
: in FILE_NAME;
OUTPUT_FILE
: in FILE_NAME := "";
MAX_COMPLEXITY : in MAX_VALUE := 20
);
-- SOURCE_FILE
: Input file name.
-- OUTPUT_FILE
: Name of the report file (defaults to standard
output).
-- MAX_COMPLEXITY : Greatest complexity not flagged in output listing
-(range: 1 .. 99, default: 20).
2
MCCABE DESCRIPTION AND USE
The McCabe measure computes complexity based on the control
structure (or "flow graph") of the program. The tool takes the
name of an Ada source program text file and computes the
cyclomatic complexity for every subprogram body contained in the
file. Specifications do not have a complexity associated with
them.
The tool also takes an output file name and a number,
MAXCOMPLEXITY, which is the maximum complexity allowed for a
program.
If a procedure is found to have a complexity greater
than the specified value, it will be flagged on the output
listing.
The McCabe tool builds the flow graph and computes the
cyclomatic number for each program unit in the source file. In
addition, it sums the number of nodes and edges in all program
units and computes a cyclomatic number for the entire file.
The tool assumes that a source program text is correct ADA
(i.e., it is compiled cleanly); otherwise it terminates with a
syntax error.
3
MOTIVATION
The McCabe complexity measure is principally useful in two ways:
as an aid in testing and as a numeric guidline for management
purposes. In testing, the complexity number corresponds to the
number of control paths through a subprogram and therefore the
Page 2
number of test cases required to test them all. If the number of
test cases is less than the complexity, then at least one of
three conditions is true:
1.
more testing is required;
2.
decision points can be removed;
3.
in-line code can replace decision points.
(See [McC] for a full explanation.) As a programming and
management guidline the tool provides a simple way of flagging
subprograms which might cause problems. The general method for
keeping subprograms simple is to establish a size limit, e.g., 50
lines or 2 pages. This is really a surrogate for the lack af any
good way of measuring simplicity. The McCabe metric is just such
a simplicity measure. The measure is only a guideline since a
large CASE statement will have a correspondingly large complexity
but it may only be the equivalent of a jump table.
Each user will have to determine through experience how best
to use the information provided by the tool.
The McCabe
complexity number is just one measure of program complexity.
Although it can help to identify program units that may require
further scrutiny, it is not at all reasonable to require that all
program units have a cyclomatic complexity below a certain value.
A case statement for example is well structured, but can have a
high complexity (on the order of the number of branches in the
statement). This does not mean that the program is poorly
structured, only that each branch of the case statement must be
tested.
4
THEORY OF THE MCCABE METRIC
The McCabe metric is based on the flow graph of a program.
The flow graph is a directed graph where the nodes represent
basic blocks and the edges represent control flow between basic
blocks.
A basic block is a sequence of consecutive statements
which may only be entered at the beginning and exited at the end.
When entered the instructions are executed in sequence without
branching except at the end [Aho].
Figure 1 shows some flow
graphs for different programming structures.
if expression
then
S1
else
S2
endif;
do while expression loop
S1;
end loop;
Page 3
if
/ \
V
V
S1
S2
\
/
V V
endif
do while
| | ^
| V |
|
S1
V
end loop
FIGURE 1
McCabe's cyclomatic complexity is defined as:
V(G) = e - n + 2p
where 'e' is the number of edges in the flow graph, 'n' is the
number of nodes, and 'p' is the number of connected components.
Ignoring the direction from the edges of the flow graph, if there
exists a path between each pair of vertices I and J then we say
the graph is a connected component. Since there is a path from
the entry node to every other node in the flow graph then
(ignoring the directions of the edges) we will be able to get
from any node I to any other node J by going through the entry
node.
Therefore, in our case of computing the cyclomatic
complexity for an individual subprogram p is always 1. The
number of connected components becomes interesting when we would
like to calcultate the cyclomatic complexity of a program that
has a number of different subprograms.
McCabe defines the
cyclomatic complexity of a system as the sum of the cyclomatic
complexities of all the modules. In this case p, the number of
connected components would be the number of different modules.
If a subprogram has some unreachable code then McCabe's
cyclomatic complexity formular does not make a lot of sense. In
some cases the tool discovers such subprograms and flags them in
the output with the message "unreachable code".
5
INTERPRETATION OF ADA STATEMENTS
There is a number of ADA statements which generate flow but
building a flow graph for them is not obvious. Sometimes it
happens because the flow of a statement can be interpreted in a
number of ways (as for case and select statements); sometimes it
happens because of the tool limits (as for a raise statement the flow could go to an exception handler belonging to a same
subprogram as the raise statement or it could go to a different
subprogram
in
which case the tool does not have enough
information to track the flow).
This is a list of such statements with
interpretations.
their
corresponding
Page 4
6
1.
The complexity of an exception handler is added
complexity of a containing subprogram.
to
the
2.
Case, select statements and exception handlers are
interpreted as if statement [McC]. For a case statement
a corresponding if statement always has an else clause.
Two forms of select statements - conditional entry call
and timed entry call are
always
interpreted
as
if...then...else...end if.
3.
Return, raise and terminate statements are ignored (as a
stop statement in [McC]).
OUTPUT FORMAT
The output of the tool is a list of names of all the
subprograms in the input file. Each name is preceeded by its
cyclomatic complexity, the number of nodes and the number of
edges in the flow graph. If any subprogram or function has a
cyclomatic complexity above the specified value, it is flagged.
A sample output follows:
MCCABE CYCLOMATIC COMPLEXITY:
SOURCE_FILE "EXAMPLE" - WITH MAX_COMPLEXITY 9
COMPLEXITY
CYCLOMATIC
NUMBER OF
EDGES NODES
4
3
14
.
.
.
10
9
37
.
.
.
8
8
25
.
.
.
32
90
48
SUBPROGRAM NAME
subprog1
subprog2
*** subprog3
.
.
.
Total for 5 program units
Page 5
7
REFERENCES
1.
[Aho] Aho, A.V., Ullman, J.D., Principles of Compiler
Design, Addision-wesley Publishing Company, pp 412-413,
1977.
2.
[McC] McCabe, T.
J., "A Complexity Measure", IEEE
Transactions on Software Engineering, Vol. SE-2, pp
308-320, December, 1976.
Page 6
8
APPENDIX A:
INSTALLATION AND MODIFICATION
To build the McCabe tool:
1. Compile all the abstractions into a program library (see READ.ME in
abstractions directory for details).
2. Compile everything named in the MCCABE.CO file into the program
library
containing the abstractions or a sublibrary whose parent library
contains
all the abstractions. MCCABE.CO lists file names in the correct
compilation order.
3. Link McCabe with the program library where everything was compiled.
To do this using the DEC Ada compiler type:
$ acs link mccabe
To run the tool on VMS:
1. Define logical symbol for the executables of the McCabe tool.
For example,
MCCABE :== $DRB1:[NOSC.TOOLS.MCCABE]MCCABE.EXE
NOTE: The full path name of the executable is required in the
definition of the symbol.
The pathname given here is just an
example and will be different on your system.
2. Enter a command with appropriate parameters.
For example,
MCCABE ("myfile");
Entering the command with no parameters gives a brief description
of how to use the tool.
Files contained in the MCCABE directory:
MCCABE.CO
MCCABE.EXE
MCCABE.CNT
READ.ME
-----
Compilation order for McCabe sources
VMS 4.0 McCabe executable
Ada source statement count
This file
The [.SOURCE] subdirectory contains most of the sources that make up the
McCabe tool. Other sources are contained in the abstractions directory.
Files in [.SOURCE]:
The source files which make up the McCabe tool are as follows:
MCCGRMLP.ADA
units)
MCCGRMAA.SUB
FLOWGRAPH.SPC
(spec)
FLOWGRAPH.BDY
(body)
GETNEXT.SUB
-- Lexer/parser source code (contains several program
-- Action routine created from the LALR grammar
-- Subprograms used to build and access the Flow Graph
-- Subprograms used to build and access the Flow Graph
-- Subprogram to obtain lexer tokens
Page 7
MCCGRMC.SPC
(spec)
MCCGRMC.BDY
(body)
MCCABE.ADA
MCCDEFS.SPC
variables
-- Grammar constants (created from the LALR grammar)
-- Grammar constants (created from the LALR grammar)
-- McCabe Complexity Driver
-- McCabeDefinitions containing global types and
used by the various parts of the McCabe Complexity
Tool
MCCSTK.SPC
(spec)
MCCSTK.BDY
(body)
PARSE.BDY
MCCGRMPT.SPC
MCCGRMPT.BDY
STATEMENT.SPC
STATEMENT.BDY
-- Subprograms to keep account of nodes and edges
-- Subprograms to keep account of nodes and edges
------
Parser for the McCabe utility.
ParserTables created from the LALR grammar (spec)
ParserTables created from the LALR grammar (body)
Subprograms to create the flow graph (spec)
Subprograms to create the flow graph (body)
The [.TEST] subdirectory contains tests used in testing the McCabe tool.
Files in [.TEST]:
TMCCABE.COM -- COM file to run all test for McCabe tool
CHECKOUT.COM -- COM file to compare old result with the new
(after running TMCCABE.COM)
CLEANUP.COM -- COM file to clean the [.TEST] directory
Files with file type .TST are inputs to the McCabe test.
EXCEPT.TST
LABS6.TST
SELECT.TST
TEST10A.TST
TEST18.TST
TEST24.TST
TEST7.TST
LABS.TST
LOOP.TST
SELECT1.TST
TEST11A.TST
TEST2.TST
TEST3.TST
TEST7A.TST
LABS2.TST
MLABS.TST
SELECT3.TST
TEST12.TST
TEST21.TST
TEST4.TST
TEST8.TST
LABS4.TST
MLABS5.TST
TEST1.TST
TEST13.TST
TEST22.TST
TEST5.TST
TEST9.TST
LABS5.TST
MLABS6.TST
TEST10.TST
TEST17.TST
TEST23.TST
TEST6.TST
Files with file type .RPT are expected results of the McCabe test.
EXCEPT.RPT
LABS6.RPT
SELECT.RPT
TEST10A.RPT
TEST18.RPT
TEST24.RPT
TEST7.RPT
LABS.RPT
LOOP.RPT
SELECT1.RPT
TEST11A.RPT
TEST2.RPT
TEST3.RPT
TEST7A.RPT
LABS2.RPT
MLABS.RPT
SELECT3.RPT
TEST12.RPT
TEST21.RPT
TEST4.RPT
TEST8.RPT
LABS4.RPT
MLABS5.RPT
TEST1.RPT
TEST13.RPT
TEST22.RPT
TEST5.RPT
TEST9.RPT
LABS5.RPT
MLABS6.RPT
TEST10.RPT
TEST17.RPT
TEST23.RPT
TEST6.RPT
The [.DOC] subdirectory contains the documentation for the McCabe tool.
Files in [.DOC]:
MCCABE.MEM
MCCABE.RNO
MCCGRM.LIS
-- McCabe tool user's manual
-- Runoff input for McCabe tool user's manual
-- Listing of requirements reference grammar. The rule
numbers in this file may be used to make changes to
the
RELEASE.NTS
case statement in the MCCAPPLYACTIONS subunit.
-- Release notes
Download