• No results found

Part III Metrics and Tool Support

10.5 Constructing a Dependency Graph

11.3.3 Metric NCDC

Metric NCDC measures the size of the dependency cycles within a system.

Definition

For a system s, metric NCDC(s) is the total number of classes of s involved in dependency cycles:

Motivation and Purpose This metric can be used:

1 To characterize the size of the dependency cycles within a system.

2 To predict the effort caused by testing all classes involved in the dependency cycles at once (if the cycles aren’t broken with help of stubs) during integration testing.

Assumptions

Basic assumptions of the metric NCDC are:

1 The size and complexity of the classes within the depen- dency cycles does not matter.

2 Concrete classes, abstract classes, and interfaces within the dependency cycles have the same effect on testing.

Discussion

To the best knowledge of the author, no metrics have been pub- lished so far to characterize dependency cycles within a system. Metric NCDC is (like metric ACD) based on a very abstract view of the system and provides only a rough view of potential test problems caused by dependency cycles.

Properties of metric NCDC

name number of classes within dependency cycles

entity system

attribute size of dependency cycles category direct metric

scale type absolute scale

context System::NCDC() : Integer

134 Chapter 11: Metrics

11.3.4

Metric NFD

Metric NFD measures the number of dependencies causing dependency cycles within the system.

Definition

For a system s, metric NFD(s) is defined as the cardinality of the feedback dependency set for s:

Motivation and Purpose This metric can be used:

1 to characterize the number of dependencies causing depen- dency cycles, and

2 to predict the effort necessary to remove all dependency cycles by removing selected dependencies.

Assumptions

Basic assumptions of the metric NFD are:

1 The size and complexity of the classes involved in the feed- back dependencies does not matter.

2 The difficulty to remove a dependency to a concrete class, an abstract class, or an interface is the same.

3 it is not intended to remove inheritance or implements rela- tionships.

4 The strength of the feedback dependencies does not matter. Assumption 3 is considered by the heuristic algorithm used to identify feedback dependency sets (see Section 10.3.7).

Discussion

Feedback dependencies are identified based on a heuristic algorithm and may not be identical with the dependencies which actually introduced the dependency cycles. However, the size of

Properties of metric NFD

name number of feedback dependencies entity system

attribute number of dependencies causing dependency cycles category direct metric

scale type absolute scale

context System::NFD() : Integer

Chapter 11: Metrics 135

the feedback dependency set is a good indicator of the effort to remove the dependency cycles.

Related Metrics

Metric NSBC (Number of Stubs to Break Cycles) in [Jung02b] is similar to metric NFD, but measures the number of classes which have to be removed in order to break all dependency cycles.

11.4

Dependency Metrics

Hard-wired dependencies may have been introduced by acci- dent. Metrics DSTM and DSTMh help to identify such depen- dencies.

11.4.1

Metric DSTM

Metric DSTM measures the strength of a given dependency.

Definition

For a dependency d, metric DSTM(d) is defined as the number of distinct statements causing d.

Properties of metric DSTM

name number of statements causing the dependency entity dependency

attribute strength of dependency category direct metric

scale type absolute scale

context ClassDependency def

let isInheritanceDependency() : Boolean =

self.client.allSupertypes()->contains(self.supplier) context ClassDependency::DSTM() : Integer

post: if self.isInheritanceDependency() result =

self.typeDeclaration->size() + self.memberAccess->size() + 1 else result = self.typeDeclaration->size() +

136 Chapter 11: Metrics

Purpose

The metric is used to characterize the strength of the depen- dency.

Assumptions

Basic assumptions of metric DSTM are:

1 Multiple access of the same category from one method of a given client class to the same class member of a supplier class is counted only once (see Section 10.5).

2 Each type of access contributes the same to the strength of the dependency.

Discussion

Ad assumption 2: Weighting different access types differently would be an alternative. However, further research is required to quantify e.g. the effect of different access types on the average ease to refactor a dependency as a basis for defining actual weights.

11.4.2

Metric DSTMh

Metric DSTMh measures the proportion of statements which cause a dependency to be semi-hard-wired.

Properties of metric DSTMh

name percentage of statements causing a dependency to be semi-hard-wired

entity dependency

attribute proportion of statements which cause a dependency to be semi-hard-wired

category indirect metric

unit [%]

Chapter 11: Metrics 137

Definition

Fora dependency d,m etric D STM h(d)is defined as the num berofdis- tinctstatem ents causing d to be sem i-hard-w ired.

Note: An inheritance relationship contributes 1 to the value of metric DSTMh like any other statement causing a class dependency to be semi-hard-wired.

Purpose

The metric can be used for different purposes:

1 To characterize the degree to which the dependency is semi-hard-wired.

2 To predict the difficulty of refactoring a semi-hard-wired dependency into a type dependency.

Metric DSTMh can be also be used to characterize hard-wired dependencies as well, but this is not the main intention (see Section 8.5.2).

Assumptions

The basic assumptions of metric DSTMh are the same as for metric DSTM.

Discussion

The percentage of statements causing a dependency to be semi-hard-wired is not always sufficient to get a complete pic- ture:

context ClassDependency def

let isInheritanceDependency() : Boolean = self.client.Ancestors()->contains(self.supplier)

let numberHwStatementsWithoutInheritance() : Integer = self.memberAccess->select(causesHardwiring())->size() context ClassDependency::DSTMh() : Integer

post: if self.DSTM() = 0 result = 0

else if self.isInheritanceDependency() result =

