Script Valley
Writing Clean Code: Naming, Functions & Structure
Writing Functions That Do One ThingLesson 2.4

Side effects in functions and why they cause bugs

pure functions, side effects definition, hidden side effects, referential transparency, function predictability, testing implications

Side Effects: The Hidden Danger in Functions

Pure vs impure function diagram

A side effect is anything a function does beyond computing and returning a value: writing to a database, modifying a global variable, logging to a file, mutating a parameter, making an HTTP call.

Side effects aren't always wrong — programs must interact with the world. The problem is hidden side effects: when a function's name implies it only reads, but it secretly writes.

// Caller has no idea this modifies the database
function getActiveUsers() {
  db.users.update({ lastChecked: Date.now() }); // hidden side effect!
  return db.users.findAll({ active: true });
}

Pure functions — those with no side effects — are the gold standard for logic. Given the same input, they always return the same output. They're trivial to test and impossible to cause bugs through unexpected state changes.

// Pure — same input always produces same output
function calculateDiscount(price, discountPercent) {
  return price * (1 - discountPercent / 100);
}

// Impure — depends on external state
function calculateDiscount(price) {
  const percent = store.getState().currentDiscount; // hidden dependency
  return price * (1 - percent / 100);
}

Separate pure logic from side effects. Put your business logic in pure functions and isolate side effects at the edges of your system — in controllers, event handlers, or service layers. This makes your core logic testable without mocking databases or APIs.

When a function must have side effects, make them explicit in the name: saveUser, sendEmail, updateLastLoginTime.

Up next

How to extract functions from long methods without breaking code

Sign in to track progress