Connascence
Connascence is a software quality metric and a taxonomy for the different kinds of coupling between code modules. Two components are connascent when a change to one would require a change to the other. Lower connascence means higher code quality. The concept was introduced by Meilir Page-Jones in What Every Programmer Should Know About Object-Oriented Design as a finer-grained successor to the older coupling and cohesion vocabulary, which spoke only of "tight" or "loose" coupling without distinguishing how the modules were coupled.
Each instance of connascence is judged on three properties: strength, degree, and locality. Strength is the type of the connascence, ranked from weak to strong. Weaker connascence is preferable because it is easier to refactor. Degree is how many occurrences of the connascence exist between the components. Locality is how far apart the components are. Connascence between distant modules is worse than connascence within a single module.
The most useful consequence of the three properties is the locality heuristic. Stronger forms of connascence are acceptable, even unavoidable, inside a single function or class where the coupling is visible in one place. The same forms become a liability when they cross module or codebase boundaries, where a change ripples to code the author may never see. The goal is not to eliminate connascence, which is impossible, but to keep it weak where it is far-reaching and allow it to be strong only where it is local.
Static and dynamic connascence
The nine types of connascence divide into two families. Static connascences can be detected by reading the source: name, type, meaning, position, and algorithm. Dynamic connascences only become apparent at run time: execution, timing, value, and identity. Static connascences are weaker as a class, because the coupling is visible to static analysis and the compiler. Dynamic connascences require reasoning about behavior, which makes them harder to find and harder to refactor.
The types
The types, in increasing strength, are as follows.
- Connascence of Name requires only that two components agree on the name of an entity. Renaming a method forces every caller to be updated, but nothing else about the callers need change. It is the weakest form and is unavoidable, since code refers to entities by label, which is why choosing good names matters.
- Connascence of Type requires that components agree on the type of an entity. In a statically typed language the compiler catches most violations. In a dynamically typed language the agreement is implicit, and a caller can silently pass the wrong kind of value.
- Connascence of Meaning (also called Connascence of Convention) requires that
components agree on the interpretation of a value. A magic number such as
2that means "administrator", or aNonereturn that means "not found", couples every reader to the same convention. Replacing the literal with a named constant, or replacing a primitive with a dedicated type that encapsulates its own meaning, weakens the connascence. The smell of modeling a rich domain concept with a bare primitive is known as primitive obsession. - Connascence of Position requires that components agree on the order of elements, such as the items in a positional argument list or the fields of a tuple. A change in the order forces a matching change at every call site. Replacing positional arguments or tuple fields with a named structure weakens the connascence to Connascence of Name.
- Connascence of Algorithm requires that components agree on an algorithm. A sender and receiver that must use the same checksum, the same character encoding, or the same validation rule are connascent in algorithm. Duplicating an algorithm across a database model, a web controller, and a front-end form couples three distant sites to a single decision.
- Connascence of Execution requires that the order of operations be respected.
Acquiring locks in one order and releasing them in another, or calling
setSubjectaftersend, are execution connascences. They are dynamic: the source may look innocuous while the run-time order is wrong. - Connascence of Timing requires that the timing of execution be respected, such as a producer that must publish before a consumer reads, or a debounce that must fire within a window. It is among the strongest forms because timing bugs are intermittent and hard to reproduce.
- Connascence of Value requires that several values change together. It often
appears between production code and tests: a test that asserts an object’s
initial state breaks if that initial value changes. Introducing an indirection
– an
InitialStatealias, for example – lets both sides refer to the same label instead of the same literal. - Connascence of Identity requires that several components reference the same entity instance, such as two parts of a program that must operate on the same singleton or the same cached object. It is the strongest form: the coupling is not to a value or a name but to identity itself.
Reducing connascence
The practical value of connascence is as a guide to decoupling. Stronger forms can often be refactored into weaker ones. Passing values by position can be replaced by passing them by name. Hidden assumptions captured by Connascence of Meaning can be made explicit through named constants or dedicated types. A duplicated algorithm can be extracted to a single shared function.
Reducing the strength of connascence is a concrete way to honor the Law of Demeter and other design principles. The taxonomy also maps onto the traditional coupling categories such as stamp coupling and control coupling, but refines them. Each traditional flavor of coupling can exhibit several types of connascence, and connascence names the stronger or weaker way a given dependency is expressed.
See also
- Coupling
- Cohesion
- Decoupling
- Encapsulation
- Law of Demeter
- Refactoring
- Stamp coupling
- Static analysis
- Design principles
References
- Page-Jones, Meilir (1996). What Every Programmer Should Know About Object-Oriented Design. Addison-Wesley.
- connascence.io. Connascence. https://connascence.io