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

Side Effects

Code Quality Intermediate
debt(d7/e5/b5/t5)
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 list phpstan, but automated detection is explicitly marked 'no' — phpstan can flag some patterns but hidden side effects (e.g. a getter warming a cache, a constructor making HTTP calls) are not reliably caught by static analysis alone. The code_pattern examples (function returning value AND writing to database, getter with cache warming) require a human reviewer to recognise the dual-purpose behaviour. No linter reliably catches the general case.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix points to Command-Query Separation — separating read and write responsibilities. While the principle sounds simple, applying it to functions that currently do both (return a value and write to DB, or constructors with IO) typically requires splitting function signatures, updating all call sites within a component, and adjusting tests. It goes beyond a single-line swap but usually stays within one component unless the side-effecting function is widely shared.

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

Closest to 'persistent productivity tax' (b5). Hidden side effects apply broadly across web, cli, and queue-worker contexts (all three listed in applies_to). They slow down testing (functions that return different values for same input break caching and mocking), make composition risky, and force future maintainers to read implementations rather than signatures. They don't define the entire system's shape but persistently tax many work streams — especially testing and debugging.

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

Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The canonical misconception is explicitly stated: developers believe side effects are always bad and should be eliminated, when in reality the goal is to isolate and make them explicit. This is a well-documented gotcha in functional and clean-code literature that most intermediate developers eventually encounter and correct, but it misleads beginners into either eliminating necessary effects or ignoring the problem entirely. It contradicts naive intuition but is widely documented.

About DEBT scoring →

Also Known As

function side effects hidden side effects implicit state change

TL;DR

Observable changes a function makes beyond returning a value — modifying global state, I/O, mutation of arguments — that make code harder to reason about.

Explanation

Side effects include: modifying global or class-level state, writing to files or databases, sending emails, mutating arguments passed by reference, and throwing exceptions. They are necessary for useful programs but should be isolated to well-defined boundaries and minimised in business logic. Unexpected side effects are a major source of bugs. The command-query separation principle (CQS) formalises this: methods that return values should not modify state, and methods that modify state should not return values.

Common Misconception

Side effects are always bad and should be eliminated. Side effects — writing to a database, sending an email — are the point of most applications. The goal is to isolate and make them explicit, not eliminate them.

Why It Matters

Hidden side effects make functions unpredictable — a caller cannot reason about the full impact of calling a function without reading its implementation, causing bugs when functions are composed or reordered.

Common Mistakes

  • Functions that modify global state, static properties, or their arguments without signalling it in the signature.
  • Constructors with side effects — database writes, HTTP calls, or file I/O in __construct().
  • Not distinguishing between acceptable necessary side effects (persisting data) and hidden accidental ones.
  • Functions that return different values for the same input due to hidden state — breaks caching and testing.

Code Examples

✗ Vulnerable
// Hidden side effects — callers can't predict what changes
function calculateTotal(array $cart): float {
    $this->lastCalculated = time();          // hidden mutation
    $this->analytics->track('cart_viewed');  // hidden I/O
    $total = array_sum(array_column($cart, 'price'));
    $this->cache->set('cart_total', $total); // hidden write
    return $total;
}
✓ Fixed
// Pure calculation — no side effects
function calculateTotal(array $cart): float {
    return array_sum(array_column($cart, 'price'));
}

// Side effects handled explicitly by the caller
$total = calculateTotal($cart);
$this->analytics->track('cart_viewed');
$this->cache->set('cart_total:' . $cartId, $total);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 55
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 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 4 pings F 0 pings S 2 pings S 1 ping M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Amazonbot 8 Scrapy 7 Perplexity 6 SEMrush 5 Ahrefs 4 Unknown AI 3 Google 2 ChatGPT 2 Claude 2 Meta AI 1 Bing 1 Sogou 1 PetalBot 1
crawler 38 crawler_json 4 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Separate commands (write, no return) from queries (read, return value) — functions that do both are harder to test and reason about
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Function returning value AND writing to database; getter method with cache warming side effect; query method that logs analytics
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: Medium Context: Function Tests: Update


✓ schema.org compliant