Low Cohesion
debt(d5/e7/b7/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list phpmetrics, phpmd, and phploc — all specialist static analysis tools. The LCOM4 > 2 metric from phpmetrics is a specialist measure, not caught by default linters or compilers. It requires deliberate setup and interpretation of metrics.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix describes extracting method groups into separate classes, but low cohesion classes (e.g., a UserService handling billing, reporting, and notifications) have callers throughout the codebase. Splitting a God class means updating injection sites, tests, and consumers across many files — this is cross-cutting by nature, not a single-component fix.
Closest to 'strong gravitational pull' (b7). Low cohesion classes tend to be load-bearing (UserService, helpers used everywhere) and every new feature is shaped by — and tends to worsen — the existing dumped-in design. As noted in why_it_matters, reuse becomes impossible and testing any one responsibility requires setting up all others, creating a persistent and widening productivity tax across the codebase.
Closest to 'notable trap' (t5). The misconception field describes a documented and common gotcha: developers believe physical co-location of related concepts equals cohesion, but cohesion is about shared purpose. A class mixing user authentication and email formatting 'seems' cohesive because both involve users, yet has low cohesion. This is a well-documented SOLID/OOP lesson that most developers eventually learn, placing it at t5.
Also Known As
TL;DR
Explanation
Cohesion measures how closely related the responsibilities of a module are. High cohesion: a class does one thing and all its methods work toward that single purpose. Low cohesion: a class mixes unrelated concerns — a UserService that also sends emails, processes payments, and generates PDF reports. Low cohesion is often the root cause of the God Class smell. The fix is decomposition: extract responsibilities into focused classes, guided by the Single Responsibility Principle.
Common Misconception
Why It Matters
Common Mistakes
- Adding utility methods to existing classes because it is convenient — create a dedicated utility class instead.
- Service classes that grow unbounded — UserService should not handle billing, reporting, and notifications.
- Static helper classes with dozens of unrelated methods — a sign of dumping ground design.
- Confusing low coupling (few dependencies) with high cohesion — they are independent dimensions.
Code Examples
// Low cohesion — UserService does everything:
class UserService {
public function register(array $data): User { /* ... */ }
public function sendWelcomeEmail(User $u): void { /* ... */ }
public function generateInvoicePdf(User $u): string { /* ... */ }
public function processSubscriptionPayment(User $u): void { /* ... */ }
public function exportUsersToCsv(): string { /* ... */ }
}
// High cohesion — each class has one purpose:
class UserRegistrationService {
public function register(array $data): User { /* ... */ }
}
class UserEmailService {
public function sendWelcomeEmail(User $u): void { /* ... */ }
}
class InvoiceGenerator {
public function generate(User $u): string { /* ... */ }
}
class SubscriptionPaymentService {
public function charge(User $u): void { /* ... */ }
}