Date post: | 02-Jan-2016 |
Category: |
Documents |
Upload: | lisa-daniel |
View: | 214 times |
Download: | 0 times |
20
06
Th
e U
niv
ers
ity o
f A
uck
lan
d
New
Zeala
nd
SO
FTW
AR
E E
NG
INEER
ING
Software Design and
Metrics
Hayden MeltonComputer Science
May 2006
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Overview
= Buzzwords for designing software:– Loosely-coupled
– Cohesive
– Encapsulating
– Manageable size
= “Fuzzy terms” – what do they actually mean?
= Today I’ll try to be rigorous about one form of coupling
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Coupling
= Two things are coupled if to changing one also requires changing another [Fowler, Stevens]
= “Strength of association of established by a connection from one module to another” [Stevens, Myers, Constantine]
= Many forms of coupling – dependency at runtime, compile time dependency, change dependency (CVS data).
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Java
= Java is a strongly typed language, which means the compiler checks the types of expressions etc before allowing compilation
= A Java program can be thought of as a collection of types (i.e. classes, interfaces, enums, primitives)
= Can view a (reference) type as a composition of other types
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Meaning of Compilation Dependency
public class Foo {
private A a = new A();
public P m1() { X x = new X(a); K k = x.m(); P p = k.m(); return p;
}
public P2 m2(P3 p3) { P2 p2 = Z.run(a, p3); return p2; }
}
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Meaning of Compilation Dependency
public class Foo {
private A a = new A();
public P m1() { X x = new X(a); K k = x.m(); P p = k.m(); return p;
}
public P2 m2(P3 p3) { P2 p2 = Z.run(a, p3); return p2; }
}
Foo
A
P
X
K
P2
P3
Z
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Structure of a typical Java Program
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Source-declared type
Externally-declared type
KEY
Structure of a typical Java Program
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Source-declared type
Externally-declared type
KEY
Compilation dependency
Structure of a typical Java Program
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Source-declared type
Externally-declared type
KEY
Compilation dependency
Structure of a typical Java Program
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Source-declared type
Externally-declared type
KEY
Compilation dependency
Structure of a typical Java Program
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Observations on Structure
= Externally-declared types can’t depend on source-declared types
= The graph is connected– Classes must communicate with each other to be
part of the same system
= The source-declared subgraph is usually connected
– Externally declared types can’t instantiate source declared ones, and they’ve got to be instantiated somewhere
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Design Principles
= Depend entirely on externally-declared types (if possible)
– Proven, well-understood, stable, widely-available
= Dependency on externally-declared types less detrimental coupling than dependency on source-declared types
– Source types change, unique to application – so not well understood
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Two Systems: a comparison
(a) (b)
= Which is most “loosely-coupled”?– Think in terms of reuse, understanding, testing, …
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
“Layered” or “Hierarchical” Structure
= Reuse– Deploying a type in the context of a new
system and having it compile
= Testing– Unit testing, Integration testing
= Understanding– No good place to start [Lakos], go round the
cycle many times [Fowler].
(a)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Reuse
= Why “verbatim reuse”?– Even the smallest changes to reused code can introduce
errors [Stark].
– Version proliferation
– Divergence from original, hard to integrate updates [Martin].
= For reuse to be effective the class we’re reusing can’t be tied to a large block of unnecessary code
– Increases the number of types to be considered in the new system, and potentially more code that could contain bugs
– Really a problem – Azureus (logger, internationalization, torrent parser, concurrency). Eclipse (Internal compiler depends on a few thousand classes c.f. Sun’s Java compiler).
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Reuse
= Dependency is transitive– If A depends on B, and B depends on C, then A
transitively depends on C.
= Deploy a source file from one program in the context of another also need all the files it needs to compile. But we also need all the files the others need. We need the transitive closure of its dependency.
= Transitively a recurring theme…
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Testing
= Unit testing – about testing a class “in isolation”
– More dependencies it has, potentially more interactions it has harder to test in isolation
(a) (b)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Testing
= Integration testing – about testing system “in order”
– Test one level, find it’s correct. Test the next level find it’s correct, …
(a) (b)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Testing
= Integration testing – about testing system “in order”
– Test one level, find it’s correct. Test the next level find it’s correct, …
(a) (b)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Testing
= Integration testing – about testing system “in order”
– Test one level, find it’s correct. Test the next level find it’s correct, …
(a) (b)
Where to start? Need to test it all in one go!
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Understanding
= Similar argument to reuse – in order to understand a class should only (at most) have to understand the classes on which it transitively depends
= Worst case for understanding class indicated in red:
= A starting point for understanding a system the first time you look at it (as per integration test order)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Understanding
= What about polymorphism? To understand Foo, we also have to understand BarImpl yet Foo doesn’t transitively depend on BarImpl!
Foo
IBar
BarImpl
Baz
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Understanding
= public class Baz { void run() { IBar bar = new BarImpl(); Foo foo = new Foo(bar); //... }}
public class Foo { private IBar bar; public Foo(IBar bar) { this.bar = bar; } //...makes extensive use of bar in body}
Constructor Dependency Injection
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Understanding
= Argument still holds if we have good unit tests– Should be able to glean all the pre- and post- conditions
from the unit tests of Foo.
– The key is the type MockBarImpl
= public class TestFoo extends TestCase { public void testFoo() { IBar bar = new MockBarImpl(); Foo foo = new Foo(bar); //... }}
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Comparing Hierarchical Structures
= Hierarchical/layered structures better than their cyclic analogues
= What “shape” of hierarchical structure is best?
(a) (b)
(c)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Comparing Hierarchical Structures
= Number of classes coupled to “nothing” (or “standalone”)?
– (a) has 1– (b) has 4– (c) has 7
= Recall: Reuse, understanding, testing.
(a)
(b)
(c)
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Ideal Hierarchical Structure
= So we want a “flatter” hierarchical structure rather than a taller one
– Classes in “flat” structures tend to have lower transitive dependencies than those in “tall” structures
= We also want the “flat” structure to have small transitive dependencies, not like:
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Metric - CRSS
a
b cd
e fg
hi
Node Reachability Set CRSS
a {a, b, e, c, f, d, g, h, i} 9
b {b, e} 2
c {c, f, g, h, i} 5
d {d, f, g, h, i} 5
e {e} 1
f {f, g, h, i} 4
g {g, h, i} 3
h {h, i, g} 3
i {i, g, h} 3
= Class Reachability Set Size (CRSS) captures the transitive dependencies of each class
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
CRSS Histogram
0
1
2
3
4
1 2 3 4 5 6 7 8 9
CRSS Value
Fre
qu
en
cy
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
A “Good” CRSS Distribution
CRSS Histogram for Netbeans 4.1
0
500
1000
1500
2000
2500
3000
3500
4000
4500
1-1
00
10
1-2
00
20
1-3
00
30
1-4
00
40
1-5
00
50
1-6
00
60
1-7
00
70
1-8
00
80
1-9
00
90
1-1
00
0
10
01
-11
00
11
01
-12
00
12
01
-13
00
13
01
-14
00
14
01
-15
00
15
01
-16
00
16
01
-17
00
17
01
-18
00
18
01
-19
00
19
01
-20
00
20
01
-21
00
21
01
-22
00
CRSS Value
Fre
qu
en
cy
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
A “Bad” CRSS DistributionCRSS Histogram -- Azureus 2.3.0.4
0
100
200
300
400
500
600
700
800
900
1000
1--
50
51
--1
00
10
1--
15
0
15
1--
20
0
20
1--
25
0
25
1--
30
0
30
1--
35
0
35
1--
40
0
40
1--
45
0
45
1--
50
0
50
1--
55
0
55
1--
60
0
60
1--
65
0
65
1--
70
0
70
1--
75
0
75
1--
80
0
80
1--
85
0
85
1--
90
0
90
1--
95
0
95
1--
10
00
10
01
--1
05
0
10
51
--1
10
0
11
01
--1
15
0
11
51
--1
20
0
12
01
--1
25
0
12
51
--1
30
0
13
01
--1
35
0
13
51
--1
40
0
CRSS Value
Fre
qu
en
cy
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Why the big gap in the Histogram?
Bunch of classes all involved in one, big strongly connected component.
CRSS
Fre
q
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Why the big gap in the Histogram?
Bunch of classes all involved in one, big strongly connected component.
CRSS
Fre
q
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Why the big gap in the Histogram?
Bunch of classes all involved in one, big strongly connected component.
CRSS
Fre
q
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Why the big gap in the Histogram?
Bunch of classes all involved in one, big strongly connected component.
CRSS
Fre
q
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
Class CRSS
org.gudy.azureus2.core3.util.Debug 1372
org.gudy.azureus2.core3.util.AEMonitor 1372
org.gudy.azureus2.core3.config. COConfigurationManager 1372
org.gudy.azureus2.core3.internat. MessageText 1372
org.gudy.azureus2.core3.logging. LGLogger 1372
org.gudy.azureus2.core3.torrent. TOTorrent 1372
org.gudy.azureus2.core3.util.SystemTime 1372
org.gudy.azureus2.core3.peer.PEPeer 1372
org.gudy.azureus2.core3.disk. DiskManager 1372
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
Subsystem Class CRSS
debug org.gudy.azureus2.core3.util.Debug 1372
threading org.gudy.azureus2.core3.util.AEMonitor 1372
configurationorg.gudy.azureus2.core3.config.
COConfigurationManager 1372
internationalisationorg.gudy.azureus2.core3.internat.
MessageText 1372
logging org.gudy.azureus2.core3.logging. LGLogger 1372
business object org.gudy.azureus2.core3.torrent. TOTorrent 1372
time org.gudy.azureus2.core3.util.SystemTime 1372
peer org.gudy.azureus2.core3.peer.PEPeer 1372
disk-io org.gudy.azureus2.core3.disk. DiskManager 1372
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
Subsystem Class CRSS Refact’d
debug org.gudy.azureus2.core3.util.Debug 1372 16
threading org.gudy.azureus2.core3.util.AEMonitor 1372 26
configurationorg.gudy.azureus2.core3.config.
COConfigurationManager 1372 1360
internationalisationorg.gudy.azureus2.core3.internat.
MessageText 1372 44
logging org.gudy.azureus2.core3.logging. LGLogger 1372 12
business object org.gudy.azureus2.core3.torrent. TOTorrent 1372 32
time org.gudy.azureus2.core3.util.SystemTime 1372 5
peer org.gudy.azureus2.core3.peer.PEPeer 1372 171
disk-io org.gudy.azureus2.core3.disk. DiskManager 1372 171
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
= Empirical evidence I have gathered shows if uncontrolled, dependencies seem to get worse over time!
– CRSS values grow
– Cycles grow and become intertwined
v1
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
= Empirical evidence I have gathered shows if uncontrolled, dependencies seem to get worse over time!
– CRSS values grow
– Cycles grow and become intertwined
v1 v2
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Using the Metric to Manage a Project
= Empirical evidence I have gathered shows if uncontrolled, dependencies seem to get worse over time!
– CRSS values grow
– Cycles grow and become intertwined
v1 v2 v3
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Criticisms
= Some cycles among classes cannot be avoided:
= public class Node { public Edge[] getIncomingEdges() {//…} //… }
public class Edge { public Node getDestnNode() { //…} //…}
Node
Edge
= The bin size on the x-axis of the CRSS histogram “takes care” of this problem. Should always avoid cycles among subsystems (groups of classes).
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Criticisms
= I’m not suggesting a flat hierarchical graph at any cost
– Need to maintain type-safeness, encapsulation, abstractions, factoring, etc
– In my examination of lots of open source systems the graphs can be flattened without compromising other design principles
= Just because the histogram indicates the graph is flat doesn’t mean the design is perfect
– Need other metrics to measure cohesion, abstractions, …
20
06
SO
FTW
AR
E E
NG
INEER
ING
Th
e U
niv
ers
ity o
f A
uck
lan
d
N
ew
Z
eala
nd
Conclusions
= Hopefully I have convinced you:
1. Flat, hierarchical (or layered structures) are good– Dijkstra (1968) – hierarchy, Parnas (1978) – no cycles,
Berard (1993) – externally declared types, Grady Booch (1995) – layered, John Lakos (1996) – flatter rather than taller
2. Some metrics are actually useful– Though it’s my view that a lot of well-known metrics
aren’t that useful
3. We ought to use metrics more in controlling software projects