116 lines
4.4 KiB
Markdown
116 lines
4.4 KiB
Markdown
# 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 + persistence` cho 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 |
|