Loading
Loading
Foundations
The two measurements every later principle is a special case of.
By the end of this chapter
Concept
How strongly the things inside one type relate to each other. A type whose fields and methods all serve one job is cohesive. A type holding a database connection, a date formatter and a discount rule is not.
Concept
How much one type must know about another to work. If changing B's internals forces a change in A, A is tightly coupled to B.
Nearly every principle later in this track is one of these two wearing a specific hat. Single Responsibility is cohesion. Dependency Inversion is coupling. Interface Segregation is both.
| Kind | Looks like | Why it bites |
|---|---|---|
| Concrete | A holds a `new StripeGateway()` | B cannot be swapped or faked in a test |
| Structural | A reads `b.getC().getD().value` | A breaks when C or D changes shape |
| Temporal | `init()` must be called before `use()` | Nothing in the type system says so |
| Shared mutable state | Both write the same object | Order of operations becomes load-bearing |
Structural coupling has a well-known rule of thumb: talk only to your immediate neighbours. A chain like order.getCustomer().getAddress().getPostcode() means the caller knows the shape of three types it has no business knowing. Asking the order for what you actually want — its delivery postcode — leaves one relationship instead of three.
Suppose PaymentProcessor constructs a StripeGateway directly. That is concrete coupling, and the usual fix is to define a PaymentGateway interface and have the processor depend on it instead.
Notice what happened. The processor is now coupled to an interface you own rather than to a vendor's class — but something, somewhere, still has to decide that the real gateway is Stripe. The coupling moved to the composition root, where it is one line that is easy to find and easy to change. It did not disappear.
Sign in to keep a note here. It is free, and nobody else can see it.
Sign inWhat this chapter was for: