Saturday, January 8, 2011

An Ontology of Coupling

Any programmer worth his coffee knows about coupling. So, why do we often see tightly coupled programs?

Well, "coupling is unavoidable. What we are most interested in when exploring coupling within IT automation is how close this relationship actually is or should be" [1].

What is coupling? "Coupling is a measure of interconnection among modules in a program structure" according to Pressman [2].

Let's be pedantic and ask: what is a module? Pressman again: "Software is divided into separately named and addressable components, called modules, that are integrated to satisfy problem requirements" [3].

[ASIDE: Pressman makes a point about why this is important by expressing human frailty in mathematical terms: "Let C(x) be a function that defines the perceived complexity of a problem x ... For two problems p1 and p2 ... [an] interesting characteristic has been uncovered through experimentation in human problem solving . That is C (p1 + p2) > C(p1) + C(p2)". That is, human comprehension of complexity can be modeled as a non-linear system.]

The reason I am being pedantic is that most programmers think about coupling between classes. But it could be between any parts of the code base since the term module is sufficiently ambiguous.

Case in point: there was a requirement for different Spring beans in our application depending on whether the app was running in London or New York. The developer decided to write two Spring config XML files each describing the beans required. Which was loaded depended on a command line switch that explicitly stated the file name.

Although this worked, it added unnecessary coupling. All the start-up shell scripts across Dev, QA and Prod in London and New York had to change.

And that's the problem with too much coupling in enterprise applications. It doesn't break the compile and the application will work. It's just costly to maintain.

Another solution was to define one of our classes as a factory in the Spring XML config. This class could determine in which city it was running and return an object of the correct class (both NY and London classes had the same interface).

This is a better solution since the many (admittedly disorganized) start-up scripts did not require changing.

Gradations of Coupling

Pressman's scale of coupling looks like this (ordered from loose to tight):

Data coupling - Simple arguments are passed between modules.

Stamp coupling - Data structures are passed.

Control coupling - "A variable that controls decisions in a subordinate or superordinate module" is passed.

External coupling - "When modules are tied to an environment external to software. For example I/O couples a module to specific devices, formats and communication protocols".

Common coupling - "When a number of modules reference a global data area".

Content coupling occurs when one modules makes use of data or control information maintained within the boundary of another module.

If the original solution had passed a flag describing which city the software was running in, it would be an example of control coupling. But by passing the file name of the XML, this was content coupling; the shell script had to know not only that the app was storing beans in an auxiliary file but how Spring loaded this file (relative to the original Spring config file as it happens).

Steve McConnell calls this last and most insidious kind of coupling "Semantic Coupling".

"Semantic coupling is dangerous because changing code in the used module can break code in the using module in ways that are completely undetectable by the compiler. When code like this breaks, it breaks in subtle ways that seem unrelated to the change made in the used module, which turns debugging into a Sisyphean task." [4]

Another example of this in my current work place is an entitlement system that takes key/value pairs to determine the access rights of a user. The problem with this is what if the system is updated and needs more or different key/value pairs? Since this is not detected by the compiler and all calling code breaks in subtle ways, this is a reasonable example of McConnell's Semantic Coupling.

I would argue that a better solution would be to pass the unique ID of the user and just let the service work our what was needed.

Conclusion

Semantic coupling seems to be not as well known as it should be. Most programmers are familiar with syntactic coupling (change an interface and the class that depends on it may break). Semantic coupling is much more subtle and even hardened engineers get it wrong.


[1] SOA Principles of Service Design (p165), Thomas Erl
[2] Software Engineering A Practitioner's Approach (p375), Fourth Edition, Robert S Presman,
[3] ibid, p365
[4] Code Complete, Second Edition (p32), Steve McConnell

No comments:

Post a Comment