Stability and Responsibility

Assume A is a class in program or package p.

clients(A) = the set of all classes in p that reference A.
providers(A) = the set of all classes in p that A references.

We are often only interested in the number of classes in each of these sets:

#clients(A) = the size of clients(A)
#providers(A) = the size of providers(A)

A responsible class has many clients. A stable class has few providers. Stable classes tend to be easier to reuse.

We could measure the responsibility and instability of a class A relative to a package or program p more formally as:

responsibity(A) = #clients(A)/#p
instability(A) = #providers(A)/#p

where:

#p = the number of classes in p

We can define the stability of a class as follows:

stability(A) = 1 – instability(A)

Exercise

Compute responsibility(X) and instability(X) for each class X in p, where p is the following program:

The Main Sequence

A general goal is that responsible classes should also be stable. For less responsible classes, for example classes in the application-specific level of the Reusability Hierarchy, views and error handlers, for example, instability isn't important because so few classes depend on these very specific types of classes.

We can state this more concretely by saying that if for any class A we plot the point

p(A) = (responsibility(A), stability(A))

Then p(A) should be as close as possible to the line:

stability = responsibility

This line is called the main sequence (from astronomy):

We can even measure the distance from p(A) to this line:

dist(A) = k * |responsibility(A) – stability(A)|

Where:

k = sqrt(0.5)

Proof:

Notice that dist = d/2 where d = the distance from (r, s) to (s, r), its reflection through the diagonal:

It's easy to show that d = h * |r – s| where h = sqrt(2).

Therefore

dist(A) = d/2 = h/2 * |r – s|
= (1/sqrt(2)) * |r – s|
= sqrt(0.5) * |r – s|

Deviance

A class is "deviant" if it is far away from the main sequence. Since k is a constant, we can define the deviance of class A as:

deviance(A) = |responsibility(A) – stability(A)|

Note that:

0 <= deviance(A) <= 1

Deviant classes (deviance near 1) should be red flags. These are unstable classes with too many responsibilities (giants) or stable classes with not enough to do (dwarfs).