# APLP Backend — Conventions | | | | --- | --- | | **Status** | Draft | ## 1. Naming & Package - Base package: `com.aplp.backend` - Mỗi module: `com.aplp.backend..` với layer = `api | application | domain | persistence` (xem `ARCHITECTURE.md`). - Tên class theo responsibility: - Controller: `XxxController` - Use case: `XxxUseCase` hoặc `XxxService` - Request/Response DTO: `XxxRequest`, `XxxResponse` - Aggregate/Root: tên domain concept (vd `Learner`, `Course`) - Repository interface: `XxxRepository` (định nghĩa ở domain) ## 2. Layer Rules | Layer | Được phép | Cấm | | --- | --- | --- | | `api` | AuthN/authorization (framework), input validation, DTO mapping | Business rules | | `application` | Orchestrate use case, transaction, call domain/persistence | Nhúng business rules riêng | | `domain` | Business logic, invariants, domain services, repository interface | Spring/JPA/HTTP dependencies | | `persistence` | Repository impl, JPA entities, mappers | Business logic | - **Domain không import Spring/JPA/HTTP.** - Persistence entities tách biệt (hoặc mappers) khỏi domain model nếu cần. ## 3. Transaction - Transaction mở ở **Application** layer (`@Transactional` trên use case/service). - Không ném transaction qua domain khi chỉ để đọc. - Repository phương thức read nên read-only transaction khi cần. ## 4. Validation - **Input/API validation** ở `api` layer (bean validation trên DTO). - **Business invariant** trong `domain` (domain exception). - Response lỗi dùng format đồng nhất (vd `ApiError` với code + message). ## 5. Errors & Exceptions - `DomainException` cho lỗi business; mapping sang HTTP status ở `api` layer. - Error response nhất quán: `code`, `message`, `details` (tuỳ thỏa thuận). - Kèm `traceId`/requestId để dễ debug (Phase 0). - Error code dùng **global enum `ErrorCode`** ở `common/api` (kèm HTTP status); mở rộng bằng cách thêm hằng số khi có module mới. ## 6. DTO Mapping - Không để JPA entity lọt ra ngoài `persistence`/`api` response. - **Mapping thủ công** (static method) trong repository impl / DTO factory — quyết định ở Phase 0 (không dùng MapStruct cho giai đoạn này; thêm khi có justification). ## 7. Repository - Interface repository của module ở `domain`; implementation ở `persistence`. - Chỉ expose các method cần thiết cho use case, không leek Query/spec toàn module. - Query đặc thù (search, aggregation) nằm trong repository implementation. ## 8. Domain Events (khi cần) - Dùng để tách rời side-effect giữa module (vd assessment hoàn thành → cập nhật adaptive state). - Không lạm dụng: nếu đồng bộ đơn giản và cùng transaction, gọi trực tiếp qua interface. - Nếu dùng Spring events: publish ở application layer, không trong domain. ## 9. Config & Secrets - Cấu hình theo environment (`application.yml`, profile dev/prod). - **Không commit secret/key vào repo.** Dùng env vars hoặc bí quyết quản lý (vault) khi có. - Không log secret/token/password. ## 10. Testing - Unit test cho `domain` + `application`. - Test repository/persistence khi cần. - Integration test cho API layer. - Quyết định framework/test DB ở Phase 0. ## 11. Code Style - Java theo tiêu chuẩn project (indent 4 spaces — xác nhận khi setup). - Code của backend **không comment thừa**; tên rõ nghĩa. - `@author`/metadata không bắt buộc. ## 12. Open Questions | ID | Question | Status | | --- | --- | --- | | CON-001 | Dùng MapStruct hay mapping thủ công? | **Resolved**: thủ công (Phase 0) | | CON-002 | Error code convention (enum per module vs global)? | **Resolved**: global `ErrorCode` trong `common/api` | | CON-003 | JPA entities tách hay dùng chung domain model? | **Resolved**: tách riêng (`*JpaEntity` trong `persistence`, domain model trong `domain`) |