Side Effects
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);
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
28
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Amazonbot 8
Perplexity 6
Unknown AI 3
Ahrefs 2
Google 2
SEMrush 2
ChatGPT 2
Also referenced
How they use it
crawler 22
crawler_json 2
pre-tracking 1
Related categories
⚡
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
🔍 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