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() modifies lastAccessTime.
  • 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)
  • Convenience
  • Unpredictable behavior
  • Comparison

    • Related Antipatterns: None directly.
    • Related Principles: CQS.

    Code example

    Typescript

    Bad (The Antipattern)

    Good (The Fix)