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
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.
