Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
The English summary is being prepared. Showing the original description.
Use when modelling a rich domain in Java - SOLID principles, encapsulated entities that enforce their own invariants, and value objects over primitives
The English summary is being prepared. Showing the original description.
See how to installReview the instructions the agent will receive before you install.
Java is chosen precisely when the domain is rich (see backend-language-decision). That value is only realized if you model it with real objects that protect their invariants — not anemic data bags with a pile of setters and logic scattered in services.
Core principle: Objects own their invariants. If a rule about an entity can be violated from outside the entity, the model is broken.
switch. New payment method → new PaymentMethod implementation, not another case.Square extends Rectangle breaks setWidth, the hierarchy is wrong — prefer composition.read shouldn't depend on write.// ❌ anemic: invariant lives nowhere, anyone can break it
class Task {
public String title; // no bound enforced
public Status status;
}
task.title = "x".repeat(500); // invalid state, no guard
// ✅ rich: the entity enforces its own rules
public final class Task {
private final TaskId id;
private String title;
private Status status;
private Task(TaskId id, String title) { this.id = id; this.title = title; }
public static Task create(String title) {
if (title == null || title.isBlank() || title.length() > 200)
throw new InvalidTaskTitle(title);
return new Task(TaskId.newId(), title);
}
public void rename(String title) { /* same guard, reused */ }
public void complete() {
if (status == Status.DONE) throw new IllegalTransition("already done");
this.status = Status.DONE;
}
// getters, no public setters
}
Wrap meaningful primitives: TaskId, Email, Money — not raw String/long/BigDecimal. A TaskId can't be accidentally passed where a UserId is expected, and validation lives in one place. Java record makes these cheap.
record for immutable value objects and DTOs.sealed interfaces + pattern matching for closed hierarchies (states, commands).InvalidTaskTitle) mapped to HTTP status at the boundary — not raw IllegalArgumentException leaking out.Prefer a sealed interface + exhaustive switch pattern matching (final since Java 21) for a closed set of states or commands over a type enum plus if/instanceof chains — the compiler then refuses to let a new case go unhandled.
String/long everywhere instead of value objects.@Data/@EqualsAndHashCode on a JPA entity — it pulls in lazy associations (forcing a load, or crashing outside the session) and generates a mutable, settable id that breaks equals/hashCode once the entity is persisted. Write equals/hashCode on the id only, or skip Lombok on entities.switch over a type enum that grows every feature → missing polymorphism.No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
The English summary is being prepared. Showing the original description.
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
The English summary is being prepared. Showing the original description.
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
The English summary is being prepared. Showing the original description.
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
The English summary is being prepared. Showing the original description.
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
The English summary is being prepared. Showing the original description.
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
The English summary is being prepared. Showing the original description.