01 Cấu trúc 4 tầng
Các thành phần tổ chức thành những tầng logic nằm ngang, mỗi tầng một vai trò kỹ thuật. Đây là phân vùng kỹ thuật (technical partitioning) — nhóm theo vai trò kỹ thuật, không phải theo domain.
Phân vùng kỹ thuật ⇒ domain bị xé lẻ. Một domain (vd "Customer") nằm rải ở cả tầng Giao diện, Nghiệp vụ lẫn CSDL — nên thay đổi theo nghiệp vụ phải sửa nhiều tầng.
02 Tầng đóng / mở & Sinkhole
Layers of Isolation: thay đổi ở một tầng không ảnh hưởng tầng khác — miễn hợp đồng (contract) giữ nguyên. Cái giá để có điều đó là các tầng trên luồng chính phải đóng.
Tầng đóng
Request không được nhảy cóc — phải qua tầng ngay dưới. Cô lập thay đổi, dễ dự đoán. Đổi cả tầng Giao diện (JSF → React.js) mà không đụng tầng khác.
Tầng mở
Cho phép bỏ qua tầng đó để xuống thấp hơn. Dùng khi thêm Services layer dùng chung (log, audit) mà tầng Business có thể bỏ qua để xuống Persistence.
Anti-pattern: Architecture Sinkhole
Request chỉ đi xuyên qua các tầng mà không xử lý gì (pass-through) → khởi tạo đối tượng & xử lý dư thừa, hại bộ nhớ & hiệu suất.
Quy tắc 80/20: ~20% request là sinkhole thì chấp nhận được; nhưng tới 80% là dấu hiệu Layered không hợp với bài toán — cân nhắc style khác.
03 Đánh giá đặc tính kiến trúc
Thang 1–5 chấm: nhiều chấm = điểm mạnh. Layered mạnh ở chi phí & đơn giản, yếu gần như mọi mặt còn lại.
Một khối (monolith) = một "lượng tử" duy nhất. UI + xử lý + CSDL gắn liền nên chỉ mở rộng tới một giới hạn; một lỗi out-of-memory đánh sập cả ứng dụng.
04 Khi nên / không nên dùng
Nên dùng khi
- Ứng dụng / website nhỏ, đơn giản.
- Ngân sách & thời gian eo hẹp.
- Là điểm khởi đầu khi chưa chắc style nào tối ưu.
Tránh khi
- Hệ thống lớn, phức tạp (bảo trì/linh hoạt/triển khai suy giảm mạnh).
- Yêu cầu hiệu suất rất cao hoặc mở rộng lớn.
- Phần lớn request là sinkhole (pass-through).
05 Dựng hệ RAG theo Layered
RAG Ánh xạ hệ "Hỏi–đáp tài liệu" vào 4 tầng đóng:
| Tầng | Trong hệ RAG |
|---|---|
| Giao diện | PHP (Laravel) — web UI, nhận câu hỏi / upload tài liệu. |
| Nghiệp vụ | AnswerService — điều phối: truy hồi → dựng prompt → gọi LLM. |
| Truy xuất dữ liệu | Embedder + VectorStore client — gọi embedding & vector DB. |
| Cơ sở dữ liệu | Vector DB (pgvector) + kho tài liệu gốc. |
Tầng đóng nghĩa là Giao diện (PHP) không được gọi thẳng vector DB — phải đi qua Nghiệp vụ:
// ✗ Nhảy cóc xuống CSDL — phá layers of isolation
// $pdo->query("SELECT ... FROM embeddings ORDER BY dist LIMIT 5");
// ✓ Đi qua tầng Nghiệp vụ
$answer = $ragService->ask($question); // Business → Persistence → DB
Đánh đổi cho RAG: Layered cho ra MVP nhanh & rẻ (đúng 5★ chi phí/đơn giản). Nhưng khi tải embedding tăng, không thể scale riêng tầng Truy xuất dữ liệu — vì cả hệ là một khối (1★ mở rộng/đàn hồi). Và một "tra cứu tài liệu theo id" dễ thành sinkhole đi xuyên 4 tầng mà chẳng xử lý gì.
06 Ghi nhớ nhanh
Tiêu chuẩn mặc định (de facto) — đơn giản, quen thuộc, hợp cơ cấu tổ chức truyền thống (Conway's Law).
Tầng đóng = cô lập thay đổi — đổi/replace một tầng không lan sang tầng khác (miễn giữ contract).
Đánh đổi rõ ràng — lấy đơn giản & chi phí thấp, hy sinh mở rộng, linh hoạt, triển khai.
Coi chừng Sinkhole — quá nhiều request pass-through là tín hiệu chọn sai style (quy tắc 80/20).
Monolith = một lượng tử — chỉ mở rộng tới một giới hạn; lỗi nhỏ có thể sập cả khối.