Hexagonal Architecture
Tổng quan về kiến trúc Hexagonal (Port & Adapter)
Introduction
Kiến trúc Hexagonal (Port & Adapter) do Alistair Cockburn phát triển và được viết ra trên blog của ông vào năm 2005.
Ý tưởng cốt lõi của kiến trúc là tách biệt phần business logic của ứng dụng ra khỏi công nghệ và hạ tầng bên ngoài.
Architecture
Kiến trúc hexagonal không chia ứng dụng thành các tầng, mà thay vào đó là phía trong, và phía ngoài ứng dụng.
Application
Phía trong ứng dụng — Application chứa các logic quan trọng cần thiết cho nghiệp vụ, code thuần thúy và không được phụ thuộc hay sử dụng đến framework hay công nghệ bên ngoài.
Application là độc lập, chỉ phụ thuộc vào chính nó. Nhờ việc tách biệt với công nghệ bên ngoài, khối application có thể được sử dụng với bất kì framework hay hạ tầng nào mà không cần thay đổi nghiệp vụ bên trong.
Kiến trúc hexagonal không quy định cấu trúc bên trong application, N-layer, DDD, spagheti, ... đều được, miễn là nó đáp ứng được tính độc lập.
Actors
Phía ngoài ứng dụng - Actors là những thứ trong thế giới thực mà ứng dụng của chúng ta tương tác, có thể là người dùng, database, hoặc ứng dụng khác, v.v ...
Actor được chia làm hai loại, phụ thuộc vào tương tác giữa actor và ứng dụng:
- Driver/Primary Actor sử dụng ứng dụng để làm một việc gì đó (tương tác thực hiện bởi actor). Driver thường là người dùng, hoặc ứng dụng khác.
- Driven/Secondary Actor được sử dụng bởi ứng dụng ( tương tác thực hiện bởi application). Driven actor cung cấp cho ứng dụng những thứ mà ứng dụng cần để hoạt động. Driven actor có thể là database, mail server, file server, hay các ứng dụng khác ...
Ports
Application giao tiếp với thế giới bên ngoài các port. Ports là các inteface mà application định nghĩa, các actor sẽ tương tác với ứng dụng qua các interface này
Ports là ranh giới giữa ứng dụng và thế giới bên ngoài.
Giống như actor, port cũng được chia thành hai loại:
- Driver/Primary Port cung cấp cho thế giới bên ngoài các tính năng của application. Application sẽ implement các interface này. Vì vậy mà driver port còn được gọi là API hay Usercase
- Driven/Secondary Port là các interface mà application cần để hoạt động, thường là các SPI. Actor sẽ cung cấp các tính năng đáp ứng interface này.
Adapters
Thông thường thì actor sẽ tương tác với application (thông qua port) sẽ sử dụng một công nghệ nào đó, ví dụ khi client tương tác với application, có thể thông qua HTTP call, socket, ... hay khi application tương tác với db bằng spring data, jdbc ...
Adapter cho phép một công nghệ, framework tương tác với port.
Adaper cũng được chia làm hai loại:
- Primary/Driver Adapter sử dụng driver port. Nó chuyển request của một công nghệ nào đó về tương thích với port. Một ví dụ điển hình là Controller - Chuyển từ HTTP call về function-call (không phụ thuộc framework)
- Secondary/Driven Adapter implement driven port. Nó chuyển request từ application thành request tương thích với một công nghệ xác định. Ví dụ như Repository - Chuyển từ function-call (không phụ thuộc framework) thành sql query (phụ thuộc vào framework, hạ tầng ,...)
Một port có thể có nhiều adapter với nhiều công nghệ khác nhau, thông thường thì một port sẽ có 2 adapter - một mock adapter phục vụ cho test, một adapter thật.
Example
Repo dưới đây sử dụng kiến trúc hexagonal, cùng với DDD. Framework và application được chia thành các module riêng biệt để demo sự tách biệt giữa bussiness và framework
Pros & Cons
Pros
- Dễ test và có thể test các logic nghiệp vụ quan trọng từ rất sớm: Việc test có thể thực hiện dễ dàng bằng cách sử dụng các mock adapter
- Tăng khả năng maintain: Các logic quan trọng được tập trung trong application, và tách biệt khỏi bên ngoài, giúp cho nó dễ thay đổi, và dễ tìm.
- Độc lập với công nghệ: Có thể dễ dàng thay đổi công nghệ, hạ tầng mà không ảnh hưởng đến logic nghiệp vụ. Đồng thời có thể tích hợp nhiều công nghệ khác nhau vào ứng dụng.
- Tập trung vào business: Có thể phát triển logic business trước cả khi lựa chọn stack công nghệ
Cons
- Độ phức tạp cao: Project phát triển theo kiến trúc hexagon có độ phức tạp cao, yêu cầu nhiều công sức và thời gian phát triển hơn.
- Cần thêm việc mapping giữa các object trong ứng dụng và thế giới bên ngoài
Khi nào thì nên áp dụng kiến trúc?
Kiến trúc hexagonal thích hợp hơn với những project vừa và lớn, liên tục thay đổi nhờ vào tính linh động của nó.
Đối với những project nhỏ, thì độ phức tạp thêm vào do kiến trúc sẽ khiến cho thời gian phát triển dài hơn mà lợi ích đem lại rất ít