- Use `kebab-case` for function and variable names, `PascalCase` for protocols and records, and `SCREAMING_KEBAB-CASE` for constants defined with `def`.
- Prefer pure functions with `defn`; isolate side effects to explicit boundaries and label impure functions with a `!` suffix (e.g., `save-user!`).
- Use `->` and `->>` threading macros to express data transformations as left-to-right pipelines rather than deeply nested function calls.
- Keep functions small and composable — a function that does one thing is easier to test, reuse, and name accurately.
- Use `let` bindings to name intermediate values in complex expressions — avoid deeply nested anonymous function calls.
- Prefer Clojure's persistent data structures (`map`, `vector`, `set`, `list`) over mutable Java collections — they are structurally shared and thread-safe by default.
- Use `defprotocol` and `defrecord`/`deftype` for polymorphism instead of multi-level inheritance from Java classes.
- Use `spec` or `malli` to validate function inputs and outputs at REPL and test time — attach specs to public functions with `fdef`.