4.4 KiB
4.4 KiB
APLP Backend — Architecture
| Module | aplp.backend.spring |
| Role | Backend cho aplp-web (learner application) |
| Status | Draft |
1. Architectural Direction
Backend theo Modular Monolith, kết hợp:
Modular Monolith
+ Clean Architecture 4 Layers
+ DDD-oriented
+ Vertical Slice / Business Module
Nguyên tắc nền tảng:
Business behavior first, database second.
Modular Monolith first; extract service chỉ khi có demonstrated need.
2. Request Flow
Controller (API layer)
↓
Application / Service (use case)
↓
Domain (business rules / model)
↓
Persistence (repository)
↓
Database
3. Clean Architecture — 4 Layers
Mỗi business module có 4 layer rõ ràng:
| Layer | Trách nhiệm | Should NOT do |
|---|---|---|
| Interface/API | HTTP entry point, DTO request/response, validation cơ bản, tách biệt khỏi domain | Chứa business logic |
| Application | Use case orchestration, transactions, authorization | Chứa domain business rules |
| Domain | Entities, value objects, business rules, domain services | Phụ thuộc DB/HTTP |
| Persistence | Repository implementation, mapping, DB access | Chứa business rules |
Dependency rule: chỉ phụ thuộc từ ngoài vào trong (API → Application → Domain); Persistence implement interface do Domain/Application định nghĩa.
4. Modular Monolith
- Code tổ chức theo business module (vertical slice), không theo technical layer toàn cục.
- Mỗi module đóng gói
interface + application + domain + persistencecho một business capability. - Module giao tiếp qua public API/interface; không import nội bộ module khác.
- Module registry/config ở application root.
Module Boundary
com.aplp.backend
└── <module> (vd: identity, learner, content, learning, assessment, adaptive, ...)
├── api (controller, dto)
├── application (use case, service)
├── domain (model, domain service, rules, repository interface)
└── persistence (repository impl, entity mapping, jpa)
5. DDD Orientation
- Aggregate là ranh giới bảo toàn bất biến (invariant) trong cùng transaction.
- Value Objects dùng cho khái niệm không có identity riêng (Score, Money, MasteryLevel).
- Domain Event (optional, temporal) dùng khi cần tách rời side-effect giữa modules — không lạm dụng cho tất cả luồng.
- Repository interface ở domain, implementation ở persistence.
6. Database
- Relational database: PostgreSQL (chosen). Dev chạy qua
docker-compose(port 5433); test dùng H2 (PostgreSQL mode). - Migrations: Flyway (chosen) tại
src/main/resources/db/migration.spring.jpa.hibernate.ddl-auto=validate. - Schema phản ánh domain model, không thiết kế "database-first".
7. Cross-Cutting Concerns
- Security / AuthN: xử lý ở API/boundary layer (Phase 0).
- Validation: input validation ở API; business invariant validation ở domain.
- Logging & Observability: structured logging, common config (Phase 9 mở rộng metrics/tracing).
- Errors: exception mapping, đồng nhất response format.
8. Deferred (tránh dùng khi chưa có justification)
- Microservices split
- API Gateway
- Kafka / Event-driven
- Redis
- Elasticsearch
- CQRS / Event Sourcing
9. Deployment
- Docker first (containerize backend).
- Kubernetes later khi có nhu cầu scale/ops.
10. Open Questions (backend-specific)
| ID | Question | Impact | Proposed Direction | Status |
|---|---|---|---|---|
| ARC-001 | Spring Boot version nào cho foundation? | Setup | Dùng phiên bản ổn định mới nhất hỗ trợ Java LTS | Resolved: Spring Boot 3.5.16 + Java 21 (Maven) |
| ARC-002 | JWT hay session cho authentication? | Security | JWT stateless + refresh flow | Resolved: JWT (access + rotating refresh, refresh token hash lưu DB) |
| ARC-003 | DB: PostgreSQL vs MySQL? | Setup | PostgreSQL | Resolved: PostgreSQL 17 (docker-compose) |
| ARC-004 | Migration: Flyway vs Liquibase? | Setup | Flyway | Resolved: Flyway |
| ARC-005 | Content đọc từ LMS qua API hay shared read model? | Module boundary | API/read model của LMS | Open (Phase 2) |
| ARC-006 | Transaction boundary giữa module nào cần được phân tách? | Data consistency | Ghi rõ trong từng use case | Open |