Types of Coupling
debt(d7/e5/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). The term's detection_hints indicate automated detection is 'no'. Identifying coupling types (content, common, control, stamp, data) requires human judgment during code review. No static analysis tools reliably detect these architectural patterns; a developer must understand the semantic relationships between modules to classify the coupling type.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix is vague ('review documentation'), but common_mistakes reveal fixes like splitting control-coupled methods into two separate methods, eliminating global mutable state, or refactoring Reflection hacks. These are not one-line fixes but targeted refactors within specific components. Worse cases (content coupling via public properties throughout) could push toward e7.
Closest to 'strong gravitational pull' (b7). Coupling types represent foundational architectural patterns that apply across web and cli contexts. Once content or common coupling pervades a codebase, every future change must navigate around it. The choice to allow or prevent specific coupling types shapes how modules interact system-wide, creating persistent architectural gravity that influences all subsequent development.
Closest to 'notable trap' (t5). The misconception field explicitly states the trap: 'All forms of coupling are equally bad.' Developers often treat coupling as binary (bad vs. good) rather than understanding the spectrum from acceptable data coupling to harmful content coupling. This is a documented gotcha that developers eventually learn, but the initial intuition that 'all coupling is bad' leads to over-engineering or misplaced refactoring priorities.
Also Known As
TL;DR
Explanation
Constantine's coupling spectrum tightest to loosest: Content (one module modifies another's internals directly — worst), Common (modules share global state), External (modules share an external data format), Control (one module directs another's flow via flag parameters), Stamp (modules share a data structure but use different parts), Data (modules share only necessary data via parameters — good), Message (modules communicate only via messages or interfaces — best). In PHP, common coupling via global variables or static state is the most frequent violation. Data and message coupling — achieved through constructor injection and interfaces — are the targets.
Common Misconception
Why It Matters
Common Mistakes
- Content coupling (modifying another class's internals) — often via public properties or Reflection hacks.
- Common coupling (shared global mutable state) — global variables, static properties, and some singleton uses.
- Control coupling (passing a flag to change a method's behaviour) — split into two separate methods instead.
- Not recognising stamp coupling (passing a whole object when only one field is needed) — pass just the needed value.
Code Examples
// Control coupling — flag changes internal behaviour:
function processOrder(Order $o, bool $sendEmail): void {
// ... process ...
if ($sendEmail) $this->mailer->send($o); // Split into processOrder + notifyCustomer
}
// Content coupling (worst) — directly accesses another class's internals
// \$obj->internalData['key'] — reaches inside private state
// Control coupling — passes a flag that controls other class's behaviour
// process(\$data, doLogging: true) — caller controls callee's internals
// Data coupling (best) — passes only needed data, receives only needed output
class TaxCalculator {
public function calculate(float \$amount, TaxRate \$rate): float {
return \$amount * \$rate->value(); // minimal interface
}
}
// Aim for data coupling — pass only what's needed, return a value
// Avoid content + control coupling — they make classes hard to change independently