Object-Oriented Metrics in Practice
Object-Oriented Metrics in Practice
Using Software Metrics to Characterize, Evaluate, and Improve the Design of Object-Oriented Systems
Bearbeitet von
Michele Lanza, Radu Marinescu, S Ducasse
Die Online-Fachbuchhandlung beck-shop.de ist spezialisiert auf Fachbücher, insbesondere Recht, Steuern und Wirtschaft.
Im Sortiment finden Sie alle Medien (Bücher, Zeitschriften, CDs, eBooks, etc.) aller Verlage. Ergänzt wird das Programm
durch Services wie Neuerscheinungsdienst oder Zusammenstellungen von Büchern zu Sonderpreisen. Der Shop führt mehr
als 8 Millionen Produkte.
4
Design Harmony
do not talk to nobody, etc.), and finally in harmony with its ancestors
and descendants. Every artifact must have its appropriate place, size,
and complexity to fit the system context.
A metric alone cannot help to answer all the questions about a sys-
tem and therefore metrics must be used in combination to provide
relevant information. Why?
Using a medical metaphor we might say that the interpretation of
abnormal measurements can offer an understanding of symptoms,
but the measurements cannot provide an understanding of the dis-
ease that caused those symptoms. The bottom-up approach, i.e., going
from abnormal numbers to the recognition of design diseases is im-
practicable because the symptoms captured by single metrics, even
if perfectly interpreted, may occur in several diseases: The interpre-
tation of individual metrics is too fine grained to indicate the disease.
This leaves us with a major gap between the things that we mea-
sure and the things that are in fact important at the design level with
respect to a particular investigation goal.
How should we combine then metrics in order to make them serve
our purposes? The main goal of the mechanism presented below is
to provide engineers with a means to work with metrics at a more
abstract level. The mechanism defined for this purpose is called a
detection strategy, defined as follows:
4.1 Detection Strategies 49
Filtering
The key issue in filtering is to reduce the initial data set so that only
those values that present a special characteristic are retained. A data
filter is a boolean condition by which a subset of data is retained from
an initial set of measurement results, based on the particular focus
of the measurement.
The purpose of filtering is to keep only those design fragments
that have special properties captured by the metric. To define a data
filter we must define the values for the bottom and upper limits of
the filtered subset. Depending on how we specify the limit(s) of the
resulting data set, filters can be either statistical, based on absolute
thresholds, or based on relative thresholds.
Statistical Filters
Threshold-Based Filters
Composition
Input Term
Input Term
Input Term
OR Output Term
Input Term
The second step is to select proper metrics that quantify best each of
the identified properties. In this context the crucial question is: from
where should we take the proper metrics? There are two alternatives:
54 4 Evaluating the Design
Notice that while the first two metrics (i.e., WMC and TCC) are metrics
defined in the literature, the last one was defined by us in order to
capture a very specific aspect, i.e., the extent to which a class uses
attributes of other classes.
The next step is to define for each metric the filter that captures best
the symptom that the metric is intended to quantify. As mentioned
earlier, this implies to (1) pick-up a comparator and (2) to set an
1
For a precise description of all the metrics used in the book, including the
metrics below please refer to Appendix A.
56 4 Evaluating the Design
Invocation Sequence
A class blueprint decomposes a class into layers and assigns its at-
tributes and methods to each layer based on the heuristics described
below (see Fig. 4.6). The layers support a call-graph notion in the
sense that a method node on the left connected to another node on
the right is either invoking or accessing the node on the right that
represents a method or an attribute.
The layers have been chosen according to a notion of time-flow and
encapsulation. The notion of encapsulation is visualized by separat-
ing state (to the right) from behaviour (to the left), and distinguish-
ing the public (to the left) from the private part (to the right) of the
class’ behaviour. Added to this only the actual source code elements
are visualized, i.e., we do not represent artificial elements resulting
3
The colors used in our visualizations follow visual guidelines suggested by
Bertin [Ber74], Tufte [Tuf90], Ware [War00], and Pinker [Pin97], e.g., we
take into account that the human brain is not capable of simultaneously
processing more than a dozen distinct colors.
60 4 Evaluating the Design
Number of Invocations
Abstract
Method
Number of
Method Lines of Code Overriding
Method
Number of
Extending
Attribute internal accesses Method
Constant
Direct access
Method invocation Method
Read Accessor
Method
Write Accessor
Method
Fig. 4.7. In a class blueprint the metrics are mapped on the width and the
height of a node. The methods and attributes are positioned according to the
layer they have been assigned to.
class for the width and the number of direct accesses from methods
defined in other classes for the height. This allows one to identify how
attributes are accessed.
Description Color
Attribute blue node
Abstract method cyan node
Extending method. A method which performs a super invocation. orange node
Overriding method. A method redefinition without hidden method invocation. brown node
Delegating method, forwards the method call to another object. yellow node
Constant method. A method which returns a constant value. grey node
Interface and Implementation layer method. white node
Accessor layer method. Getter. red node
Accessor layer method. Setter. orange node
Invocation of a method. blue edge
Invocation of an accessor. Semantically equivalent to a direct access. blue edge
Access to an attribute. cyan edge
The left part of Fig. 4.8 shows the blueprint of a Smalltalk class
named Jun-OpenGL3dGraphAbstract which we describe hereafter. As
the named blueprint on the right in Fig. 4.8 shows, this kind of rep-
resentation does not scale well in practice; additionally, metrics in-
formation is not reflected in a named blueprint (i.e., the width and
height of nodes is not correlated with metric value). Therefore it is
not used in this book.
The code shown is Smalltalk code; however, in order to understand
the code sequence being fluent in Smalltalk is not a must as we are
only concerned with method invocations and attribute accesses.4
The class blueprint shown in Fig. 4.8 has the following structure:
method with the same name, hence the node color is orange. It
directly accesses two attributes, as the cyan line shows. The code
of the method initialize is as follows:
initialize
super initialize.
displayObject := nil.
displayColor := nil
asPointArray
ˆ self displayObject asPointArray
The five grey nodes in the interface layer are methods returning
constant values as illustrated by the following method isArc. This
method illustrates a typical practice to share a default behavior
among the hierarchy of classes.
isArc
ˆ false
displayObject
displayObject isNil ifTrue:
[ displayObject := self createDisplayObject ].
ˆ displayObject
createDisplayObject
ˆ self subclassResponsibility
Fig. 4.9. A blueprint of the class JunSVD. This class blueprint shows patterns
of the type Single Entry, Structured Flow and All State.
Example 2: An Algorithm
The class blueprint presented in Fig. 4.9 displays the class JunSVD
implementing the algorithm of the same name. Looking at the blueprint
we get the following information.
compute
| superDiag bidiagNorm eps |
m := matrix rowSize.
n := matrix columnSize.
u := (matrix species unit: m) asDouble.
v := (matrix species unit: n) asDouble.
sig := Array new: n.
superDiag := Array new: n.
bidiagNorm := self bidiagonalize: superDiag.
eps := self epsilon * bidiagNorm.
self diagonalize: superDiag with: eps.
color
ˆ ColorValue hue: self hue
saturation: self saturation
brightness: self brightness
We see that the methods xy: (B) and xy (C), play a central role in the
design of the class as they are both called by several of the methods
of each subclass, as confirmed by the following method of the class
JunColorChoiceSBH:
JunColorChoiceSBH>>brightness: value
((value isKindOf: Number) and:
[0.0 <= value and: [value <= 1.0]])
ifTrue: [self xy: self xy x @ 1 - value]
By building the class blueprint for this class (see Fig. 4.11) we
can immediately see that Modeller is not a class with an excessive
number of methods, but has a certain number of considerably large
and complex methods (3 methods are longer than 100 lines of code,
the longest one addDocumentationTag (annotated as 1a in the figure)
70 4 Evaluating the Design
is 150 lines code and invoked by three other methods, two of which
are the second and third longest methods in this class: addOperation
(1b, 116 LOC) and addAttribute (1c, 108 LOC). The class blueprint
reveals other disharmonies in this class: there are 12 attributes in
this class, all of them private (which is good), but there are “only” 4
accessor methods. Moreover, the attributes are accessed both directly
and indirectly (using the accessors), denoting a certain inconsistency
or lack of access policy.