91 lines
3.9 KiB
Markdown
91 lines
3.9 KiB
Markdown
# APLP Backend — Conventions
|
|||
|
|
|
||
|
|
| | |
|
||
|
|
| --- | --- |
|
||
|
|
| **Status** | Draft |
|
||
|
|
|
||
|
|
## 1. Naming & Package
|
||
|
|
|
||
|
|
- Base package: `com.aplp.backend`
|
||
|
|
- Mỗi module: `com.aplp.backend.<module>.<layer>` 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`) |
|