Side effects are not evil. They are how programs do anything useful: read a request, write to a database, log, send a message, call a Java API. The problem is when side effects are mixed into your core logic so you cannot test, reuse, or reason about it.
The Clojure approach in one sentence
Write a pure core that calculates values, and an impure shell that performs I/O.
Why Java developers like this once they feel it
- Fewer mocks: most logic can be tested as plain functions.
- Better refactors: you can move pure code freely.
- Clear boundaries: the “do work” part is easy to find and review.
This section teaches patterns for keeping effects explicit without making the code feel abstract.
In this section
-
Understanding Side Effects
Learn what counts as a side effect, why it complicates design, and how to spot clean effect boundaries in Clojure code.
-
Isolating Side Effects
Use a functional core and an imperative shell so effectful code stays thin and business rules stay easy to test.
-
Managing State Changes
Use atoms, refs, and agents deliberately, while keeping state transitions pure and effect boundaries explicit.