Source · Christian Ciceri et al., Software Architecture Metrics (O'Reilly)
Why this matters
Ciceri et al., Software Architecture Metrics, Introduction; Building Evolutionary Architectures 2eArchitects make claims like 'this design is too coupled' or 'that module lacks cohesion' — but claims without measures are just opinions, hard to defend and impossible to guard automatically. Metrics turn qualitative judgments about structure into objective numbers.
Measuring architecture lets you track decay over time, compare designs, set thresholds, and — crucially — feed those thresholds into fitness functions so the qualities you care about are enforced continuously rather than argued about in reviews.
The concept
Software Architecture Metrics, Ch. on coupling, cohesion, connascence & complexityCoupling measures interdependence. Afferent coupling (Ca) counts the incoming dependencies — how many other components depend on this one (a measure of responsibility; changing it is risky). Efferent coupling (Ce) counts the outgoing dependencies — how many components this one depends on (a measure of how much it can be broken by others). High coupling in either direction makes change harder.
Cohesion measures how strongly the elements inside a component belong together. High cohesion (a component doing one well-defined job) is desirable; low cohesion signals a component with unrelated responsibilities that probably wants splitting.
Connascence is a more precise vocabulary for coupling introduced by Meilir Page-Jones: two elements are connascent if a change in one requires a change in the other to keep the system correct. It has a type (e.g. connascence of name, type, position, meaning, execution order, timing) and two properties — strength (how hard it is to reason about and refactor) and locality (how close the elements are). The guidance: prefer weaker forms of connascence, and the further apart two elements are, the weaker their connascence should be.
Cyclomatic complexity measures the number of independent paths through a piece of code (roughly, decision points plus one). Higher values mean more branches, more test cases needed, and typically lower maintainability — a code-level metric that rolls up into architectural health.
Worked example
Software Architecture Metrics; connascence guidance (Page-Jones)Consider a 'Notifications' component. Ten other components call it (Ca = 10) and it depends on three (Ce = 3). Its high afferent coupling flags it as a load-bearing dependency: any breaking change ripples to ten callers, so it needs a stable contract and careful evolution.
Inside it, two methods send email and two compute tax — unrelated jobs, so cohesion is low; splitting tax out would raise cohesion in both resulting components. One method has nested conditionals giving a cyclomatic complexity of 14, well above a comfortable threshold, so it is flagged for refactoring and demands many test paths.
Finally, a caller passes arguments positionally to Notifications — connascence of position. Because the caller and callee live in different components (low locality), this relatively strong, distant connascence is exactly what the guidance says to reduce; switching to named parameters weakens it to connascence of name. Each judgment is now a number that a fitness function can watch: fail the build if Ca on a shared component or the cyclomatic complexity of any method crosses its threshold.
How it connects
Software Architecture Metrics; Building Evolutionary Architectures 2e; Learning DDDThese metrics quantify the coupling that The Hard Parts' decompositions create and that DDD's bounded contexts try to contain. They are the raw material of evolutionary fitness functions: a coupling or complexity threshold becomes an executable governance rule.
Connascence gives a precise language for the contract coupling seen in Communication Patterns, and cohesion echoes DDD's drive to keep a model's elements that change together, together. Measurement is what turns every earlier topic from advice into something you can enforce.
- Swapping afferent and efferent coupling. Afferent (Ca) = incoming dependencies (who depends on me); efferent (Ce) = outgoing (who I depend on). Mixing them inverts the risk analysis.
- Treating connascence as a single value. It has a type, plus two properties — strength and locality — and the guidance depends on both: distant elements should have weaker connascence.
- Assuming higher cyclomatic complexity is always unacceptable. It is a signal correlated with lower maintainability and more test paths, used against thresholds — not an absolute pass/fail on its own.
- Afferent coupling counts incoming dependencies; efferent coupling counts outgoing — both raise the cost of change.
- Cohesion measures how well a component's elements belong together (high is good); connascence is a precise coupling vocabulary with a type, strength, and locality — prefer weaker, and weaker still at distance.
- Cyclomatic complexity counts independent paths through code; metrics turn structural opinions into thresholds that fitness functions can enforce.