Cohesion
About
Cohesion refers to how closely related and focused the responsibilities of a single module, class, or component are. A highly cohesive module performs one well‑defined task or closely related set of tasks, while a low‑cohesion module handles many unrelated responsibilities.
High cohesion improves clarity, maintainability, and reusability because each module has a clear purpose.
Low cohesion, on the other hand, leads to "god classes" or overly complex modules that are harder to understand and modify.
In software design, the goal is to achieve high cohesion (strong internal focus) along with low coupling (minimal external dependency). These two metrics complement each other in creating a well‑structured, maintainable system.
Types of Cohesion
Cohesion is typically classified from worst (lowest) to best (highest):
Coincidental Cohesion (Worst)
Unrelated tasks are grouped in the same module.
Example: A utility class that contains random methods like file parsing, database queries, and logging.
Problem: No logical connection; makes maintenance harder.
Logical Cohesion
Functions that are related by a broad category but not by a specific task.
Example: A module handling all types of input (keyboard, file, network) in one place.
Problem: Still too general; often requires conditional logic to handle different cases.
Temporal Cohesion
Elements are related by the time they are executed.
Example: An initialization module that sets up unrelated resources at startup.
Problem: The tasks are only related by execution timing, not functionality.
Procedural Cohesion
Functions are related by the sequence of execution.
Example: A module that processes an order by first validating, then saving, then sending notifications—all in one method.
Problem: May still mix unrelated tasks even if they are executed together.
Communicational Cohesion
Functions operate on the same data or contribute to the same output.
Example: A report generation module that formats and outputs a given dataset.
Better: The tasks share the same data context.
Sequential Cohesion
Output from one part of the module becomes input for another part.
Example: A data processing pipeline where one function cleans the data and another analyzes it.
Better: There’s a direct functional link between steps.
Functional Cohesion (Best)
Every element in the module contributes to a single, well‑defined task.
Example: A
PaymentProcessor
class that handles only payment processing and nothing else.Best: Easy to maintain, test, and reuse.
Measuring Cohesion
Cohesion can be evaluated both qualitatively and quantitatively.
1. Qualitative Indicators
Signs of high or low cohesion can be observed during code reviews:
High Cohesion:
Each module/class has a clear, single responsibility.
Methods in the module operate on the same set of data.
Minimal unrelated logic is present.
Low Cohesion:
The module contains methods dealing with unrelated tasks.
Changes in one responsibility often require touching unrelated parts of the module.
Conditional logic exists to handle unrelated scenarios.
2. Quantitative Metrics
Several metrics attempt to measure cohesion numerically:
LCOM (Lack of Cohesion of Methods)
A high LCOM value indicates low cohesion.
Various formulas exist, but the core idea is to measure how often methods share common attributes.
TCC (Tight Class Cohesion) and LCC (Loose Class Cohesion)
TCC measures the percentage of method pairs directly connected through shared attributes.
LCC extends this to indirect connections.
SRP (Single Responsibility Principle) Adherence
While qualitative in nature, checking adherence to SRP indirectly measures cohesion.
Impact of Low Cohesion
Low cohesion means that a module handles too many unrelated responsibilities. This creates several long‑term problems:
Poor Maintainability
Changes to one responsibility often risk breaking unrelated functionality in the same module.
Developers must understand more unrelated code before making changes.
Reduced Readability
The module’s purpose becomes unclear, making it harder for new team members to understand its role.
Harder Testing
Unit tests become complicated because they must cover multiple, unrelated behaviors in one module.
Increased Risk of Bugs
Unrelated code sharing the same module may unintentionally interfere with each other’s behavior.
Limited Reusability
Modules with mixed responsibilities are harder to reuse in other contexts without bringing in unrelated logic.
Slower Development
Multiple developers working on unrelated parts of the same module may cause merge conflicts and delays.
In short: Low cohesion turns a module into a “dumping ground” for unrelated logic, making the system brittle, harder to extend, and more expensive to maintain.
Benefits of High Cohesion
High cohesion is a strong indicator of good design quality. It provides several advantages:
Clear Purpose
Each module has a single, well‑defined responsibility, making its role easy to understand.
Improved Maintainability
Changes are localized, reducing the chance of introducing unintended side effects.
Better Reusability
Highly cohesive modules can be reused in different systems without pulling in unrelated logic.
Simpler Testing
Unit tests are easier to write and maintain because they target one specific behavior.
Parallel Development
Teams can work on different cohesive modules with minimal interference.
Higher Quality Architecture
High cohesion complements low coupling, resulting in a system that is both modular and adaptable.
Strategies to Reduce Cohesion
If a module has low cohesion, we can apply the following strategies to improve it:
Apply the Single Responsibility Principle (SRP)
Ensure each module has only one reason to change.
Refactor Large Modules
Break down “god classes” or bloated services into smaller, focused units.
Group Related Behavior and Data
Keep functions and variables that operate on the same data within the same module.
Avoid Mixing Unrelated Logic
Separate different concerns (e.g., data access, business logic, presentation) into distinct layers.
Use Clear Naming
A module’s name should clearly reflect its purpose; rename or split it if the name becomes too broad.
Introduce Domain‑Driven Design (DDD) Boundaries
Align modules with well‑defined business domains or subdomains.
Remove Dead or Unused Code
Old, unused functionality reduces cohesion by adding unrelated responsibilities.
Last updated