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

Single Responsibility Principle

General PHP 5.0+ Beginner
debt(d7/e7/b7/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints explicitly state automated=no. While phpstan and phpcs are listed as tools, they can flag heuristics like XxxManager/XxxHelper/XxxUtil with 10+ public methods, but this is a shallow proxy — the real violation (multiple reasons to change) requires human judgment during code review. No tool can reliably detect conceptual responsibility misalignment.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix says 'split it', but splitting a class that owns multiple concerns (e.g., a controller doing DB queries, business logic, and HTTP response building) typically requires extracting services, updating all call sites, and retesting across multiple files. When SRP is ignored during prototyping and the code 'works', the common_mistakes entry confirms it compounds — the refactor becomes cross-cutting rather than local.

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

Closest to 'strong gravitational pull' (b7). Applies across web, cli, and queue-worker contexts. A codebase that ignores SRP systematically produces tightly coupled classes that shape every subsequent change — every new feature must navigate the tangled responsibilities. The common_mistakes entry notes that most spaghetti codebases trace back to this, making it a persistent productivity tax with strong gravitational pull on all future development.

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

Closest to 'serious trap' (t7). The misconception field documents exactly the trap: developers commonly believe SRP means 'a class should only do one thing' (one action/method), when the actual principle is 'one reason to change' (one stakeholder/concern). This is a meaningful semantic difference that leads developers to either over-split (5-line helper classes for trivial operations) or under-split (conflating unrelated concerns as 'one thing'). It contradicts intuitive interpretations of the word 'single'.

About DEBT scoring →

Also Known As

SRP Single Responsibility Principle one reason to change

TL;DR

A class or function should have one reason to change — doing one thing and doing it well.

Explanation

The S in SOLID, SRP states that every module, class, or function should be responsible for one part of the system's functionality. "One reason to change" means: if two different types of requirements changes would require editing the same class, that class probably has too many responsibilities. SRP makes code easier to understand, test, and modify because changes to one concern don't accidentally break another.

Common Misconception

SRP means a class should only do one thing. SRP means a class should have only one reason to change — one stakeholder or concern driving its evolution. A class with two unrelated responsibilities will be modified for two different reasons, coupling changes that should be independent.

Why It Matters

Classes with a single responsibility are easier to test in isolation, safer to change without side effects, and simpler to reuse. Most spaghetti codebases trace back to classes that grew to own too many concerns.

Common Mistakes

  • Confusing SRP with "one method per class" — it means one reason to change, not one action.
  • Putting database queries, business logic, and HTTP response building all inside a controller.
  • Splitting too aggressively — a 5-line helper class for every trivial operation creates its own maintenance burden.
  • Ignoring SRP during prototyping and never refactoring once the code "works".

Code Examples

✗ Vulnerable
class User {
    public function save(): void { /* DB logic */ }
    public function sendWelcomeEmail(): void { /* SMTP logic */ }
    public function toJson(): string { /* serialisation */ }
    public function validatePassword(string $pw): bool { /* validation */ }
    // Four reasons to change
}
✓ Fixed
class OrderController {
    public function store(Request $r, OrderService $orders) {
        $order = $orders->create($r->validated());
        return response()->json($order);
    }
}
// OrderService handles business logic, dispatches events/jobs

Added 13 Mar 2026
Edited 22 Mar 2026
Views 100
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 2 pings S 0 pings M 1 ping T 1 ping W 4 pings T 9 pings F 9 pings S 15 pings S 10 pings M 1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 48 Perplexity 9 Amazonbot 7 Ahrefs 5 Google 5 SEMrush 4 ChatGPT 2 Unknown AI 2 Claude 2 Bing 2 Meta AI 1 Qwen 1 PetalBot 1
crawler 85 crawler_json 4
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
If you struggle to name a class in one word (not 'Manager', 'Helper', 'Util'), it has multiple responsibilities — split it
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Class named XxxManager XxxHelper XxxUtil with 10+ public methods across unrelated concerns
Auto-detectable: ✗ No phpstan phpcs
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update


✓ schema.org compliant