Tiếp theo loạt bài viết về kiến trúc đa tầngkiến trúc lục giác, hôm nay chúng ta sẽ tìm hiểu về một người anh em của chúng - kiến trúc củ hành.

#1 Khái niệm kiến trúc củ hành

Kiến trúc củ hành có một vài nét tương đồng với kiến trúc phân tầng và kiến trúc lục giác. Cụ thể, ở kiến trúc củ hành, chúng ta cũng có định nghĩa về các "tầng", tuy nhiên các "tầng" trong kiến trúc củ hành có đôi chút khác biệt so với kiến trúc phân tầng:

Tầng Domain Model: chứa các entity và các class liên quan trực tiếp tới các entity này

Tầng Domain Service: chứa các process được định nghĩa bởi domain

Tầng Application Service: chứa application logic (các use case sẽ nằm ở đây)

Tầng ngoài: chứa các thành phần còn lại của ứng dụng như UI, database, test case...

Khi 4 tầng trên được biểu diễn thành dạng vòng tròn đồng tâm, ta có một minh hoạ trực quan về kiến trúc củ hành như sau:

Đặc trưng của kiến trúc củ hành đó là một luật về sự ràng buộc giữa các tầng (dependency):

  • Vòng bên ngoài chỉ có thể phụ thuộc vào vòng trong.

Luật này đã ngầm định rằng các tầng thấp hơn (vòng trong) không thể phụ thuộc vào tầng trên. Và đó là một mô hình triển khai tuân thủ nguyên tắc Dependecy Inversion (một trong 5 nguyên tắc thiết kế hướng đối tượng S.O.L.I.D).

Ta cũng có thể suy ra các luật như sau:

  • Ứng dụng dược build xoay quanh một object model độc lập
  • Lớp bên trong định nghĩa các interface, lớp bên ngoài implement các interface này
  • Các mối ràng buộc sẽ hướng vào phần trung tâm (domain model)
  • Tất cả application core code có thể dịch và chạy mà không phụ thuộc vào infrastructure (hạ tầng)

Theo hình minh họa ở trên, ta thấy 3 vòng trong cùng tạo nên một thứ gọi là application core. Application core chứa đầy đủ các logic phục vụ việc chạy và test application tương ứng với những component bên ngoài được "cắm" vào. Nhờ áp dụng nguyên lý Dependency Inversion, ta có thể "cắm" bất kỳ component nào vào application core mà không cần thay đổi phần logic trong đó.

Làm quen và triển khai các kiến trúc xây dựng ứng dụng trong khóa thực tập NodeJS Full Stack

#2 Bản chất

Bản chất của kiến trúc củ hành xoay quanh việc áp dụng nguyên lý Dependecy Inversion kết hợp với việc định nghĩa các tầng một cách hợp lý.

Thoáng nhìn qua thì có vẻ kiến trúc củ hành không khác kiến trúc đa tầng, tuy nhiên hãy để ý đến "hướng phụ thuộc" giữa các tầng (direction of dependencies).

Ta thấy, với kiến trúc phân tầng, tầng trên sẽ phụ thuộc vào tầng dưới, cụ thể như minh họa dưới đây:

Theo lý thuyết đó, tất cả các tầng sẽ phụ thuộc vào tầng Infrastructure. Khi có mội thay đổi ở tầng Infrastructure (ví dụ: thay đổi thư viện, thay database provider...), chúng ta sẽ phải thay đổi business logic. Kiến trúc củ hành sinh ra để bảo vệ business logic trước những sự thay đổi đó. Cụ thể, ta có thể hình dung sự phụ thuộc giữa các tầng trong kiến trúc củ hành như sau:

#3 Áp dụng

Kiến trúc củ hành không định nghĩa (một cách cứng nhắc) cách implement các tầng. Do đó, chúng ta được phép tự do chọn lựa các thành phần cần đặt vào từng tầng. Tuy nhiên, lưu ý rằng Domain Model phải là phần logic trung tâm của ứng dụng, ta không được trộn lẫn nó với các thành phần không liên quan (UI, database...).

Và để thiết kế ứng dụng tuân thủ nguyên lý Dependency Inversion, ta sẽ đặt các interface ở lớp bên trong, từ đó, các class lớp bên ngoài sẽ implement những interface này.

Ví dụ lần này chúng ta hãy áp dụng cho một ngôn ngữ OOP khá phổ biến là C#. Ta cần lưu ý đến cách triển khai các interface và implement thành các class tương ứng.

Đây là cáu trúc chung của project (đã cắt bới phần configuration file)

Điều đầu tiên dễ nhận thấy là Application Core được chia tách ra khỏi Infrastructure, UI và test. Tiếp theo, hãy tìm hiểu sâu hơn phần Application Core.

Có 2 class đáng chú ý ở đây là Visitor và VisitorProcessor, chúng thuộc domain model và application service. Theo luật của kiến trúc củ hành, phần core không phụ thuộc vào các lớp bên ngoài nên phần VisitorBuilder và VisitorRepository sẽ được biểu diễn dưới dạng interface, sau đó các class ở lớp UI và Infrastructure sẽ implement những interface này.

Bạn có thể xem đầy đủ nội dung của project minh họa tại đây

#4 Ưu điểm

Kết hợp hoàn hảo với DDD: điều này không qúa bất ngờ bởi kiến trúc này xây dựng theo một domail model.

Phần code trung tâm không phụ thuộc vào các thành phần bên ngoài

Linh hoạt - với project xây dựng theo kiến trúc củ hành, chúng ta có thể giữ phần lõi và thay đổi các thành phần thuộc các lớp bên ngoài.

Dễ kiểm thử - vì phần lõi của application không phụ thuộc vaò các thành phần bên ngoài nên việc kiểm thử phần lõi trở nên nhẹ nhàng hơn.

#5 Áp dụng khi nào?

Theo quan điểm của tác giả, các trường hợp áp dụng kiến trúc củ hành cũng gần giống với kiến trúc lục giác.

Trong thế giới của các ứng dụng micro service làm việc theo kiểu request-response, ta sẽ cần một Repository interface và một hoặc 2 gateways dể bảo vệ business code khỏi các ràng buộc không mong muốn. Tác giả không giám chắc đó là một hình thức triển khai kiến trúc củ hành.

Một điều thú vị mà tác giả phát hiện ra, đó là kiến trúc củ hành có vẻ thân thiện với các lập trình viên C# hơn.

Tổng kết

Kiến trúc củ hành đã quy định mối ràng buộc giữa các lớp của ứng dụng theo nguyên tắc Dependency Inversion nhằm giảm tối đa sự phụ thuộc của các lớp bên trong ra các lớp bên ngoài.

Bạn có thể tham khảo series đầy đủ về kiến trúc củ hành và câu chuyện sau 4 năm áp dụng của Jeffrey Palermo

Tham khảo CodeCampServer - một sản phẩm thiết kế theo kiến trúc củ hành.

Techmaster via TidyJava