Types of Cohesion
debt(d5/e5/b5/t5)
Closest to 'specialist tool catches' (d5). The term's detection_hints list phpmd and phpmetrics as tools that can identify cohesion issues, but automated detection is marked 'no' — these tools flag symptoms (large classes, many responsibilities) rather than directly measuring cohesion type. Recognising coincidental vs functional cohesion still requires human judgment.
Closest to 'touches multiple files / significant refactor' (e5). The quick_fix suggests splitting modules with low cohesion, which typically means extracting classes, moving methods, and updating all call sites. This is not a one-line fix but a focused refactoring effort within a component or set of related classes.
Closest to 'persistent productivity tax' (b5). The term applies across all contexts (web, cli, queue-worker) and is tagged as architectural. Poor cohesion choices compound over time — a coincidentally cohesive Utils class becomes a dumping ground that slows down multiple work streams, but it doesn't fully define the system's shape like a core architectural decision would.
Closest to 'notable trap' (t5). The misconception field states that developers believe 'any grouping of related code counts as good cohesion' when there's actually a spectrum. This is a documented gotcha — developers must learn that logical cohesion (grouping by layer) is worse than functional cohesion, but it's not as severe as concepts where the obvious approach is always wrong.
Also Known As
TL;DR
Explanation
Constantine's cohesion spectrum from weakest to strongest: Coincidental (elements grouped arbitrarily — a 'utils' class), Logical (logically similar actions — all I/O routines), Temporal (executed at the same time — startup code), Procedural (follow a sequence), Communicational (share data), Sequential (output of one feeds into next), Functional (all elements contribute to a single well-defined task — ideal). In practice aim for functional or communicational cohesion. Coincidental and logical cohesion produce the most brittle, untestable code. High cohesion combined with low coupling are the two primary structural quality objectives for any module.
Common Misconception
Why It Matters
Common Mistakes
- Accepting coincidental cohesion (random grouping) in utility classes without questioning whether the grouping makes sense.
- Temporal cohesion (things that run at the same time) masquerading as functional cohesion in initialisation classes.
- Not recognising that most 'Utils' or 'Helpers' classes exhibit coincidental or logical cohesion — split them.
- Targeting sequential or communicational cohesion as the goal when functional cohesion (single, well-defined purpose) is achievable.
Code Examples
// Coincidental cohesion — completely unrelated methods grouped together:
class Utils {
public function formatDate(DateTime $d): string { /* ... */ }
public function sendEmail(string $to, string $body): void { /* ... */ }
public function calculateTax(float $amount): float { /* ... */ }
// Nothing in common — should be 3 separate classes
}
// Types of cohesion (high to low):
// Functional (best) — every element contributes to ONE task
class EmailSender {
public function send(Email $email): void { /* SMTP logic only */ }
}
// Sequential — output of one element is input of next
class DataPipeline {
public function run(array $data): array {
return $this->validate($this->transform($this->load($data)));
}
}
// Coincidental (worst) — elements grouped by chance
class Utils { // anti-pattern: unrelated methods lumped together
public function sendEmail() {}
public function formatDate() {}
public function calculateTax() {}
}