Robert C.Martin wrote an interesting article about a set of metrics that can be used to measure the quality of an object-oriented design in terms of the interdependence between the subsystems of that design.

Here’s from the article what he said about the interdependence between modules:

What is it that makes a design rigid, fragile and difficult to reuse. It is the interdependence of the subsystems within that design. A design is rigid if it cannot be easily changed. Such rigidity is due to the fact that a single change to heavily interdependent software begins a cascade of changes in dependent modules. When the extent of that cascade of change cannot be predicted by the designers or maintainers the impact of the change cannot be estimated. This makes the cost of the change impossible to estimate. Managers, faced with such unpredictability, become reluctant to authorize changes. Thus the design becomes rigid.

And to fight the rigidity, he introduced metrics like Afferent coupling, Efferent coupling, Abstractness and Instability.

Let’s discover all these metrics and how they could be very useful to improve the design of applications. For that, let’s analyze jOOQ by JArchitect.

jOOQ (Java Object Oriented Querying) is a type safe SQL query builder modeling standard and vendor-specific SQL constructs directly in a Java fluent API.

And here’s the dependency graph between all jOOQ jars.

Afferent Coupling

The number of types outside this project that depend on types within this project.

Let’s execute the following CQLinq query to get the afferent coupling of jOOQ jars:

from p in Projects where !p.IsThirdParty select new { p,p.NbTypesUsingMe }

jooq-3.2.2 is the most used by the other jars.

Efferent Coupling

The number of types outside this project used by types of this project.

from p in Projects where !p.IsThirdParty select new { p,p.NbTypesUsed }

The efferent coupling and afferent coupling could be applied also on packages and types. For example, the efferent coupling for a particular type is the number of types it directly depends on. Types where TypeCe is very high are types that depend on too many other types. They are complex and in general have more than one responsibility.

Abstractness

The ratio of the number of internal abstract types (i.e., abstract classes and interfaces) to the number of internal types. The range for this metric is 0 to 1 , with A=0 indicating a completely concrete project and A=1 indicating a completely abstract project.

A = Na / Nc

Where:

A = abstractness of a module

Zero is a completely concrete module. One is a completely abstract module

Na = number of abstract classes in the module

Nc = number of concrete classes in the module

Let’s take as example the jooq-3.2.2 and search for all its abstract types.

from t in Types where t.IsAbstract || t.IsInterface select new { t, t.NbLinesOfCode }

jooq-3.2.2 has 811 types so the Abstractness is equal to 365/811 = 0.45, almost half of the jOOQ types are abstract.

Instability

The ratio of efferent coupling (Ce) to total coupling. I = Ce / (Ce + Ca). This metric is an indicator of the project’s resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable project and I=1 indicating a completely instable project.

I = Ce/(Ce + Ca)

I represent the degree of instability associated with a project.

Ca represents the afferent coupling, or incoming dependencies, and

Ce represents the efferent coupling, or outgoing dependencies

Abstractness vs Instability Graph and the Zone of Pain

To have more details about this graph, you can refer to the Robert C.Martin article.

Here’s the graph for jOOQ framework:

The idea behind this graph is that the more a code element of a program is popular, the more it should be abstract. Or in other words, avoid depending too much directly on implementations, depend on abstractions instead. By popular code element, I mean a project (but the idea works also for packages and types) that is massively used by other projects of the program.

It is not a good idea to have concrete types very popular in your code base. This provokes some Zones of Pains in your program, where changing the implementations can potentially affect a large portion of the program. And implementations are known to evolve more often than abstractions.

The main sequence line (dotted) in the above diagram shows how abstractness and instability should be balanced. A stable component would be positioned on the left. If you check the main sequence, you can see that such a component should be very abstract to be near the desirable line – on the other hand, if its degree of abstraction is low, it is positioned in an area that is called the “zone of pain”.

After the analysis of many Java frameworks with JArchitect, jOOQ is among the few ones where all the jars are inside the green zone, thanks to interfaces and abstract classes.