Hexagonal Architecture - Ports and Adapters

Kiến trúc hình lục giác (Hexagonal Architecture) - còn gọi là Ports and Adapters - đưa ý tưởng tách domain khỏi hạ tầng đi xa hơn, tạo cách linh hoạt để kết nối ứng dụng với các hệ thống bên ngoài. Do Alistair Cockburn đề xuất năm 2005, mục tiêu: ứng dụng không phụ thuộc framework, DB hay bất kỳ công nghệ cụ thể nào.

Đây là bước tiến hóa từ Layered Architecture - Kiến trúc Phân lớp, chuyển trọng tâm vào domain thay vì bận tâm framework/database.

⬡ Ẩn dụ “hình lục giác”

Hình lục giác chỉ mang tính ẩn dụ: một lục giác có 6 cạnh, tượng trưng cho việc ứng dụng có nhiều “cổng” (port) để giao tiếp (không nhất thiết đúng 6, số lượng tùy nhu cầu).

Điểm mấu chốt: mọi tương tác từ bên ngoài đều phải đi qua một Port - Cổng giao tiếp và một Adapter - Bộ chuyển đổi để đến được lõi, và ngược lại.

Hình dung như cổng USB: port giống cổng kết nối trên máy tính, adapter là “đầu nối” cụ thể cắm vào (dây sạc, USB drive). Máy tính không quan tâm bạn cắm thiết bị gì, miễn tuân thủ giao thức cổng. Tương tự, ứng dụng không quan tâm chi tiết bên ngoài, miễn adapter tuân theo interface của port.

🔗 Quan hệ với kiến trúc phân lớp

Hexagonal không thay thế mà bổ sung cho Layered:

  • Domain + Application = lõi của lục giác.
  • Infrastructure = các adapter bao quanh.

Khác biệt: hexagonal đề nghị nghĩ rõ hơn về các loại interaction - liệt kê những “kết nối ngoài” cụ thể (UI, DB, Mail, Payment, Logging) và tạo cơ chế cắm-rút cho từng cái.

🛠️ Các bước áp dụng

  1. Xác định các port cần có: dựa vào use case (UI/API/CLI = input port) và phụ thuộc ngoài (DB, cache, email = output port).
  2. Định nghĩa interface/hợp đồng cho mỗi port trong core (OrderRepository, NotificationService, PaymentGateway).
  3. Triển khai adapter tương ứngTầng Infrastructure (bản thật: MySQL, Stripe; bản giả: FakeRepository cho test).
  4. Kết nối bằng Dependency Injection: container bind interface port → class adapter cụ thể.

🎯 Lợi ích nổi bật

  • Decouple tuyệt đối core khỏi bên ngoài - core không bao giờ “kẹt” với công nghệ nào.
  • Thử nghiệm dễ, tăng chất lượng - chạy use case với in-memory adapter thay I/O thật.
  • Đổi công nghệ không ảnh hưởng core - đổi email→SMS chỉ cần adapter mới cho port Notification.
  • Hỗ trợ đa kênh, đa nền tảng - thêm API/mobile chỉ là thêm adapter.
  • Rất hữu dụng khi tích hợp giữa các Bounded Context khác nhau.

⚠️ Đánh đổi

Số lượng interface/class tăng đáng kể → cần trình độ tổ chức cao và quy ước đặt tên. Đừng trừu tượng hóa quá mức - tập trung port & adapter vào những điểm dễ thay đổi/khó test.

Liên quan