Use pull requests, small commits, CI commands, and Clojure-aware review checklists to keep team changes understandable when Java developers adopt Clojure.
Good Clojure collaboration is not just “open a pull request.” It is making small, reviewable changes to namespaces, data shapes, tests, and build commands so teammates can understand the behavior without replaying your whole REPL session.
Java engineers already know code review. The adjustment is knowing what Clojure changes tend to hide.
| Review surface | What can hide there |
|---|---|
| Namespace form | New dependency direction, circular require risk, broad :refer :all, or unused aliases. |
| Data shape | Changed map keys, nested structures, optional fields, or defaults. |
| Pure functions | Behavior can shift without a class or interface changing. |
| Tests | Expectations may be too example-specific or may miss edge cases. |
| Build files | Classpath, REPL, test, and production commands can diverge. |
A good first Clojure pull request should usually do one of these:
Avoid combining formatting, dependency upgrades, namespace reshuffling, feature logic, and packaging changes in one pull request. Those changes stress different reviewers and create noisy diffs.
Use a description that answers the questions reviewers will actually have.
| PR field | Useful content |
|---|---|
| Behavior changed | What the code now does differently. |
| Data shape | New or removed keys, nested maps, defaults, and nil behavior. |
| Namespace impact | New dependencies, renamed namespaces, or interop boundaries. |
| Test command | Exact command run locally and expected CI command. |
| Review focus | What needs careful review: correctness, API shape, performance, migration, or build wiring. |
This is especially helpful for Java teammates who can read Clojure syntax but do not yet know where subtle changes usually live.
When reviewing Clojure, do not stop at “the functions are short.” Short code can still hide coupling, unclear data contracts, or weak test coverage.
| Question | Why it matters |
|---|---|
| Is the namespace dependency direction clear? | Prevents reload problems and circular requires. |
| Are data contracts obvious at boundaries? | Java callers and Clojure internals need stable shapes. |
| Are errors represented consistently? | Mixed Java/Clojure systems often drift between exceptions and data errors. |
| Do tests cover behavior, not implementation trivia? | Pure functions are easy to test well, but also easy to under-test. |
| Does CI run the same command documented in the PR? | Prevents “works only in my REPL” merges. |
Merge conflicts in Clojure often happen in ns forms, data literals, and test expectations. Resolve the meaning first, then the parentheses.
1--- current branch
2 (:require [order-service.pricing :as pricing]
3 [order-service.validation :as validation]))
4--- incoming feature/audit
5 (:require [order-service.pricing :as price]
6 [order-service.audit :as audit]))
A good resolution may not be either side exactly:
1(ns order-service.handler
2 (:require
3 [order-service.audit :as audit]
4 [order-service.pricing :as pricing]
5 [order-service.validation :as validation]))
After resolving a conflict, run tests. If the conflict touched namespace dependencies, also reload the affected namespace from a clean REPL or run the project command that CI uses.
Before requesting review:
git diff origin/main...HEAD.Before approving:
ns form and dependency direction.