Đánh Giá Clean Architecture — VinhPhatERP v2
Thời điểm đánh giá: 2026-04-12 | Trạng thái: Typecheck 0 errors, Lint 0 errors
1. Sơ đồ Kiến trúc Hiện tại
┌─────────────────────────────────────────────────────┐ │ UI Layer src/features/*/ *.tsx │ │ (Pages, Forms, Lists, Cards) │ ├─────────────────────────────────────────────────────┤ │ Logic Layer src/features/*/ use*.ts │ │ (React Query Hooks as Use-Cases) │ ├─────────────────────────────────────────────────────┤ │ Contract Layer src/schema/ *.schema.ts │ │ (Zod schemas, shared constants, domain types) │ ├─────────────────────────────────────────────────────┤ │ API Layer src/api/ *.api.ts │ │ (Supabase queries, data mapping) │ ├─────────────────────────────────────────────────────┤ │ Infra Layer src/services/supabase/ │ │ (client.ts, database.types.ts, tenant.ts) │ └─────────────────────────────────────────────────────┘
Các tầng bổ sung:
src/domain/contracts/— Pure business logic (ContractStateMachine, ContractDomain)src/models/— Domain model types (joined/mapped data)src/app/plugins.ts— Feature Registry Patternsrc/shared/— components, utils, hooks, lib dùng chung
2. Điểm Mạnh
A. Plugin / Feature Registry System — Xuất sắc
- Tất cả features được đăng ký tập trung trong
plugins.ts - Mỗi feature là một plugin độc lập với
key,route,icon,requiredRoles,group,order - Component loading là lazy — tối ưu bundle size
- Thêm/tắt một feature chỉ cần comment 1 dòng trong
plugins.ts
B. Schema-First Approach — Tốt
src/schema/là nguồn sự thật duy nhất cho Zod validation- Barrel export qua
index.tsvới xử lý naming collision rõ ràng - Schema được dùng nhất quán: form validation + API type + contract
C. Use-Case Pattern via React Query Hooks — Tốt
- Mỗi feature có hooks riêng (
useOrders.ts,useProgressBoard.ts, v.v.) - Hooks xử lý: Loading / Error / Success / Cache Invalidation
- UI components chỉ consume hooks, không gọi API trực tiếp
D. Domain Layer — Đặc trưng cao cấp
src/domain/contracts/ContractDomain.ts— Pure business logic cho hợp đồng/đơn hàngContractStateMachine.ts— State machine độc lập, không phụ thuộc UI hay Supabase- Có unit test riêng (
ContractDomain.test.ts) — dễ kiểm tra isolate
E. Infra Isolation — Sạch
database.types.tsgiữ nguyên, không bị "ô nhiễm" bởi business logicsrc/models/cung cấp domain models (joined/mapped) tách biệt khỏi DB typestenant.tsxử lý Row Level Security isolation tập trung
F. Zero Deep Relative Imports Giữa Features
- Kết quả grep
from '../../→ Không có vi phạm - Tất cả test files đều dùng
@/alias
3. Điểm Yếu & Nợ Kỹ Thuật
A. src/domain/ và src/models/ — Bị giám sát
- Phần lớn các features KHÔNG có corresponding domain object
- Business logic bị pha trộn vào hooks thay vì nằm trong domain layer
B. src/hooks/ và src/utils/ — Tầng ngoài phạm vi
- Tồn tại
src/hooks/vàsrc/utils/ở root level NGOÀIshared/ - Redundancy với
src/shared/hooks/vàsrc/shared/utils/
C. Cross-Feature Import
payments/DebtsPage.tsximport từ@/features/reports/DebtAgingSection- Vi phạm nguyên tắc: features phải độc lập (loosely coupled)
D. Một số Features Thiếu Module Definition
src/features/dashboard/— Không códashboard.module.ts- Features thiếu
.module.tsthì không cóFeatureDefinition, thiếu metadata
4. Vi Phạm Kiến Trúc Nhận Thấy
| STT | Vi phạm | File | Mức độ |
|---|---|---|---|
| 1 | Cross-feature import | payments/DebtsPage.tsx import từ reports/ | Trung bình |
| 2 | Duplicate util root | src/hooks/ vs src/shared/hooks/ | Nhẹ |
| 3 | Duplicate util root | src/utils/ vs src/shared/utils/ | Nhẹ |
| 4 | Missing module | dashboard/ không có .module.ts | Nhẹ |
| 5 | Business logic in hook | Nhiều use*.ts xử lý mapping phức tạp | Trung bình |
5. So Sánh Level Architecture
| Level | Tên | Trạng thái |
|---|---|---|
| Level 1 | Basic Components | ✅ Done |
| Level 2 | Feature Folders | ✅ Done |
| Level 3 | Shared Components | ✅ Done |
| Level 4 | API Layer tách biệt | ✅ Done |
| Level 5 | Schema-First | ✅ Done |
| Level 6 | Plugin System | ✅ Done |
| Level 7 | Domain Layer + State Machine | ⚠️ ~70% done |
| Level 8 | Event-Driven between features | ❌ Chưa có |
| Level 9 | AI Audit + Pre-commit gate | ✅ Done |
6. Khuyến Nghị Ưu Tiên
Ưu tiên cao:
- Tách
DebtAgingSectionra khỏifeatures/reports/→shared/components/ - Xóa
src/hooks/vàsrc/utils/root — merge vàosrc/shared/
Ưu tiên trung bình:
- Bổ sung
.module.tscho các features chưa có (dashboard, inventory) - Mở rộng
src/domain/— tạo domain objects cho các Bounded Contexts chính
Ưu tiên thấp:
- Tạo
src/services/đầy đủ hơn — thêm error tracking, logging service - Level 8 Event Bus — dùng custom events để features giao tiếp không cần import lẫn nhau
7. Điểm Tổng Kết
| Tiêu chí | Điểm |
|---|---|
| Infra Isolation | 9/10 |
| Contract/Schema | 9/10 |
| API Layer | 8/10 |
| Business Logic (Use-Cases) | 7/10 |
| Domain Layer | 6/10 |
| Feature Independence | 7/10 |
| Extensibility (Plugin) | 10/10 |
| Type Safety | 9/10 |
| Tổng | 65/80 = 81% |
Kết luận: Kiến trúc dự án đang ở mức "Production-Grade Level 7", vượt xa ứng dụng React thông thường. Điểm còn thiếu chủ yếu ở Domain Layer và Feature Independence (cross-feature coupling).