Glossary / Side effects

Side effects

A side effect is an observable interaction beyond computing and returning a value. Examples include mutating shared state, changing the DOM, writing storage, sending a request, logging, scheduling a timer, or throwing an exception. Effects are necessary in useful programs; the engineering goal is to make them explicit, scoped, and controllable rather than hidden throughout domain logic.

Effects and failure behavior

function calculateTax(amount, rate) {
  return amount * rate; // computation
}

async function saveOrder(order, repository, logger) {
  logger.info("saving order"); // effect
  await repository.insert(order); // effect and failure boundary
}

Effects can be synchronous or asynchronous. They can fail, race, be repeated during retries, or occur in an order that matters. A function with a side effect may still return a useful value; “pure versus impure” is not a moral judgment. It is a way to identify dependencies and reason about observability.

Hidden effects are especially risky in getters, default parameters, render functions, array transformations, and retry wrappers. A retry can duplicate a payment or message unless the operation is idempotent. Event listeners and subscriptions require cleanup. Tests should distinguish the decision being made from the adapter that performs I/O, then integration-test the boundary.

Design guidance

Pass effectful dependencies explicitly when that improves control. Give operations names that reveal their behavior (persist, publish, update) rather than disguising them as harmless calculations. Define ownership, ordering, cancellation, and retry behavior. In UI code, centralize effects around lifecycle or event boundaries rather than triggering them during pure render calculations.

Interview questions

  1. Are side effects bad? No; they enable I/O and state change, but hidden effects make behavior harder to test and reason about.
  2. Name common effects. Network requests, logging, DOM mutation, storage writes, timers, and shared-state mutation.
  3. Why are effects important for retries? Repeating them may duplicate externally visible actions unless they are idempotent or deduplicated.
  4. How isolate effects? Keep domain decisions deterministic and place I/O behind explicit adapters or service boundaries.

References