(numberHwStatementsWithoutInheritance() + 1) / self.DSTM() else result = numberHwStatementsWithoutInheritance() /

138 Chapter 11: Metrics

Example 20

Dependency A is caused by 20 dependencies, 5 of them making the dependency semi-hard-wired. Dependency B is caused by 4 dependencies, only one making it semi-hard-wired. In both cases the value of DSTMh equals 0.25 but dependency B may be easier to be refactored into a type dependency because only on statement needs to be tackled.

‰ A combination of the absolute number and relative number of statements causing a dependency to be semi-hard-wired there- fore provides more information to characterize the degree to which it is semi-hard-wired. However, the smallest values of DSTMh can be found within dependencies with a large value of DSTM:

The value of metric DSTMh is small, if the number of state- ments causing the dependency to be semi-hard-wired (the fraction’s numerator within the formula) is small and DSTM (the denominator) is large.

Therefore, we prefer the definition of metric DSTM as a relative number.

11.5

Reduction Metrics

Reduction metrics for dependencies are a new type of metrics which solve one shortcoming of existing coupling metrics: cou- pling metrics are class based. If the coupling value is to high, the developer is left alone with the task to identify the set of depen- dencies with the most negative impact on system structure.

11.5.1

Introduction

A reduction metric rM(d) for dependencies describes the degree to which the value of a metric M is reduced if a dependency d is removed from the system.

Note: metric values decrease when a dependency is removed in general.

A high value of a reduction metric for a given dependency means that the software characteristic is sensitive to the exist- ence of this dependency.

Chapter 11: Metrics 139

Related Metric Types

Change metrics Demeyer, Ducasse, and Nierstrasz use metrics called change

metrics to find refactorings [Deme00]. These metrics are calcu-

lated as the difference between system metric values of two dif- ferent system versions and are not linked to specific classes or class dependencies.

11.5.2

Metric rACD

Metric rACD measures the sensitivity of the number of indirect1 dependencies to the existence of a given dependency.

Definition

For a dependency d, metric rACD(d) is defined as a reduction metric based on metric ACD.

Motivation and Purpose

Metric rACD helps to identify metrics with a strong impact on the dependency structure.

Assumptions

The assumptions of metric rACD are:

1 The size and complexity of the classes does not matter. 2 Indirect dependencies do matter.

1 When removing any of the dependencies within a system, the overall number of direct dependencies is always reduced to the same amount, i.e. by 1. Therefore, metric rACD does only measure sensitivity concern- ing indirect dependencies.

Properties of metric rACD

name reduction metric based on metric ACD entity dependency

attribute effect on indirect dependencies category indirect metric

scale type rational scale

context ClassDependency::rACD() : Real post: if self.system.ACD() = 0 then result = 0

else result = 1 - self.system.removeDependency(self).ACD() / self.system.ACD()

140 Chapter 11: Metrics

3 The effect of indirect dependencies on the investigated attribute does not depend on the level of indirection.

4 Dependencies on concrete classes, abstract classes, and interfaces have the same effect on the investigated attribute. 5 The category of the dependency does not matter.

6 The dependencies can be removed without substitution. Discussion

Metric rACD only provides a rough evaluation of a dependency because it is based on simplifying assumptions. A more thor- ough evaluation of the effect of a given dependency on test tasks would require e.g. to consider the size and complexity of all classes during the calculation of the ACD values.

Ability to realize improvements

Possible improvements of system metrics, as indicated by the reduction metrics, can only be fully realized if the dependency can be removed without substitution (assumption 6).

Interpreting values of rACD

A high value of metric rACD is not bad per se: a well-designed system will always contain outstanding dependencies which e.g. connect subsystems and which therefore have a high rACD value. A high value of rACD only means, that it is worth to inves- tigate the related dependency closer because of possible large improvements to the dependency structure and testability if the dependency can and should be refactored.

Absolute versus relative metric definition

Note: whether metric ACD is defined as an absolute number (as in this work) or relative to the number of classes within the sys- tem does not have an effect on the metric rACD because the number of classes can be cancelled down in the formula of the reduction metric:

While the size of the system does not matter for reduction met- rics, a possible reduction of metric ACD by a particular value (e.g. 5%) may be more relevant in a larger system than in a smaller system.

Comparison with coupling metrics

Coupling metrics which take into account indirect coupling aren’t sensitive to dependency cycles (see Section 3.3.1) or to classes that play a pivotal role like hubs (see example below).

rA C D d C D D n --- C D D \{d} n --- --- C D D C D D \{d} --- = =

Chapter 11: Metrics 141

Example 21

Within the dependency graph shown in Figure 26, class

D

and

F

play the role of a hub, i.e. a class which, when removed from the system, breaks the dependency graph into independent sub- graphs.

We compare metric rACD with metric CBOi, which is derived from metric CBO (see Appendix C) by taking into account indi- rect dependencies: while metric rACD clearly indicates that the dependency between

D

and

F

is critical, metric CBOi is not able to highlight the critical classes.

Figure 26 Dependency graph

Table 5 Dependencies and values of rACD

‰ C F A H B D E G I dependency d CBOi of client class rACD(d) [%] Ao B 8 3.5 Ao C 3.5 Bo D 6 17.2 Bo E 0.0 Co D 6 20.7 Do E 5 6.9 Do F 55.2 Fo G 3 17.2 Fo H 0.0 Fo I 17.2 Go H 1 3.5

142 Chapter 11: Metrics