Skip to content

03 — Cohesion, Coupling & Dependencies

Driving question: When do metrics reveal design problems, and when do they merely count structure?

Learning objectives

  • Explain multiple forms of coupling and cohesion.
  • Interpret dependency metrics as proxies rather than ground truth.
  • Identify temporal, semantic, and change coupling from repository evidence.
  • Relate coupling to testability and change propagation.

Structural and evolutionary coupling

Two modules can be weakly coupled in the static dependency graph yet strongly coupled in practice if they nearly always change together. Conversely, a static dependency may be stable and harmless.

Useful evidence includes:

  • imports/calls/inheritance;
  • shared data schemas;
  • co-change frequency;
  • issue linkage;
  • runtime communication;
  • ownership boundaries.

A simple co-change score for files \(a\) and \(b\) can be expressed as:

\[ CC(a,b)=\frac{|changes(a) \cap changes(b)|}{|changes(a) \cup changes(b)|} \]

The metric is not a verdict; it is a clue about hidden dependencies.

Dependency direction

Dependency direction should reflect what is stable, policy-rich, or strategically important. A “low-level” persistence implementation depending on a domain interface can preserve domain independence even though calls flow the other way at runtime.

Design / research exercise

Mine 100–500 commits from a repository. Find a pair of files/classes with unexpectedly high co-change. Inspect whether the coupling is accidental, semantic, generated, test-related, or architectural.

Suggested reading

  • Robert C. Martin on coupling and package principles.
  • Research literature on logical/evolutionary coupling.