54
2006 The University of Auckland New Zealand SOFTWARE ENGINEERING Software Design and Metrics Hayden Melton Computer Science [email protected] May 2006

2006 The University of Auckland New Zealand SOFTWARE ENGINEERING Software Design and Metrics Hayden Melton Computer Science [email protected] May

Embed Size (px)

Citation preview

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

[email protected]

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

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

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

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

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

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

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

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

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

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