Difference Between Cohesion and Coupling
Cohesion refers to what the class (or module) can do. Low cohesion would mean that the class does a great variety of actions - it is broad, unfocused on what it should do. High cohesion means that the class is focused on what it should be doing, i.e. only methods relating to the intention of the class.
Example of Low Cohesion:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
Example of High Cohesion:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
As for coupling, it refers to how related or dependent two classes/modules are toward each other. For low coupled classes, changing something major in one class should not affect the other. High coupling would make it difficult to change and maintain your code; since classes are closely knit together, making a change could require an entire system revamp.
Good software design has high cohesion and low coupling.
Cohesion is an indication of how related and focused the responsibilities of an software element are.
Coupling refers to how strongly a software element is connected to other elements.
The software element could be class, package, component, subsystem or a system. And while designing the systems it is recommended to have software elements that have High cohesion and support Low coupling.
Low cohesion results in monolithic classes that are difficult to maintain, understand and reduces re-usablity. Similarly High Coupling results in classes that are tightly coupled and changes tend not be non-local, difficult to change and reduces the reuse.
We can take a hypothetical scenario where we are designing an typical monitor-able ConnectionPool
with the following requirements. Note that, it might look too much for a simple class like ConnectionPool
but the basic intent is just to demonstrate low coupling and high cohesion with some simple example and I think should help.
- support getting a connection
- release a connection
- get stats about connection vs usage count
- get stats about connection vs time
- Store the connection retrieval and release information to a database for reporting later.
With low cohesion we could design a ConnectionPool
class by forcefully stuffing all this functionality/responsibilities into a single class as below. We can see that this single class is responsible for connection management, interacting with database as well maintaining connection stats.
With high cohesion we can assign these responsibility across the classes and make it more maintainable and reusable.
To demonstrate Low coupling we will continue with the high cohesion ConnectionPool
diagram above. If we look at the above diagram although it supports high cohesion, the ConnectionPool
is tightly coupled with ConnectionStatistics
class and PersistentStore
it interacts with them directly. Instead to reduce the coupling we could introduce a ConnectionListener
interface and let these two classes implement the interface and let them register with ConnectionPool
class. And the ConnectionPool
will iterate through these listeners and notify them of connection get and release events and allows less coupling.
Note/Word or Caution: For this simple scenario it may look like an overkill but if we imagine a real-time scenario where our application needs to interact with multiple third party services to complete a transaction: Directly coupling our code with the third party services would mean that any changes in the third party service could result in changes to our code at multiple places, instead we could have Facade
that interacts with these multiple services internally and any changes to the services become local to the Facade
and enforce low coupling with the third party services.
High cohesion within modules and low coupling between modules are often regarded as related to high quality in OO programming languages.
For example, the code inside each Java class must have high internal cohesion, but be as loosely coupled as possible to the code in other Java classes.
Chapter 3 of Meyer's Object-Oriented Software Construction (2nd edition) is a great description of these issues.