Stable Abstractions Principle is your friend to fight the design rigidity.

Robert C.Martin wrote an interesting article about a set of metrics that can be used to measure the quality of 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 introduces metrics like Afferent coupling, Efferent coupling, Abstractness, Instability and the “distance from main sequence”. Let’s go inside jOOQ to discover all these metrics and how they could be very useful to improve the design of your application.

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

Here’s the dependency graph of all the jOOQ jars

jooq1

Afferent Coupling:

The number of types outside this project that depends on types within this project. High afferent coupling indicates that the concerned projects have many responsibilities. 

Here are the values of this metric for the jOOQ jars:

jooq2

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

Efferent Coupling

The number of types inside this project that depends on types outside this project. High efferent coupling indicates that the concerned project is dependent.

Here are the values of this metric for the jOOQ jars:

jooq3
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 an 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 }

jooq4

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

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

Distance from main sequence (D)

The perpendicular normalized distance of a project from the idealized line A + I = 1 (called main sequence). This metric is an indicator of the project’s balance between abstractness and stability. A project squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal projects are either completely abstract and stable (I=0, A=1) or completely concrete and instable (I=1, A=0). The range for this metric is 0 to 1, with D=0 indicating a project that is coincident with the main sequence and D=1 indicating a project that is as far from the main sequence as possible. The picture in the report reveals if a project is in the zone of pain (I and A both close to 0) or in the zone of uselessness (I and A both close to 1).

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

AbstractnessVSInstability

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”.

jOOQ has all the jars inside the green zone, thanks to interfaces and abstract classes.