Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesGood software design usually aims for high cohesion within modules and controlled, low coupling between them. Cohesion asks whether a module’s responsibilities belong together; coupling asks how strongly modules depend on one another, including whether a change in one forces changes in another. The goal is not to eliminate dependencies—modules must communicate—but to make boundaries and dependencies clear enough that changes stay manageable.
What coupling and cohesion mean
Coupling measures interdependence
Modules are coupled when they use one another’s functions or data, or when changing one requires changing another. Martin Fowler describes coupling in terms of this change impact: the practical concern is not that a dependency exists, but how it is arranged and controlled, particularly between larger parts of a system. His 2001 article on reducing coupling explains why communication is necessary while unmanaged dependencies can make changes travel farther than intended.
Cohesion measures whether responsibilities fit
A module is cohesive when its responsibilities support a clear, shared purpose. If it collects unrelated functions or data, its remit becomes harder to understand. Fowler discusses this problem in Linking Modular Architecture to Development Teams: unclear responsibilities and boundaries can make modules harder to reason about and change.
Why good design aims for high cohesion and controlled coupling
The familiar guideline is “low coupling between layers, high cohesion within them,” as Fowler puts it in Layering Principles. The Open University similarly treats coupling as a degree of interdependence and advises balancing coupling and cohesion in its introductory explanation.
#1 Best Overall
These are design directions, not numeric targets or a rule to split every system into the smallest possible pieces. Some coupling is the useful communication that lets modules work together. The aim is to prevent unnecessary dependencies from tying unrelated responsibilities and changes together, while keeping each module’s purpose understandable.
How the two forces affect changes
When dependencies spread change
If one domain’s change unexpectedly affects other domains, teams may need to understand several areas to make a safe update. That can happen when boundaries are unclear or dependencies expose details that other modules do not need. The risk is not simply “many dependencies”; it is dependencies that make unrelated parts change in lockstep.
Rank #2
When responsibilities blur
A module that does several unrelated jobs can be difficult to navigate because its purpose does not explain what belongs inside it. Changes may then be harder to locate, and the module’s responsibilities are harder to reason about as a whole.
Use boundaries to manage dependencies
Consider a user interface that directly depends on domain logic, which in turn directly depends on a database. Fowler’s package diagram in Reducing Coupling illustrates how a mapper or adapter boundary can alter that dependency arrangement. This is an example of a possible design, not evidence that every system needs a mapper. An abstraction is valuable when it isolates a meaningful change or clarifies a boundary; it can be needless complexity when it does neither.
Fowler recommends examining dependency patterns between larger architectural modules, and notes that a diagram can make those patterns easier to see. A useful diagram shows not just which pieces communicate, but where the important boundaries lie and which direction dependencies take.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.A practical way to review a design
- Trace a representative change. Ask which modules would need edits to implement a typical requirement. Look for areas that must change together despite having different responsibilities.
- Check responsibility fit. Can you describe the module’s purpose clearly, and do its functions and data support that purpose?
- Inspect dependency direction and visibility. Are dependencies explicit at important boundaries, and do they cross the system in a way that makes sense for the architecture?
- Weigh indirection against its cost. Does an interface, adapter, or mapper isolate a likely change or clarify ownership? If not, it may add complexity without a useful boundary.
These questions are qualitative review aids, not a standardized score. A design that has fewer dependencies is not automatically better if it becomes harder to understand or communicate through; judge whether the dependencies and responsibilities fit the changes the system needs to support.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




