A service does `if (order.getStatus() == OPEN && !order.getLines().isEmpty()) { order.setStatus(PAID); order.setPaymentRef(ref); }` — and the exact same check, with a subtly different condition, lives in three other services. A batch job sets an order's status to `PAID` directly, with no lines, and nobody notices for a week. What's the underlying design problem, and what does the fix actually look like in code?
This is the anaemic model the lesson names directly: Order is a bag of fields with getters and setters, and the rule "only an open order with at least one line can become paid" lives in the service that happens to call setStatus, not in the Order itself — so every place that wants to change an order's status has to remember and correctly re-implement that rule, and the batch job is exactly the place that didn't. The fix is to move the invariant into the aggregate: a markPaid(PaymentRef ref) method on Order that checks the rule itself and throws if it doesn't hold, with setStatus and setPaymentRef removed from the public API entirely. Once there is no way to set status except through a method that enforces the rule, the batch job (and the other three services) cannot construct the invalid state even if they try — the invariant is checked in exactly one place, inside the object it is about, rather than duplicated with three variations across the services that touch it.