skip to content

In software design, what do the terms "cohesion" and "coupling" mean, and what is the standard rule of thumb about them?

level: juniorimportance: must knowfreq 88%

answer

  1. Cohesion = inside; coupling = between
  2. High cohesion, low coupling
  3. Blast radius of a change
  4. Name it without saying "and"
  5. Weakest sufficient dependency, not zero

basics

~10 s

Cohesion is how strongly the things inside one module belong together. Coupling is how much one module depends on another. The rule: aim for high cohesion inside modules and low coupling between them.

solid answer

~50 s

Cohesion measures internal relatedness: do all the elements of a module (functions, data, classes) serve one clear purpose? Coupling measures inter-module dependency: how much must module A know about module B's internals, and how likely is a change in B to force a change in A? The design heuristic is high cohesion, low coupling. High cohesion makes a module understandable, nameable, testable and reusable as a unit; low coupling makes change local, so a bug fix or refactor does not ripple across the system. The two are related: when related behaviour is scattered across modules, cohesion is low and coupling is forced up, because the scattered parts must keep talking to each other. Both are qualitative gradients, not booleans — the practical question in review is "is this the most cohesive grouping and the weakest dependency that still does the job?"

go deeper

for a junior

Define both in one sentence each and state the rule "high cohesion, low coupling", with a concrete example such as a Utils grab bag versus a focused PriceCalculator.

for a middle

Add that both are spectra with named levels, connect cohesion to SRP, and give real smells: shotgun surgery, divergent change, long getter chains.

for a senior

Frame coupling in terms of change propagation and blast radius, point out that the two measures trade against each other, and stress depending on stable abstractions rather than volatile details.

for a principal

Discuss boundaries as economic decisions: cohesion aligned to axes of change and team ownership (Conway's Law), coupling classified by cost of the change it propagates, and the failure mode of splitting badly into a distributed monolith.

## The two words A **module** here is any unit of grouping — a function, a class, a package, a service, a deployable component. The two classic quality measures of a modular decomposition, introduced by Larry Constantine in the 1960s–70s (structured design) and still the vocabulary used today, are cohesion and coupling. **Cohesion — internal.** How closely related are the responsibilities *inside* one module? A module with high cohesion does one thing. You can name it in a short noun phrase without "and": `PriceCalculator`, `InvoiceRepository`. A module with low cohesion is a grab bag: `Utils`, `Helpers`, `Manager` — you can only name it with vague words or a list. **Coupling — external.** How much does one module depend on another? Coupling is a property of a *pair* (or a graph) of modules. Key question: **if B changes, how likely is A to break or need editing?** The more A relies on B's internal details (fields, table schema, order of calls, global state), the tighter the coupling. ## The rule and why it holds > Maximise cohesion within modules, minimise coupling between them. Why it matters, concretely: - **Change locality.** The whole point of modularity (David Parnas, 1972) is that a design decision likely to change should be hidden inside one module, so a change touches one place. Low coupling = small blast radius. - **Comprehension.** A cohesive module can be understood without reading the rest of the system. Low cohesion forces you to hold unrelated concerns in your head at once. - **Testing.** Low coupling means fewer collaborators to stub/mock; high cohesion means the tests for one behaviour live in one place. - **Reuse and replacement.** You can only reuse or swap out a unit that has one purpose and few incoming assumptions. - **Parallel work.** Teams can work independently only if their modules do not constantly force each other to change (this is the design half of Conway's Law). ## The two are coupled to each other They are not independent knobs. If you split one concern across three modules, each module is now less cohesive *and* the three must communicate constantly, raising coupling. Conversely, if you smash everything into one giant module, coupling between modules drops to zero — but internal cohesion collapses and you have just hidden the coupling inside the module, where no tool can see it. This is why "zero coupling" is not the goal: a system of modules that never talk does nothing. The goal is the **weakest sufficient dependency**. ## Degrees, not booleans Both are spectra with classic named levels: - Cohesion, worst → best: coincidental, logical, temporal, procedural, communicational, sequential, **functional**. - Coupling, worst → best: content, common, external, control, stamp, **data** (plus "message coupling" / no coupling at the far end). You do not need to recite these in most interviews, but knowing they are ordered scales shows you understand these are gradients you move along, not properties you toggle. ## Smells of getting it wrong - A change to one feature requires editing five files in five packages → low cohesion (**shotgun surgery**). - One module has to change for many unrelated reasons → low cohesion (**divergent change**); this is the same idea as the Single Responsibility Principle. - A module reaches through another object's fields: `order.getCustomer().getAddress().getCity()` → high coupling (**inappropriate intimacy** / violation of the Law of Demeter). - Two services share a database table and both write it → high coupling (common coupling) even though there is no code-level import. ## Edge cases and nuance - **Coupling is unavoidable and sometimes desirable.** Depending on a *stable abstraction* (an interface, a versioned contract) is cheap coupling. Depending on a *volatile implementation detail* is expensive coupling. Judge coupling by the likelihood and cost of the change it propagates, not by counting arrows. - **Cohesion is relative to the axis of change.** Robert Martin's phrasing of SRP — "gather things that change for the same reason, separate things that change for different reasons" — makes cohesion depend on *who asks for changes*, not on surface similarity. Two functions that both format text may look similar yet belong apart if one serves accounting and the other serves marketing. - **Distributed systems do not fix coupling.** Splitting a tangled codebase into services over HTTP converts compile-time coupling into runtime coupling, usually making it worse (the "distributed monolith"). The decomposition must follow cohesive boundaries first.

  • Can coupling ever be zero, and would that be good?
    Only for modules that never interact — and a system of modules that never interact does no useful work. Some coupling is inherent; the goal is to make it weak, explicit and directed toward stable abstractions rather than volatile details.
  • How do cohesion and coupling relate to the Single Responsibility Principle?
    SRP is essentially a cohesion rule stated in terms of change: a module should have one reason to change, i.e. one set of stakeholders. Following it raises cohesion, and because related behaviour stops being scattered, it also tends to lower coupling.
  • Give a code-level smell for each.
    Low cohesion: a `Utils` class or a class that must change for both billing and rendering reasons (divergent change). High coupling: one class navigating another's internals via long getter chains, or two modules sharing mutable global state.

Think of a toolbox versus a junk drawer. A cohesive module is the drawer that holds only screwdrivers — you know what is in it from the label. Coupling is how many other drawers you must open to finish one job: if changing a light bulb needs the screwdriver drawer, the fuse box and the neighbour's key, the design is tightly coupled.

saying these in an interview costs you the question

  • Swapping the definitions — saying cohesion measures dependencies between modules.
  • Claiming the goal is zero coupling; a system whose modules never interact does nothing.
  • Treating them as booleans rather than gradients with named levels.
  • Believing that splitting into microservices automatically lowers coupling.
  • Assuming a small file is cohesive — size is not relatedness.

context