Coupling & Cohesion
The problem
As a codebase grows, some ways of organizing it make a single change ripple through dozens of unrelated files, while other ways keep related logic together and isolate the rest — the difference between the two is almost entirely a matter of coupling and cohesion, and it determines whether a codebase gets harder or easier to change over time.
Why now
Functions and scope already established hiding internals as the default, good practice at the function level; modules and bundling extended that same idea to files. Coupling and cohesion is the general vocabulary for judging how well that hiding principle is being applied across an entire system, not just one function or file.
Mental model
Cohesion asks 'do the things inside this unit belong together' — high cohesion means a module does one clear job. Coupling asks 'how much does this unit know about, and depend on, other units' internals' — low coupling means changing one module rarely forces changes elsewhere. The goal is always high cohesion, low coupling: related things grouped tightly, unrelated things touching each other as little as possible.
Requires
- Functions & ScopeProgramming Fundamentals
Coupling and cohesion generalize the hide-by-default principle already established for a single function's scope; you need that smallest-scale instance of encapsulation before judging it across modules, services, or an entire architecture.
- Modules & BundlingJavaScript Runtime
Modules are the concrete unit coupling and cohesion are most directly evaluated on — how much a module exposes, and how much it depends on another module's internals, is a direct extension of the file-level encapsulation already covered.
Unlocks
- Dependency Injection in .NET.NET Internals
- Code Review PracticesEngineering Practices
- RefactoringEngineering Practices
- Technical DocumentationEngineering Practices
- Technical Debt ManagementEngineering Practices
- SOLID PrinciplesLow-Level Design
- Layered Architecture & Separation of ConcernsSoftware Architecture
- Monolith vs. MicroservicesSoftware Architecture
Used in
- Code review judgment calls about whether a change belongs in an existing module or a new one
- Refactoring decisions — splitting an overly broad module, or merging artificially separated ones
- Every higher-level architecture decision in this domain, which is really coupling and cohesion applied at a larger scale
- Explaining why a 'small' change unexpectedly touched a dozen unrelated files
Projects
- Identify a tightly coupled pair of modules in a real codebase (one directly reaching into another's internals) and refactor them to communicate through a narrow, explicit interface instead
- Take a low-cohesion 'utils' file doing five unrelated things and split it into focused, single-purpose modules
Examples
- A billing module that directly reads and writes another module's internal database tables is tightly coupled — a schema change in one breaks the other unexpectedly
- A utils.js file containing date formatting, API calls, and validation logic has low cohesion — three unrelated concerns bundled together for no structural reason
Resources
Mastery checklist
- I can define coupling and cohesion and identify examples of each in real code
- I can refactor a tightly coupled pair of modules to communicate through a narrower interface
- I can split a low-cohesion module into focused, single-purpose ones
- I can explain why high cohesion and low coupling together make a codebase easier to change safely