# Coupling and cohesion

> Keep things that change together in one place (high cohesion) and minimise what each part knows about the others (low coupling).

Concept · Code design · https://levelcode.org/concepts/coupling-and-cohesion

**Coupling** measures how much one module depends on another's details. **Cohesion** measures how closely the contents of one module belong together. The goal, stated by Larry Constantine in the 1970s and still the best single test of a design, is **low coupling and high cohesion**: changes stay local, and each module is understandable on its own.

## Coupling, from worst to best

| Kind | What's shared | Example |
| --- | --- | --- |
| Content | One module edits another's internals | reaching into another package's unexported state via reflection |
| Common | Global mutable state | a package-level `var currentConfig` many modules write |
| Control | A flag telling another module what to do | `Render(doc, true)` |
| Stamp | A large structure when only a field is needed | passing a whole `User` to compute a display name |
| Data | Only the values needed | `DisplayName(first, last string)` |
| Message | Calls through a narrow interface or events | publishing `OrderPaid` |

Coupling can also be **temporal** (things must happen in a particular order) or hidden in shared databases, file formats and assumptions — a column two services both write is coupling, even with no import between them.

## Cohesion

A cohesive module's parts change for the same reason. `billing` holding invoices, tax rules and payment retries is cohesive. `utils` holding date formatting, HTTP retries and a slug generator has only **coincidental** cohesion — the parts are together because someone had to put them somewhere. Low cohesion shows up as **divergent change** (one file edited for unrelated reasons); high coupling shows up as **shotgun surgery** (one change touches many files).

## Using it

- Group code by feature, not by technical layer — see [package by feature](https://levelcode.org/concepts/package-by-feature).
- Depend on small interfaces rather than concrete types ([dependency inversion](https://levelcode.org/concepts/dependency-inversion)).
- Pass only the data a function needs.
- Ask of every change: how many places did I have to touch, and did they belong together?

Zero coupling isn't the goal — modules that never interact do nothing useful. The aim is to make each dependency deliberate, narrow and stable. The [design principles lesson](https://levelcode.org/roadmaps/software-engineer/design-principles) builds the other principles on this pair.
