How is Single Responsibility related to cohesion
In software engineering, Cohesion and the Single Responsibility Principle (SRP) represent two sides of the same architectural coin:
🟢 Junior Level
In software engineering, Cohesion and the Single Responsibility Principle (SRP) represent two sides of the same architectural coin:
- Cohesion (Internal Focus): Measures how closely related and focused the methods, fields, and responsibilities within a single class or module are to each other.
- Single Responsibility Principle (SRP): Formulates the architectural rule that a class must have one, and only one, reason to change (one business actor or stakeholder driving changes).
┌──────────────────────────────────────────────┬──────────────────────────────────────────────┐
│ Cohesion (Structural Metric) │ Single Responsibility Principle (Design Rule)│
├──────────────────────────────────────────────┼──────────────────────────────────────────────┤
│ Measures internal alignment of class members.│ Mandates that a class serves a single actor. │
│ High Cohesion: all methods share state/goal. │ Adhering to SRP naturally yields High │
│ Low Cohesion: isolated islands of logic. │ Cohesion across the codebase! │
└──────────────────────────────────────────────┴──────────────────────────────────────────────┘
The Direct Relationship
When you adhere strictly to SRP, a class solves one isolated business responsibility. Because all its methods operate on the same state variables toward that specific purpose, the class inherently achieves High Cohesion.
Conversely, when a class violates SRP (e.g., orchestrating persistence, formatting PDF documents, calculating taxes, and dispatching SMS notifications), its methods split into disjoint islands that share no state. This results in Low Cohesion.
Java Code Example
Low Cohesion (SRP Violation)
// Swiss-Army Knife: methods share no common purpose or internal fields
public class OrderManager {
private String databaseUrl;
private SmtpClient smtpClient;
private PdfGenerator pdfGenerator;
public void saveToDatabase(Order order) { /* Uses databaseUrl */ }
public void sendEmailConfirmation(Order order) { /* Uses smtpClient */ }
public byte[] generateInvoicePdf(Order order) { /* Uses pdfGenerator */ }
}
High Cohesion (SRP Compliant)
Decomposing the monolith into cohesive, focused units:
// Cohesion = 100%: All methods operate strictly on persistence transactions
public class OrderRepository {
private final DataSource dataSource;
public void save(Order order) { /* ... */ }
public Optional<Order> findById(UUID id) { /* ... */ }
}
// Cohesion = 100%: Strictly responsible for PDF document generation
public class OrderPdfInvoiceGenerator {
private final PdfTemplate template;
public byte[] generate(Order order) { /* ... */ }
}
🟡 Middle Level
Cohesion vs. Coupling: The Architectural Frontier
The primary design ideal across Object-Oriented architecture is “High Cohesion, Low Coupling”:
| Metric | Direction | Definition | Architectural Target |
|---|---|---|---|
| Cohesion | Internal (Intra-module) | How focused the elements within a class or package are on a single responsibility. | Maximize (High) |
| Coupling | External (Inter-module) | The degree of direct dependency and knowledge between separate classes or modules. | Minimize (Low) |
[Low Cohesion + High Coupling] [High Cohesion + Low Coupling]
(Chaos) (Clean Design)
┌──────────────────┐ ┌──────┐ ┌──────┐
│ A B C D │ │ A B │ │ C D │
└─┬──────────────┬─┘ └──┬───┘ └──┬───┘
│ │ │ │
▼ ▼ └──────►◄─────┘
[Module 1] [Module 2] Stable Interface
Glenford Myers’ 7 Levels of Cohesion
In classic structured design theory (Glenford Myers, Stevens & Constantine), cohesion is classified into seven discrete tiers, ranked from worst to best:
- Coincidental Cohesion (Worst 🔴): Class elements are bundled arbitrarily with no meaningful relation (e.g.,
CommonUtils,Helper,MiscManager). - Logical Cohesion (🔴): Methods are grouped by category of operation, but perform distinct tasks (e.g.,
InputReadercontainingreadFromKeyboard(),readFromNetwork(),readFromTape()). - Temporal Cohesion (🟠): Elements are executed at the same moment in time, but are conceptually unrelated (e.g.,
StartupManagerclearing temp files, verifying license tokens, and initializing logger). - Procedural Cohesion (🟡): Methods are grouped because they must execute in a specific sequential order, but manipulate disjoint data structures.
- Communicational Cohesion (🟡): Methods operate on the exact same input or output data structure (e.g.,
OrderRepositoryperforming CRUD operations on theOrderentity). - Sequential Cohesion (🟢): The output of one method serves directly as the input to the next method in a transformation pipeline (
ParseTokens$\rightarrow$ValidateAST$\rightarrow$GenerateBytecode). - Functional Cohesion (Best / SRP Ideal 🟢): Every element in the class contributes strictly to performing one, and only one, well-defined function (e.g.,
SHA256Hasher,BCryptPasswordEncoder).
🔴 Senior Level
Mathematical Cohesion Metrics: LCOM1 and LCOM4
Static analysis tools (SonarQube, JArchitect) mathematically quantify class cohesion using the LCOM (Lack of Cohesion of Methods) metric family:
LCOM1 (Chidamber & Kemerer, 1994)
Analyzes all unique pairs of methods in a class $(M_i, M_j)$:
- Let $P$ be the number of method pairs that share no common instance fields ($I_i \cap I_j = \emptyset$).
- Let $Q$ be the number of method pairs that share at least one instance field ($I_i \cap I_j \neq \emptyset$).
A high $P$ value indicates disjoint method clusters and a severe SRP violation.
LCOM4 (Hitz & Montazeri)
LCOM4 constructs an undirected graph:
- Vertices ($V$): Methods and instance variables of the class.
- Edges ($E$): An edge links two methods if they access a shared instance variable, or if one method directly invokes the other.
- Metric Output: The number of connected components in the graph.
SRP Cluster 1 (Component 1) SRP Cluster 2 (Component 2)
[Method 1] ─── (fieldA) ─── [Method 2] [Method 3] ─── (fieldB) ─── [Method 4]
===> Disjoint Graph (LCOM4 = 2). SRP VIOLATION! Requires refactoring into 2 classes.
- $\text{LCOM4} = 1$: Ideal cohesive class. All methods and fields are interconnected.
- $\text{LCOM4} \ge 2$: The class has fractured into independent subgraphs. The integer value directly dictates the exact number of independent classes into which the monolith should be decomposed!
Hardware Impact: False Sharing in Multi-Core Architectures
In high-throughput concurrent systems, low cohesion (a God Object aggregating multiple unrelated responsibilities) induces a critical hardware penalty known as False Sharing:
- CPU Cache Line Alignment: Modern CPUs fetch and invalidate memory in discrete 64-byte blocks (cache lines).
- The False Sharing Mechanism:
When a class merges disparate responsibilities into a single object, unrelated mutable fields reside side-by-side in contiguous heap memory (e.g.,
volatile long lastProcessedOrderIdandvolatile long emailBatchCounter).- Thread 1 (Order Worker) frequently writes to
lastProcessedOrderId. - Thread 2 (Email Dispatcher) frequently writes to
emailBatchCounter. - Although Thread 1 and Thread 2 manipulate distinct variables, both fields reside on the exact same 64-byte cache line.
- The CPU cache coherence protocol (MESI/MOESI) forces constant invalidation and bouncing of the cache line across CPU cores (Cache Line Bouncing), degrading performance by $10\times$ to $50\times$.
- Thread 1 (Order Worker) frequently writes to
- The SRP Solution: Refactoring into separate, highly cohesive classes partitions variables across independent heap allocations, eliminating hardware-level cache contention.
4 Tricky Questions
1. Can a class have maximum Cohesion (LCOM4 = 1) yet still severely violate SRP?
Answer: Yes. A prime example is an Anemic Domain Model entity or a massive DTO with 60 fields and 120 getters and setters. Because all getters and setters directly read and write the class’s fields, an automated LCOM tool will report near-perfect structural cohesion.
However, if that single entity is manipulated by five distinct business actors (e.g., Accounting, Inventory, Logistics, Marketing, and Customer Support), any change demanded by Marketing (e.g., modifying customer tier representation) risks breaking Accounting’s financial reports.
Conclusion: Cohesion measures internal code topology (methods to fields). SRP evaluates alignment with business actors and change boundaries.
2. Does blindly maximizing Cohesion lead to the “Atomic Dust” (Poltergeists) anti-pattern?
Answer:
Yes. If an engineering team pursues Functional Cohesion dogmatically to the extreme, they may decompose every three-line routine into its own class (OrderVatCalculator, OrderDiscountApplier, OrderTotalRounder).
This creates the Atomic Dust / Micro-Class Explosion anti-pattern:
- Intra-class cohesion is $100\%$, but system-wide Coupling skyrockets exponentially.
- To execute a routine checkout, a coordinator service must inject and orchestrate 25 micro-classes.
- Cognitive load and call stack depth increase dramatically.
Remedy: Domain-Driven Design (DDD) Aggregates establish balanced boundaries, grouping cohesive domain invariants together while keeping coupling low.
3. How does package organization (Package-by-Layer vs. Package-by-Feature) impact cohesion?
Answer:
- Package-by-Layer (
controllers,services,repositories): Exhibits Low Cohesion at the architectural level. Theservicespackage containsBillingService,CatalogService, andUserService. These classes share zero business domain concepts; their only commonality is their technical layer (Logical Cohesion). - Package-by-Feature (
order,billing,user): Exhibits High Cohesion. All classes within theorderpackage (OrderController,OrderService,OrderRepository,OrderEvents) focus on the exact same bounded context, evolve together, and can be extracted cleanly into an independent microservice.
4. What is the fundamental difference between Class Cohesion and Interface Cohesion?
Answer:
- Class Cohesion: Evaluated based on state sharing and algorithmic collaboration between concrete methods and internal fields (quantified via
LCOM). - Interface Cohesion: Interfaces have no instance state. Interface cohesion is evaluated by client consumption patterns: do clients actively use all declared methods together?
If an interface declares both
print()andscan(), but client $A$ only prints and client $B$ only scans, the interface possesses low cohesion and violates the Interface Segregation Principle (ISP).
🎯 Interview Cheat Sheet
30-Second Summary
- Core Link: SRP is the architectural rule defining why to separate classes (one actor, one reason to change). High Cohesion is the structural outcome (methods and fields collaborate toward a single goal).
- Golden Target: High Cohesion + Low Coupling.
- Myers Taxonomy: Functional (ideal) $\rightarrow$ Sequential $\rightarrow$ Communicational $\rightarrow$ Procedural $\rightarrow$ Temporal $\rightarrow$ Logical $\rightarrow$ Coincidental (worst).
- Mathematical Proof: $LCOM4 \ge 2$ signifies disjoint subgraphs and mathematically indicates that a class must be split into multiple classes.
- Hardware Impact: Low cohesion leads to False Sharing on 64-byte CPU cache lines across concurrent threads.
Common Follow-up Questions
- “How do you identify low cohesion in a code review without running SonarQube?” → Look for Swiss-Army knife class names (
Manager,Utils,Common), large numbers of constructor dependencies ($> 5$), or methods within the same class that operate on completely distinct sets of private fields. - “Why are utility classes like
StringUtilsacceptable despite having Logical Cohesion?” → They are pure, stateless, and do not hold business domain rules. Their convenience outweighs the theoretical penalty as long as they remain free of domain logic.
Red Flags (DO NOT Say)
- ❌ “Cohesion and Coupling mean the same thing.” (Cohesion is internal focus; Coupling is external interdependence).
- ❌ “An Anemic Entity with 100 getters and setters cannot violate SRP because its LCOM is 1.” (Structural cohesion does not equate to business actor isolation).
- ❌ “Every single method should be placed into its own class to achieve maximum cohesion.” (Produces Atomic Dust / Poltergeist anti-pattern, causing unmanageable coupling).
Related Topics
- What is Single Responsibility Principle and How to Apply It — SRP fundamentals
- What happens if a class has multiple reasons to change — Fragility from low cohesion
- How to refactor God Object — Decomposing low-cohesion classes
- How to determine if a class has single responsibility — Pragmatic heuristic checks