Hidden Side Effects
A function does more than it claims.
“Function promises to do one thing, but it also does other hidden things.” – Robert C. Martin
Signs of Use (Symptoms)
-
getUser()modifieslastAccessTime. -
validate()also saves to database. - Calling a function causes unexpected state changes.
Why it is bad (Consequences)
- Surprise: Callers don’t expect side effects.
- Testing: Hard to test without triggering unwanted effects.
- CQS Violation: Queries shouldn’t modify state.
Why it happens (Root Cause)
Convenience. “While I’m here, I’ll also do X.”
When it might be okay (Exceptions)
- Logging (usually acceptable, low-impact side effect).
Explanation
Problem
checkPassword(pw) returns true/false but also increments loginAttempts.
The Flaw
Name says “check”, but it also mutates state.
Real world analogy
A peephole that also unlocks the door when you look through it.
Refactoring Solution
- Separate Command and Query:
checkPassword()+incrementAttempts(). - Rename: If side effects are intentional, name should reflect it:
verifyPasswordAndIncrementAttempts().
Pros and Cons (of the Antipattern)
| Pros (Why people do it) | Cons (The price you pay) |
|---|---|
Comparison
- Related Antipatterns: None directly.
- Related Principles: CQS.
Code example
Typescript
Bad (The Antipattern)
Good (The Fix)