Java Coding Standards Core
This file is the default standard for Java backend changes. It defines the smallest set of rules that are non-negotiable plus high-value defaults. Use this first. Load deeper references only when needed.
1. Rule Tiers
- REQUIRED: Must be followed unless the user explicitly asks for a justified exception.
- DEFAULT: Preferred behavior; adapt to existing module patterns when needed.
- PREFERRED: Good practice when it improves clarity and does not increase coupling.
2. Platform Baseline
- REQUIRED: Target Java 21+ style (project baseline is Java 25).
- REQUIRED: Use Jakarta APIs (
jakarta.*), notjavax.*. - DEFAULT: Prefer records for immutable DTO/value carriers.
- DEFAULT: Prefer sealed types for closed polymorphism.
- PREFERRED: Use pattern matching, text blocks, and
varwhere readability improves.
3. Architecture and Dependency Direction
- REQUIRED: Keep domain logic independent of transport/framework details.
- REQUIRED: Domain code must not depend on Spring web, Mongo driver, or HTTP client specifics.
- REQUIRED: Respect module boundaries; do not call another module's internal classes or repositories.
- DEFAULT: For cross-module coordination, prefer events over direct synchronous calls.
- DEFAULT: Use synchronous interfaces only for simple, stable dependencies.
4. Vertical Slice Structure
- REQUIRED: Organize by business feature/slice, not horizontal technical folders.
- REQUIRED: Keep most changes localized to one slice when implementing a feature.
- DEFAULT: Use flat slice structure for simple features.
- DEFAULT: Add
api/domain/application/infrastructuresubfolders only when feature complexity requires it.
5. Naming and Roles
- REQUIRED: Use role suffixes consistently:
Controller,Handler,Repository,GatewayorAdapter,Event,Policy/Service,Factory,Assembler,Config.- REQUIRED: Use business-first names that communicate responsibility.
- REQUIRED: Do not introduce ambiguous types such as
*Manager,*Helper,*Utils,*Datafor core domain behavior.
6. Domain Modeling
- REQUIRED: Avoid primitive obsession for domain identifiers; use typed IDs/value objects.
- REQUIRED: Enforce business invariants in domain/application layer, not only at HTTP boundary.
- DEFAULT: Use immutable value objects with validation in construction paths.
- DEFAULT: Keep aggregates behavior-focused; avoid anemic models when meaningful invariants exist.
7. Validation and Exceptions
- REQUIRED: Validate request shape/format at API boundary.
- REQUIRED: Validate business rules in handler/domain paths.
- REQUIRED: Convert infrastructure exceptions to application/domain-relevant exceptions before crossing boundaries.
- REQUIRED: Return stable error contracts from global exception handling.
8. Persistence and Tenant Safety
- REQUIRED: Include tenant scoping in every tenant-owned query/filter.
- REQUIRED: Keep repository contracts explicit; avoid hidden cross-tenant behavior.
- DEFAULT: Keep transaction boundaries at handler/application level.
- DEFAULT: Mark read paths as read-only transactional when supported by the stack.
9. Events and Integration
- REQUIRED: Publish cross-module events only after successful state change.
- DEFAULT: Prefer async event processing for side effects and decoupling.
- DEFAULT: Include correlation metadata on cross-module or async events.
- PREFERRED: Use transactional outbox for reliability-critical event delivery.
10. Testing Minimums
- REQUIRED: Add or update tests for changed behavior.
- REQUIRED: Cover business-critical paths with integration tests.
- REQUIRED: Keep architecture checks that enforce boundaries and naming.
- DEFAULT: Unit-test complex policies/value objects with deterministic edge cases.
11. Logging and Observability
- REQUIRED: Use structured, parameterized logging (no string concatenation for log interpolation).
- REQUIRED: Preserve request traceability across boundaries (trace/correlation + tenant/user context where available).
- DEFAULT: Keep logs concise and high signal; avoid duplicative noise at multiple layers.
12. Legacy Adaptation Rule
- REQUIRED: Do not force full rewrites of legacy slices when making scoped changes.
- DEFAULT: Improve touched code toward these standards incrementally.
- REQUIRED: If a required rule cannot be satisfied due to legacy constraints, note the constraint and the safest compliant compromise.
13. Quick Compliance Checklist
Use this before finalizing changes:
- Does dependency direction still flow inward?
- Are module boundaries and tenant boundaries preserved?
- Are identifiers/domain values strongly typed where it matters?
- Are naming suffixes and slice roles clear?
- Are validation and exception mappings split correctly by layer?
- Are events, transactions, and tests appropriate for risk?
- Is the change incremental and pragmatic for existing code?