← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Coupling

quality Intermediate
debt(d5/e7/b7/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). The term's detection_hints list phpstan, phpmd, and deptrac as tools that can identify coupling issues through metrics like afferent/efferent coupling and dependency analysis. These are specialist static analysis tools, not default linters, so coupling problems require deliberate tooling setup to detect automatically.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor' (e7). While the quick_fix suggests injecting dependencies and depending on abstractions, actually decoupling tightly coupled code typically requires changes across many files — introducing interfaces, refactoring constructors, updating instantiation sites, and potentially restructuring module boundaries. It's rarely a single-line fix; it's architectural work that spans the codebase.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Coupling decisions shape how every future change propagates through the system. The term applies to all PHP contexts (web, cli, queue-worker) and is tagged as architecture/principles. Once tight coupling is established, it acts as a persistent tax — every modification risks rippling through coupled modules, and the coupling pattern tends to spread as developers follow existing conventions.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception explicitly states that developers wrongly believe 'any dependency between modules is bad coupling.' This is a documented gotcha that most developers eventually learn — the real goal is loose coupling via abstractions, not zero coupling. The common_mistakes (hidden singleton coupling, Law of Demeter violations) represent patterns that look fine but create invisible coupling.

About DEBT scoring →

Also Known As

tight coupling loose coupling module coupling

TL;DR

The degree to which one module depends on another; high coupling makes changes expensive and testing difficult.

Explanation

Coupling measures how much changing one module forces changes in others. Types range from loose (data coupling via parameters) to tight (content coupling where one module directly modifies another's internals). High coupling is a primary driver of brittle, hard-to-test code. It is reduced by programming to interfaces, using dependency injection, applying the Law of Demeter, and introducing well-defined boundaries between modules. Coupling and cohesion are twin concerns — high cohesion within a module naturally reduces coupling to other modules.

Common Misconception

Any dependency between modules is bad coupling. Coupling is unavoidable — the goal is loose coupling, where modules depend on abstractions rather than concrete implementations, making them independently changeable and testable.

Why It Matters

Tightly coupled classes cannot be changed, tested, or reused independently — a change to one ripples through many, making the codebase increasingly expensive to modify.

Common Mistakes

  • Instantiating dependencies with new inside a class instead of injecting them.
  • Accessing global state or singletons directly — hidden coupling that is invisible in the signature.
  • Returning concrete types instead of interfaces — callers become coupled to the implementation.
  • Reaching into chained objects: $order->getCustomer()->getAddress()->getCity() — violates Law of Demeter and couples deeply.

Code Examples

💡 Note
Swap Stripe for Braintree by injecting a different implementation — PaymentService never changes.
✗ Vulnerable
// High coupling: PaymentService directly instantiates and calls Stripe SDK
class PaymentService {
    public function charge(int $cents): void {
        $stripe = new \Stripe\Charge();
        $stripe->create(['amount' => $cents, 'currency' => 'usd']);
    }
}
✓ Fixed
// Low coupling: depends on an interface, not a concrete class
interface PaymentGateway {
    public function charge(int $cents, string $currency): ChargeResult;
}

class PaymentService {
    public function __construct(private PaymentGateway $gateway) {}
    public function charge(int $cents): ChargeResult {
        return $this->gateway->charge($cents, 'usd');
    }
}

class StripeGateway implements PaymentGateway { ... }

Added 15 Mar 2026
Edited 22 Mar 2026
Views 36
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 3 pings F 1 ping S 0 pings S 1 ping M 2 pings T 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Perplexity 10 Ahrefs 7 Amazonbot 6 Google 2 Unknown AI 2 ChatGPT 2
crawler 27 crawler_json 2
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
Depend on abstractions (interfaces) not concretions; inject dependencies rather than instantiating them; measure coupling with fan-in/fan-out metrics
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Class directly instantiating 5+ other classes; domain class importing infrastructure namespace; high afferent/efferent coupling metric
Auto-detectable: ✓ Yes phpstan phpmd deptrac
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update

✓ schema.org compliant