Level 3–4 · Mục tiêu: thoát khỏi tranh cãi danh pháp, chọn theo bài toán.


1. Khung so sánh

Mỗi “kiến trúc” thực chất trả lời một tập câu hỏi khác nhau — so sánh chỉ công bằng khi đặt đúng tầng câu hỏi:

  • Tầng tổ chức phụ thuộc trong một đơn vị deploy: Layered, Hexagonal, Onion, Clean.
  • Tầng tổ chức delivery/UI: MVC.
  • Tầng topology hệ thống: Modular Monolith (và Microservices).
  • Tầng mô hình hóa nghiệp vụ: DDD.

Chúng không loại trừ nhau — một hệ thống có thể đồng thời là: modular monolith (topology) × Clean Architecture (phụ thuộc) × DDD (mô hình) × MVC (trong tầng delivery).

2. Nhóm “cùng một ý tưởng”: Hexagonal, Onion, Clean

Hexagonal (2005)Onion (2008)Clean (2012)
Ẩn dụLục giác, ports & adaptersCác lớp vỏ hành4 vòng tròn đồng tâm
Insight trung tâmApp ở tâm; DB, UI, test đều là “adapter cắm vào port” — đối xứng hóa mọi I/ODomain model ở lõi; mọi coupling hướng vào tâmDependency Rule + đặt tên tầng (Entities/Use Cases/Adapters/Frameworks)
Quy định phần trongKhông — chỉ định nghĩa ranh giới với ngoàiCó: Domain Model / Domain Services / Application ServicesCó: Entities / Use Cases
Điểm mạnh riêngKhái niệm port/adapter sắc bén nhất; “driving vs driven side”Nhấn mạnh domain model làm tâmPhát biểu quy tắc gọn nhất; phổ biến nhất

Kết luận thẳng: ba cái này là một trường phái, khác biệt chủ yếu ở trọng tâm trình bày. Nếu team bạn cãi nhau “nên dùng Hexagonal hay Clean” — hai bên đang đồng ý với nhau mà không biết. Chọn từ vựng nào cả team thống nhất là được; tài liệu này dùng từ vựng Clean vì phổ biến, nhưng dùng khái niệm port/adapter của Hexagonal vì sắc hơn.

3. Clean vs Layered — khác biệt thật sự duy nhất

TrụcLayered cổ điểnClean/Hexagonal/Onion
Hướng phụ thuộcTrên → xuống → DB ở đáy: business import data accessMọi thứ → domain ở tâm: data access import business
Trung tâm hấp dẫnDatabase (schema định hình model)Domain model (nghiệp vụ định hình schema)
Test businessCần DB hoặc mock tầng DAL đặt cạnh implementationFake cổng do business sở hữu — thuần RAM
Chi phíThấp hơn, quen thuộc+interface, +mapping, +kỷ luật
Khi hợp lýCRUD, báo cáo, ít rule — DB đúng là trung tâm thật của bài toánRule thật, sống lâu, nhiều delivery

Một câu: Layered + đảo mũi tên ở ranh giới business/data = Clean. Toàn bộ khác biệt là Dependency Inversion (chương 1.3). Vì thế đường migrate Layered → Clean rất cụ thể: giữ nguyên các tầng, chỉ chuyển interface repository về phía business và dịch kiểu dữ liệu về domain — làm dần từng module (chương 14).

4. Clean vs MVC

MVC là pattern của tầng delivery (tách hiển thị / điều khiển / dữ liệu hiển thị), sinh ra cho GUI. Trong backend hiện đại, “MVC framework” thường nghĩa là: controller (handler) + model (ORM entity) + view (JSON serializer). Vấn đề không nằm ở MVC — mà ở chỗ MVC không có câu trả lời cho câu hỏi “business logic để đâu”, nên logic mặc định chảy vào controller (fat controller) hoặc model ORM (god model). Clean Architecture không thay thế MVC; nó bổ sung phần MVC bỏ trống: controller của MVC trở thành adapter mỏng gọi use case. So sánh “MVC vs Clean” đúng ra là “MVC-một-mình vs MVC-cộng-lõi-nghiệp-vụ”.

5. Clean Architecture vs Modular Monolith vs Microservices

Khác tầng câu hỏi: Clean tổ chức bên trong một đơn vị; Modular Monolith / Microservices tổ chức giữa các đơn vị.

Trục quyết địnhMonolith thườngModular MonolithMicroservices
Số team1–22–8nhiều, cần deploy độc lập thật
Ranh giới cưỡng chế bởiquy ướccompiler (internal/) + CImạng (tuyệt đối)
Chi phí gọi chéo00mạng + serialize + partial failure
Consistencytx chung dễtx chung được, kỷ luật dữ liệu nên cóphân tán (saga/outbox) bắt buộc
Chi phí vận hànhthấp nhấtthấpcao (discovery, tracing, on-call × N)
Sai lầm điển hìnhranh giới mục nátranh giới giả (JOIN chéo module)distributed monolith

Quan hệ với Clean Architecture: như chuỗi e-commerce (chương 12) chứng minh — Clean bên trong module là điều kiện để leo thang topology rẻ. Modular monolith là điểm dừng đúng của đa số hệ thống; microservices là công cụ giải bài toán tổ chức và vận hành, không phải bài toán code.

6. Clean Architecture vs DDD

Không phải đối thủ — bổ khuyết (toàn bộ chương 9): Clean cho vỏ (ranh giới, hướng phụ thuộc), DDD cho ruột (VO, aggregate, bounded context) và cho chiến lược chia hệ thống (context map — thứ Clean hoàn toàn không bàn). Dùng Clean không DDD → nguy cơ vỏ đẹp ruột anemic. Dùng DDD không Clean → model hay nhưng bị framework/ORM ăn mòn dần. Hệ có rule thật: dùng cả hai, liều lượng theo chương 9 mục 7.

7. Bảng chọn nhanh theo bối cảnh

Bối cảnhKhuyến nghị
Script, tool, POCKhông kiến trúc — một package, viết thẳng
CRUD nội bộ, 1–2 dev, ít ruleLayered đơn giản hoặc flat + transaction script
SaaS có domain thật, 2–8 dev, sống nhiều nămModular monolith × Clean (liều vừa) × DDD mức 1–3 — điểm ngọt của đa số
Nghiệp vụ phức tạp, nhiều teamTrên + bounded context nghiêm + event giữa module
Cần scale/deploy/compliance tách biệt có số liệuTách service từng cái có lý do, giữ Clean trong mỗi service
Hệ đọc cực nặng / search / feed+ CQRS mức 2–3 cho đúng phần đó

8. Điều các trường phái đều đồng ý (và là thứ đáng nhớ nhất)

Bóc nhãn hiệu đi, mọi kiến trúc tốt hội tụ về bốn điều đã học ở Level 1: ranh giới đặt theo trục thay đổi; phụ thuộc trỏ về phía ổn định; nghiệp vụ tách khỏi cơ chế; ranh giới phải được máy móc cưỡng chế. Ai nắm bốn điều đó có thể tự chế kiến trúc phù hợp cho bối cảnh của mình — đó chính là mục tiêu của tài liệu này, thay vì trung thành với bất kỳ nhãn hiệu nào.

Chương cuối: Level 4 — Evolutionary Architecture, Refactor Legacy, Tổ chức & Con người