Trong Model của DDD thì dùng rất nhiều các pattern khác nhau như là Entity, value object, Repository, Factory, service … Nhưng trước khi bắt đầu về DDD, thì chúng ta nên tìm hiểu Model của DDD có gì đặc biệt và nó khác model truyền thống như thế nào. Tại sao DDD lại có thể giúp chúng ta mô hình hoá được các nghiệp vụ vào trong code. Bài viết này mình sẽ so sánh model của DDD hay còn gọi là Rich Model với anenic model mà khá là phổ biến trong MVC hoặc DAO ( data access object)
Anemic Model
Anemic model đơn giản chỉ là các thực thể (Entity) mà dùng để biểu diễn bằng các class mà chỉ chứa các thông tin của data hoặc là các liên kết với các Entity khác. Những class này thì thường không biểu diễn các logic của nghiệp vụ và logic thì thường được đặt ở trong phần Service, Util và helpers.. Chúng ta thường dùng cách này để mô hình hoá một đối tượng ở trong source code
Khi chúng ta thực hiện một chức năng, thì thông thường sẽ tạo ra một class để giúp lưu giữ các thông tin và thường gọi những class này là Entity. Những Entity này sẽ thường biểu diễn cho các bảng của Database, chúng thường sẽ không biểu diễn các logic của nghiệp vụ gì cả mà đơn giản chỉ là Map thông tin với các bảng và ràng buộc giữa chúng trong database mà thôi, phổ biến nhất là chúng ta hay dùng ORM
Sau khi chúng ta tạo ra các entity mà map với các bảng và thông tin trong DB thì tiếp theo sẽ tạo ra các class để đọc và ghi chúng. Một pattern rất phổ biến đó là lớp DAO (Data access object), nó sẽ giúp chúng ta lấy các thông tin trong DB và apply nó vào các class. Thông thường thì mỗi Entity sẽ biểu diễn cho một chức năng nhất định và số lượng DAO class sẽ tương ứng với số lượng Entity nhưng hãy nhớ rằng nó sẽ không chứa tí gì về logic trong đấy cả. DAO class đơn giản chỉ là giúp chúng ta lấy các giữ liệu từ DB và lưu giữ nó trong các Entity mà thôi. Hiện này thì hầu hết các ngôn ngữ lập trình đều có các framework và hỗ trợ pattern này
Bên trên lớp DAO này thường là lớp Service. Service sẽ sử dụng DAO để thực hiện các logic và nghiệp vụ của một chức năng cụ thể. Bất kể là có bao nhiêu tính năng hay nghiệp vụ thì Service luôn luôn thực hiện theo các bước: Lấy các Entity bằng cách dùng DAO, sau đó sẽ cập nhập các trạng thái của chúng dựa theo yêu cầu của bài toán và lưu thay đổi đấy. Thiết kế này thì đã được Martin Fowler miêu tả như là một chuỗi các Transaction script. Khi các chức năng ngày càng trở nên phức tạp hơn, thì số lượng cần thực thi cũng sẽ tăng lên trong việc lấy các dữ liệu, xử lý và lưu giữ chúng. Thường để xử lý các việc này thì một vài service sẽ bắt đầu gọi các service khác, kết quả là làm cho chức năng các thêm phức tạp, source code ngày càng nhiều hơn và khó kiểm soát hơn và tất cả đều được đặt ở Service. Các Entity và DAO cũng vậy sẽ ngày càng phức tạp hơn
DDD là một cách tiếp cận hoàn toàn khác trong việc cấu trúc source code và phân chia ở các layer
Rich Model
Kiến trúc của Domain Driven Design Model được biểu diễn ở hình bên phải và nó dùng Rich Model
Rich Model dựa theo các nguyên tắc hướng đối tượng, do đó một rich domain model thực ra là một OOP và mục đích của nó là mang dữ liệu và logic được đặt cùng với nhau. Nguyên tắc của hướng đối tượng là một object có thể quản lý trạng thái của nó và đảm bảo rằng trạng thái đấy là hợp lệ trong bất kỳ thời điểm nào.
Các bạn để ý sẽ thấy rằng lớp Service của Domain Driven Design sẽ nhỏ hơn rất nhiều so với Anemic Model. Lý do là vì hầu hết toàn bộ logic của nghiệp vụ sẽ được đặt ở lớp Domain: Entity, Value Object và Aggregate. Lớp Service giờ đây chúng ta sẽ chỉ đặt các hoạt động mà làm việc với nhiều Domain khác nhau.
Trong DDD thì lớp Domain sẽ có nhiều kiểu object khác nhau. Đó là Entity, value object và những object tổng hợp giữa chúng mà trong DDD thì gọi là Aggregate. Các Aggregate có thể được kết nối với nhau chỉ bằng các identifier của Aggregate Root. Chúng sẽ không chia sẽ bất kỳ dữ liệu nào khác với các Agreegate khác
Trong DDD thì Repository giúp chúng ta tương tác với database nhưng chú ý rằng nó sẽ không truy cập một cách trực tiếp mà nó chỉ thường chỉ là một lớp abstract ( interface) mà thôi, còn việc phía sau thì nó có thể được implement kết nối với một database hoặc cũng có thể thông tin đó được gọi thông qua API nào đấy. Số lượng Repository thường sẽ tương đương với số Aggregate trong DDD, nên các ứng dụng vơi Anemic Model thì sẽ có nhiều Repository hơn là trong Rich Model
Kết luận
Khi sử dụng kiến trúc DDD model nó mang tới rất nhiều lợi ích cho lập trình viên
Bằng việc chia các object ra thành Entity và value object chúng ta có thể quản lý một cách chính xác hơn khi tạo ra các object trong ứng dụng. Aggregate cho phép chúng ta đóng gói các domain, do dó API được thực hiện đơn giản hơn và các thay đổi bên trong Aggregate cũng dễ dàng hơn. Chúng ta sẽ không cần quan tâm rằng những thay đổi này sẽ ảnh hưởng đến các Aggregate khác
Trong DDD các Aggregate kết nối và truy cập thông qua Aggrerate root nên nó giảm được các kết nối, sự phụ thuộc lẫn nhau và đảm bảo được tính toàn vẹn dữ liệu, qua đó giảm được rủi ro khi bug phát sinh hay chỉnh sửa source code.
Domain giúp cho chất lượng code tốt hơn khi nó phản ánh được những logic, nghiệp vụ mà Domain Expert diễn tả. Nó cũng giúp dễ dàng hơn trong việc quyết định một giải pháp chính xác nhất và nếu cần thiết thì có thể thay đổi và triển khai chúng
Rich Model là một lựa chọn tốt nhưng cũng không thể phủ nhận rằng chi phí để phát triển cũng cao hơn rất nhiều so với Anemic Model. Nên đối với các ứng dụng đơn giản mà chỉ cần thao tác CURD với Database thì chúng ta nên dùng Anemic Model vì nó giúp phát triển nhanh chóng. Nếu bạn làm việc trên các ứng dụng lớn, nghiệp vụ phức tạp thì nên dùng Rich Model hay DDD model