High-quality software is both valuable to the business and easy to change. While it’s simple to be dogmatic at either end of this spectrum, both goals are important to the business in the long run. Aiming for highly cohesive and loosely coupled code is key to finding the balance, but this concept can be tough to understand at first glance. So what does it actually mean?
High Cohesion, Loose Coupling characterizes software designed with a keen focus on Separation of Concerns, the foundation of effective, resilient, malleable, performant, secure, maintainable software.
High Cohesion describes the internals of a well-bounded module that consists of coupled elements working together to accomplish something, which improves the comprehensibility of the codebase at large. Such a module contains all the decision-making power necessary to do its job.
Loose Coupling means that with respect to a given change, one module can be changed without requiring a change in other modules.
Coupling inside a module leads to cohesion, while coupling outside a module leads to multiple modules that must be kept in sync to execute a given change, increasing the cost of such changes. It's all about where you draw the boundaries.
It's worth noting that a module is merely a distinct part of the system that performs some kind of important job and hides its inner workings from the rest of the system, according to David L. Parnas in his seminal paper on software modularization.
There are small-scale jobs and large-scale jobs, so this characterization of high-quality code applies equally to the system at every scale, from the smallest function to the entire application and beyond.
Updated on Oct 25, 2023: Inspired by Kent Beck's excellent conference talk on software design, I adjusted some of the language for clarity and added a paragraph to highlight the importance of where the boundaries are drawn.