Đầu tiên chúng ta bắt đầu với bài toán quản lý sản phẩm với các nghiệp vụ phức tạp. Ví dụ hệ thống quản lý sản phẩm của các trang thương mại điện tử (Amazon, shoppe, tiki..).

Với bất kì sản phẩm phần mềm nào, chúng ta đều có chung mục đích thiết kế:

– DRY (Don’t Repeat Yourself), các nghiệp vụ được phân tách rõ ràng, cô đọng và tập trung cao.
– Có thể mở rộng, sửa đổi các thành phần độc lập.
– Linh hoạt trong việc phát triển.
– Dễ dàng test và bảo trì.

Các mục tiêu này sẽ ảnh hưởng tới cách thiết kế mô hình ứng dụng khác nhau. Chúng ta sẽ phân tích 3 mô hình thiết kế hay được sử dụng để tìm hiểu ưu, nhược điểm cũng như chọn cách thiết kế hệ thống phù hợp nhất.

Mô hình MVC

Mô hình MVC là mô hình phổ biến trong việc lựa chọn và xây dựng ứng dụng.
Đó là mô hình đơn giản, dễ tiếp cận và nhanh chóng đưa ra các tính năng.
Theo mô hình MVC thì phần quản lý sản phẩm sẽ theo mô hình như sau:

Với mô hình MVC như trên việc xử lý ở product model sẽ trở nên phức tạp. Lúc này product model sẽ là nơi:

– Định nghĩa các thuộc tính của product.
– Truy xuất database.
– Và thực thi các nghiệp vụ.

Thông thường mô hình MVC sẽ sử dụng pattern Active Record để mapping với database. Đây là cách làm đơn giản, nhưng có các hạn chế sau:

– Model product trở nên quá nặng khi chứa quá nhiều các logic từ định nghĩa thuộc tính, truy xuất dữ liệu, thực thi nghiệp vụ…
– Do không phân tách được các tầng nghiệp vụ và dữ liệu, nên khó thực hiện unit test các thành phần riêng biệt.
– Việc thay đổi logic truy xuất dữ liệu và logic nghiệp vụ khó khăn. Do các thành phần bị phụ thuộc vào nhau.
– Tính đóng gói của nghiệp vụ không đảm bảo. Các nghiệp vụ sẽ chỉ được cài đặt theo mô hình CRUD. Vì vậy càng về sau sự trùng lặp các logic càng cao.

Do các hạn chế đó nên đây không phải mô hình phù hợp với các ứng dụng logic phức tạp như ecommerce. Nó sẽ dẫn tới chi phí maintain về sau cao.

Mô hình ba lớp.

Hướng tiếp cận tiếp theo là phân tích và thiết kế theo phương pháp n-tier hay Domain Driven Design. Đặc trưng của mô hình này là:

– Phân tách tầng nghiệp vụ khỏi tầng ứng dụng và tầng truy xuất cơ sở dữ liệu. Tầng này gọi là Domain Layer. Tầng này là nơi chứa tất cả các logic nghiệp vụ.
– Trong tầng nghiệp vụ, tập trung vào design model sao cho model phản ánh đầy đủ nhất tính chất nhất quán của nghiệp vụ. Tầng này có thể chia thành 2 phần riêng biệt là Domain ModelDomain Service. Domain Service đóng vai trò cung cấp các nghiệp vụ ra bên ngoài (tới tầng Aplication) xoay quanh các domain model của hệ thống.
– Thiết kế tầng infrastructure chứa các logic về truy xuất dữ liệu, thao tác với database, messeage queue.

DDD Partern

Lợi ích:
Với việc tổ chức hệ thống này, các tầng ứng dụng, nghiệp vụ và data access sẽ chia tách riêng biệt, và chỉ tương tác thông qua interface. Các nghiệp vụ sẽ xoay quanh model product. Tầng data access sẽ truy xuất hoặc lưu trữ các object products.
Hạn chế:
Việc áp dụng mô hình 3 lớp xoay quanh model product cũng dẫn tới khó khăn là việc thiết kế model cho các nghiệp vụ đọc-dữ-liệu.
Đồng thời nó cũng ảnh hưởng tới tốc độ phát triển của hệ thống khi cài đặt các nghiệp vụ query đa dạng và phức tạp trong khi phuc vụ client. Việc này bị ảnh hưởng bởi cách thiết kế model và tầng Repository.

Mô hình CQRS

Mô hình CQRS (Command Query Responsibility Segregation) là sử mở rộng của mô hình trong ba lớp trong DDD. Đặc trưng quan trọng của CQRS là việc tách hai phần logic đọc và ghi dữ liệu ra hai phần riêng biệt:

– Phần ghi dữ liệu: được thực hiện qua việc send các command tới các handler thông qua command bus. Comand hanlder đóng vai trò tương tự domain service sẽ tương tác với các model để thực hiện các nghiệp vụ thay đổi dữ liệu.
– Phần đọc dữ liệu: được thiết kế riêng không lệ thuộc vào các model của phần ghi dữ liệu. Do đó có thể linh hoạt trong việc truy xuất database, cũng như sử dụng các data source khác nhau để tối ưu về tốc độ truy xuất.


Mô hình CQRS đã khắc phục các hạn chế đã nêu ở mục 2 bên trên. CQRS mang lại các lợi thế lớn:

– Cho phép phát triển và tối ưu phần đọc dữ liệu riêng biệt với phần ghi dữ liệu.
– Việc mô hình hoá các nghiệp vụ ghi dữ liệu dưới các command cho phép che đậy tốt các logic nghiệp vụ, giúp việc mở rộng dễ dàng hơn. Đồng thời các command đó có thể dễ dàng chuyển đổi giữa xử lý đồng bộ và bất đồng bộ thông qua lớp abstractcommand bus mà không thay đổi mô hình. Giúp cung cấp một mô hình nhất quán, xuyên suốt trong bộ kiến trúc.

Tóm tắt về 3 mô hình (cả 3 mô hình trên đều có ưu/nhược điểm)

– Mô hình MVC đơn giản, nhưng hạn chế khi giải quyết nghiệp vụ phức tạp và testing, mở rộng
– Mô hình ba lớp phù hợp cho việc xử lý nghiệp vụ phức tạp, nhưng có nhiều hạn chế khi tối ưu phần đọc ra.
– Mô hình CQRS mở rộng từ mô hình ba lớp, giải quyết tốt việc chia tách đọc ghi, nhưng cũng đòi hỏi phải thiết kế phức tạp hơn.

Trên đây, chúng ta đã tìm hiểu qua về 3 mô hình khi thiết kế hệ thống. Và với các hệ thống lớn, cần đòi hỏi xử lý nghiệp vụ phức tạp, đồng thời đáp ứng hiệu năng, mô hình chúng ta nên chọn là CQRS. Mặc dù còn hạn chế về độ phức tạp khi triển khai, đòi hỏi team work cùng hiểu về hệ thống, tuy nhiên những giá trị mà nó mang lại nên được đánh đổi.

Phần tiếp theo chúng ta sẽ tìm hiểu tiếp về mô hình CQRS-ES.

Bài viết được tham khảo từ
tiki-engineering.
future-processing.