← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Inappropriate Intimacy

Code Quality Intermediate
debt(d5/e5/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). PHPMD and PHPMetrics (listed in detection_hints.tools) can flag coupling metrics and some patterns of inappropriate intimacy, but they catch it heuristically — high afferent/efferent coupling counts, not the nuanced semantic issue. Many forms (e.g., Reflection abuse, bidirectional dependencies, deep getter chains) require careful code review, pushing toward d7, but the tooling availability pulls it back to d5.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to move methods/data between classes or introduce dedicated methods — this typically touches at least two classes and all their callers. It's not a one-line fix (ruling out e1-e3), but it's usually contained within a component boundary rather than being a cross-cutting architectural rework, so e5 fits well.

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

Closest to 'persistent productivity tax' (b5). Inappropriate intimacy applies across all contexts (web, cli, queue-worker) and is an OOP coupling smell that, once established, slows down multiple work streams — any change to either intimately coupled class risks breaking the other. It doesn't quite define the system's shape (b7-b9), but it's more than a localized tax because the coupling tends to spread and affect refactoring velocity broadly.

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

Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field states that developers wrongly believe inappropriate intimacy only matters across module boundaries, and that proximity justifies tight coupling. This is a genuine and common conceptual trap — developers who co-locate related classes often assume direct internal access is acceptable. It's a well-documented gotcha but doesn't quite contradict how similar concepts work elsewhere (t7), so t5 is appropriate.

About DEBT scoring →

Also Known As

class intimacy excessive coupling nosy class

TL;DR

Two classes that access each other's private fields and internals too freely, creating tight bidirectional coupling.

Explanation

Inappropriate Intimacy occurs when a class reaches into the internal details of another — reading private fields via getters that expose implementation, or worse, when two classes each rely on each other's internals (bidirectional dependency). This creates fragile code where changing one class's internals forces changes in the other. Remedies include moving methods to the class that owns the data they operate on (Move Method), extracting a shared class if both classes manipulate the same data, or breaking the bidirectional relationship by introducing an interface.

Common Misconception

Inappropriate intimacy only matters when classes are in different modules. Two closely located classes that constantly access each other's private details are equally problematic — proximity does not justify tight coupling.

Why It Matters

When two classes know too much about each other's internal structure, changes to one always require changes to the other — they should be separated by stable interfaces, not direct field access.

Common Mistakes

  • Accessing public properties directly instead of calling methods — changes to the property name break callers.
  • Classes that call private-by-convention methods (prefixed with _) of another class.
  • Circular dependencies between classes — A knows B's internals, B knows A's internals.
  • Using Reflection to access private members of another class in production code — extreme intimacy.

Code Examples

✗ Vulnerable
// OrderService reaches into User's internals
class OrderService {
    public function discountRate(User $user): float {
        return $user->loyaltyPoints > 1000 ? 0.15
             : ($user->memberSince < '2020-01-01' ? 0.10 : 0.0);
    }
}
✓ Fixed
// Move knowledge into the class that owns the data
class User {
    public function discountRate(): float {
        if ($this->loyaltyPoints > 1000) return 0.15;
        if ($this->memberSince < new \DateTimeImmutable('2020-01-01')) return 0.10;
        return 0.0;
    }
}

class OrderService {
    public function discountRate(User $user): float {
        return $user->discountRate(); // ask User, don't reach in
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 88
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 2 pings S 2 pings S 1 ping M
SEMrush 1
Bing 1 Amazonbot 1
Amazonbot 13 PetalBot 9 Ahrefs 7 SEMrush 7 Unknown AI 5 Bing 5 Perplexity 2 ChatGPT 2 Twitter/X 2 Applebot 2 Majestic 1 Google 1 Meta AI 1 Brave Search 1 Sogou 1
crawler 55 crawler_json 2 your_contextpost 1 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
When ClassA constantly accesses ClassB's private internals, move the relevant methods and data to ClassA, or introduce a dedicated method in ClassB that performs the operation
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Class using getters to access deep internals of another class; bidirectional dependency between two classes; class knowing too much about another's internal structure
Auto-detectable: ✗ No phpmd phpmetrics
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: High Context: Class Tests: Update


✓ schema.org compliant