Why does code review exist?
Code review is not about approving or mocking code. It has three jobs: catch mistakes before users meet them, keep the team's understanding of the code aligned, and share knowledge. A good review comment is specific (which line), explains the risk, and suggests a way forward. "This is bad" is not useful; "this line accepts a quantity of 0, let's add @Positive" is. It also helps to say whether a comment is blocking (must be fixed before merge) or a nit (a matter of taste). More: code review culture.
Layers: controller, service, repository
- The controller translates HTTP: it reads the request, calls a service, and returns the right status and body. Business rules do not live here.
- The service holds business rules and transaction boundaries (pricing, discounts, stock checks).
- The repository only stores and reads data.
If a rule lives in a controller you cannot reuse it from a job or a message consumer, and testing it means starting the HTTP layer. More: Spring Boot layering.
Validate input at the edge
Everything that comes from a client is untrusted. Write a typed request DTO, add Bean Validation constraints, and put @Valid on the controller parameter. When validation fails, Spring throws MethodArgumentNotValidException and you turn it into a 400 Bad Request in a @RestControllerAdvice. RFC 9457 (Problem Details) defines the response format; Spring 6 provides the ProblemDetail class, so clients always get errors in the same shape. More: validation and errors.
Return the right HTTP status
When a new resource is created, return 201 Created and put the new resource's address in the Location header. A 200 OK says "something happened"; 201 says "a new resource exists and here is where". On failure, never return 200 with an empty body.
Do not expose entities
A JPA entity is a database model. If it becomes your API response, internal fields leak (internal statuses, for example), the API breaks whenever a table changes, and lazy associations cause surprise queries or serialization errors. Write a separate response DTO so the API contract does not depend on the database.
Naming
The author who writes q, p, o understands it today; in three months nobody does. quantity, product, order and OrderStatus.NEW make the code readable without comments. Magic numbers such as 10 and 0.9 should be named constants so the rule is visible.
A short example
@PostMappingpublic ResponseEntity<OrderResponse> create(@Valid @RequestBody CreateOrderRequest request) { OrderResponse created = orderService.create(request); URI location = URI.create("/orders/" + created.id()); return ResponseEntity.created(location).body(created);}The controller stays thin: validation is in the annotations, the rule is in the service, and only the status and header are set here.