Code that looks like it belongs
A pull request that is functionally correct and stylistically foreign is not a contribution. It is a review burden. The team either rewrites it, or merges it and carries a second dialect in the codebase forever.
Add refund eligibility to an order service: a refund may be issued within 30 days of delivery, must not exceed the original charge, and must be rejected outright on a cancelled order. Small, well specified, roughly eighty lines.
Both implementations below satisfy that. Both compile, both pass the same tests. Only one of them looks like it was written by the team that owns the repository.
@Service public class RefundService { @Autowired private OrderRepository repo; public Refund issue(Long id, BigDecimal amt) { Order o = repo.findById(id) .orElseThrow(() -> new RuntimeException("not found")); if (o.isCancelled()) throw new IllegalStateException("cancelled"); if (amt.compareTo(o.getTotal()) > 0) throw new IllegalArgumentException("too big"); return repo.save(new Refund(o, amt)); } }
public final class RefundService { private final OrderRepository orders; private final RefundValidator validator; RefundService(OrderRepository orders, RefundValidator validator) { this.orders = orders; this.validator = validator; } public Result<Refund> issue(OrderId id, Money amount) { return orders.findActiveById(id) .flatMap(order -> validator.check(order, amount)) .map(order -> orders.recordRefund(order, amount)); } }
A pull request is not judged on whether the code works. It is judged on whether the reviewer recognises it.
The conventions on the right were not supplied in a style guide. There isn’t one. They were derived from the repository, and each one is cited to the file it came from, so a reviewer can check the reasoning rather than trust it.
| Convention | Derived from | Evidence |
|---|---|---|
| Errors returned, not thrown | Result<T> across the service layer |
31 of 34 service methods return Result; 0 throw checked exceptions |
| Constructor injection, package-private | Every service in domain/ |
No @Autowired field in the module since 2023 |
| Validation in a dedicated validator | OrderValidator, PaymentValidator |
One validator per aggregate; none use bean annotations |
| Typed identifiers and money | OrderId, Money |
No raw Long id or BigDecimal amount in any public signature |
| Explicit repository methods | findActiveById, findSettledBefore |
Query intent named on the interface, never derived at the call site |
Two of these are not cosmetic. findActiveById exists because
findById returns soft-deleted orders, and the team was bitten by that once
already. An implementation that reaches for findById reintroduces a bug the
repository was deliberately shaped to prevent — and it does so invisibly, because
the code reads as perfectly reasonable Spring.
The Result type matters for the same reason. This service is called from a
batch consumer that must continue past a single bad record. An implementation that
throws does not fail the build. It fails the batch, at three in the morning, on someone
else’s rota.
That last row is deliberate. The fastest way to make a pull request unreviewable is to mix the change with improvements nobody asked for. A diff that touches only what the ticket describes can be reviewed in the time the reviewer actually has.