Connascence: A Look at Object-Oriented Design in Java
Want to learn more about how to implement connascence in Java? Check out this post to learn more about object-oriented design and connascence.
Join the DZone community and get the full member experience.
Join For FreeLately, at Codesai, we've been studying and applying the concept of connascence in our code and have provided an introductory talk about it.
1. Introduction
The concept of connascence is not new at all. Meilir Page-Jones introduced it in 1992 in his paper Comparing Techniques by Means of Encapsulation and Connascence. Later, he elaborated more on the idea in his What Every Programmer Should Know About Object-Oriented Design book from 1995, and its a more modern version of (same book but using UML) Fundamentals of Object-Oriented Design in UML from 1999.
Ten years later, Jim Weirich brought connascence back from oblivion in a series of talks: Grand Unified Theory of Software Design, The Building Blocks of Modularity, and Connascence Examined. As we'll see later in this post, he did not only bring connascence back to life but also improved its exposition.
More recently, Kevin Rutherford wrote a very interesting series of posts, in which he talked about using connascence as a guide to choose the most effective refactoring and how connascence can be a more objective and useful tool than code to identify design problems [1].
2. What Is Connascence?
The concept of connascence appeared in the early nineties when object-oriented programming was starting its path to becoming the dominant programming paradigm, as a general way to evaluate design decisions in an object-oriented design. In the previous dominant paradigm, structured programming, fan-out, coupling, and cohesion were fundamental design criteria used to evaluate design decisions. To make clear what Page-Jones understood by these terms, let's see the definitions he used:
Fan-out is a measure of the number of references to other procedures by lines of code within a given procedure.
Coupling is a measure of the number and strength of connections between procedures.
Cohesion is a measure of the "single-mindedness" of the lines of code within a given procedure in meeting the purpose of that procedure.
According to Page-Jones, this set of design criteria governs the interactions between the levels of encapsulation that are present in structured programming, including level-1 encapsulation (the subroutine) and level-0 (lines of code), as can be seen in the following table from the Fundamentals of Object-Oriented Design in UML.
To: |
level-0 construct (line of code) |
level-1 construct (procedure) |
From: |
||
level-0 construct (line of code) |
Structured Programming |
Fan-out |
level-1 construct (procedure) |
Cohesion |
Coupling |
However, object-oriented programming introduces at least level-2 encapsulation (the class), which encapsulates level-1 constructs (methods) with attributes. This introduces many new interdependencies among encapsulation levels, which will require new design criteria to be defined (see the following table from Fundamentals of Object-Oriented Design in UML showing the relationship between encapsulation levels and design criteria in object-oriented designs).
To: |
level-0 construct (line of code) |
level-1 construct (procedure) |
level-2 construct (class) |
From: |
|||
level-0 construct (line of code) |
Structured Programming |
Fan-out |
- |
level-1 construct (procedure) |
Cohesion |
Coupling |
- |
level-2 construct (class) |
- |
Class cohesion |
Class Coupling |
Two of these new design criteria are class cohesion and class coupling, which are an analog to the structured programing's procedure cohesion and procedure coupling, but, as you can see, there are other ones in the table that don't even have a name.
Connascence is meant to be a deeper criterion behind all of them, and, as such, it is a general way to evaluate design decisions in an object-oriented design. This is the formal definition of connascence by Page-Jones:
Connascence between two software elements A and B means either:
1. You can postulate some change to A that would require B to be changed (or at least carefully checked) in order to preserve overall correctness, or
2. You can postulate some change that would require both A and B to be changed together in order to preserve overall correctness.
In other words, there is connascence between two software elements when they must change together for the software to keep working correctly.
We can see how these new design criteria can be used for any of the interdependencies among encapsulation levels present in an object-oriented design. Moreover, it can also be used for higher levels of encapsulation (packages, modules, components, bounded contexts, etc). In fact, according to Page-Jones, connascence is applicable to any design paradigm with partitioning, encapsulation, and visibility rules [2].
3. Forms of Connascence
Page-Jones distinguishes several forms (or types) of connascence. Connascence can be static when it can be assessed from the lexical structure of the code or dynamic when it depends on the execution patterns of the code at run-time.
There are several types of static connascence:
- Connascence of Name (CoN): this is when multiple components must agree on the name of an entity.
- Connascence of Type (CoT): this is when multiple components must agree on the type of an entity.
- Connascence of Meaning (CoM) or Connascence of Convention (CoC): this is when multiple components must agree on the meaning of specific values.
- Connascence of Position (CoP): this occurs when multiple components must agree on the order of values.
- Connascence of Algorithm (CoA): this is when multiple components must agree on a particular algorithm.
There are also several types of dynamic connascence:
- Connascence of Execution (order) (CoE): this is when the order of execution of multiple components is important.
- Connascence of Timing (CoTm): this occurs when the timing of the execution of multiple components is important.
- Connascence of Value (CoV): this occurs when there are constraints on the possible values some shared elements can take. It's usually related to invariants.
- Connascence of Identity (CoI): this happens when multiple components must reference the entity.
Another important form of connascence is contranascence, which exists when elements are required to differ from each other (e.g., have different names in the same namespace or be in different namespaces, etc). Contranascence may also be either static or a dynamic.
4. Properties of Connascence
Page-Jones talks about two important properties of connascence that helps measure its impact on maintainability:
- Degree of explicitness: the more explicit a connascence form is, the weaker it is.
- Locality: connascence across encapsulation boundaries is much worse than connascence between elements inside the same encapsulation boundary.
A nice way to reformulate this is using what is called the three axes of connascence [3]:
Degree
The degree of an instance of connascence is related to the size of its impact. For instance, a software element that is connascent with hundreds of elements is likely to become a larger problem than one that is connascent to only a few.
Locality
The locality of an instance of connascence talks about how close the two software elements are to each other. Elements that are close together in the same encapsulation boundary should, typically, present higher forms of connascence than the elements that are far apart and in different encapsulation boundaries. In other words, as the distance between software elements increases, the forms of connascence should be weaker.
Strength
Page-Jones states that connascence has a spectrum of explicitness. The more implicit a form of connascence is, the more time consuming and costly it is to detect. Also, a stronger form of connascence is usually harder to refactor. Following this idea, we find that stronger forms of connascence are harder to detect and/or refactor.
This is why static forms of connascence are weaker and easier to detect than the dynamic ones. For example, let's take a look at why CoN is much weaker and easier to refactor than CoP.
The following figure by Kevin Rutherford shows the different forms of connascence that we saw before but sorted by descending strength.
Connascence, Design Principles, and Refactoring
Connascence is simpler than other design principles, such as the SOLID principles, Law of Demeter, etc. In fact, it can be used to see those principles in a different light, meaning they can be seen using more fundamental principles like the ones in the first chapter of Kent Beck's Implementation Patterns book.
We use code smells, which are a collection of code quality antipatterns, to guide our refactorings and improve our design, but, according to Kevin Rutherford, they are not the ideal tool for this task [4]. Sometimes, connascence might be a better metric for coupling than the somewhat-fuzzy concept of code smells.
Connascence gives us a more precise vocabulary to talk and reason with coupling and cohesion [5] and, thus, helps us to better judge our designs in terms of coupling and cohesion and decide how to improve them. In the words of Gregory Brown,
"this allows us to be much more specific about the problems we're dealing with, which makes it it easier to reason about the types of refactorings that can be used to weaken the connascence between components."
It provides a classification of forms of coupling in a system and, even better, a scale of the relative strength of the coupling each form of connascence generates. It's precisely that scale of relative strengths what makes connascence a much better guide for refactoring. As Kevin Rutherford says, "because it classifies the relative strength of that coupling, connascence can be used as a tool to help prioritize what should be refactored first." Connascence explains why performing a given refactoring is a good idea.
How Should We Apply Connascence?
Page-Jones offers three guidelines for using connascence to improve systems maintainability:
1. Minimize overall connascence by breaking the system into encapsulated elements.
2. Minimize any remaining connascence that crosses encapsulation boundaries.
3. Maximize the connascence within encapsulation boundaries.
According to Kevin Rutherford, the first two points conforms to what he calls the Page-Jones refactoring algorithm [6].
These guidelines generalize the structured design ideals of low coupling and high cohesion is applicable to object-oriented designs or, as it was said before, to any other paradigm with partitioning, encapsulation, and visibility rules.
This might still be a little subjective, so some of us prefer a more concrete way to apply connascence using Jim Weirich's two basic principles:
- Rule of Degree: convert strong forms of connascence into weaker forms of connascence [7].
- Rule of Locality: as the distance between software elements increases, using weaker forms of connascence.
Footnotes
[1] See Kevin Rutherford's great post The Problem With Code Smells
[2] This explains the titles Jim Weirich chose for his talks Grand Unified Theory of Software Design and The Building Blocks of Modularity
[3] See the webinar Connascence How to Measure Coupling by Nick Hodges.
[4] Again, see Kevin Rutherford's post The Problem With Code Smells
[5] The concepts of coupling and cohesion can be hard to grasp — just see this recorded debate about them, Understanding Coupling and Cohesion.
[6] See Kevin Rutherford's post The Page-Jones Refactoring Algorithm
[7] Even though he used the word degree, he was actually talking about strength.
References
Books
- Fundamentals of Object-Oriented Design in UML, Meilir Page-Jones
- What Every Programmer Should Know About Object-Oriented Design, Meilir Page-Jones
- Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design, Edward Yourdon and Larry L. Constantine
Papers
- Comparing Techniques by Means of Encapsulation and Connascence, Meilir Page-Jones
Talks
- The Building Blocks of Modularity, Jim Weirich (slides)
- Grand Unified Theory of Software Design, Jim Weirich (slides)
- Connascence Examined, Jim Weirich
- Connascence Examined (a newer version that goes into considerable detail about the various types of connascence), Jim Weirich (slides)
- Understanding Coupling and Cohesion debate, Corey Haines, Curtis Cooley, Dale Emery, J. B. Rainsberger, Jim Weirich, Kent Beck, Nat Pryce and Ron Jeffries
- Red, Green, ... now what ?!, Kevin Rutherford (slides)
- Connascence, Fran Reyes and Alfredo Casado (slides)
- Connascence: How to Measure Coupling, Nick Hodges
Posts
- Connascence as a Software Design Metric, Gregory Brown
- The Problem With Code Smells, Kevin Rutherford
- A Problem With Primitive Obsession, Kevin Rutherford
- The Page-Jones Refactoring Algorithm, Kevin Rutherford
- Connascence – Some examples, Mark Needham
Others
Published at DZone with permission of Manuel Rivero. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments