Learn how Java engineers can keep I/O, logging, database writes, and other effects outside retryable Clojure state updates while preserving concurrency safety and testability.
Side effects are not optional in production software. Programs log, call databases, publish messages, read files, send HTTP requests, and update external systems. The concurrency problem is not that effects exist. The problem is letting effects hide inside retryable state updates where they can repeat, block, or interleave unpredictably.
For Java engineers, the core rule is direct:
| Place | Safe responsibility |
|---|---|
| Pure functions | Calculate decisions from immutable inputs. |
swap! update functions |
Compute the next atom value only. |
dosync transactions |
Coordinate ref state only. |
| Agents, queues, executors, I/O namespaces | Perform effects at explicit boundaries. |
This section shows how to separate “calculate” from “do” in concurrent Clojure code so state coordination remains deterministic and effects remain observable, testable, and operationally controlled.