DDD - Mô hình miền thiếu máu có phải là một antipotype không? Chúng ta có nên sử dụng các mô hình miền phong phú không? [đóng cửa]


11

Mô hình miền thiếu máu đã bị chỉ trích từ lâu bởi Evans và Fowler , vì rõ ràng nó đi ngược lại các nguyên tắc hướng đối tượng, v.v ... Cộng đồng DDD rõ ràng phù hợp với tuyên bố này.

Tuy nhiên, trong những năm gần đây, đã có những tiếng nói không đồng ý cho rằng nó hoàn toàn không phải là một phản mẫu và đó là một ví dụ về việc tuân theo các nguyên tắc RẮN.

Tôi đã làm việc rất nhiều năm bằng cách sử dụng Spring Framework. Mỗi dự án trong mỗi công ty luôn có một lớp dịch vụ chứa logic nghiệp vụ, sử dụng các kho lưu trữ hoạt động trên các mô hình thiếu máu (các thực thể JPA). Hơn nữa, hầu hết các mẫu, ngay cả những mẫu chính thức từ các chàng trai mùa xuân, đều thể hiện cách làm việc này.

Câu hỏi của tôi là: mô hình miền thiếu máu vẫn được coi là một antipotype? Có phải tất cả chúng ta đã làm những điều (liên quan đến DDD) sai? Bạn không nghĩ rằng việc có các mô hình Miền phong phú vi phạm các nguyên tắc RẮN?


2
" Mô hình miền thiếu máu vẫn được coi là một antipotype? ". Bởi một số, có. Bởi những người khác, bao gồm cả tôi, xem nó là cách viết mã thích hợp hơn hầu hết thời gian, nhưng nếu RDM phù hợp với bạn, hãy sử dụng nó. Vì vậy, bỏ phiếu để đóng này là hoàn toàn dựa trên ý kiến.
David Arno

1
Đây sẽ là một câu hỏi tuyệt vời cho một diễn đàn thảo luận / tranh luận; nhưng hiện tại không có câu trả lời có thẩm quyền. Chúng tôi thích các câu hỏi có thể được trả lời, không chỉ thảo luận.
VoiceOfUnreason

Câu trả lời:


9

ADM là một mô hình tốt cho một giải pháp dịch vụ phân tán như một dịch vụ siêu nhỏ. Nó phù hợp với nhiều trường hợp kinh doanh dựa trên web ngày nay.

Hãy xem xét nếu chúng ta có một đối tượng Miền Đặt hàng. Với cách tiếp cận OOP, chúng tôi sẽ thêm Order.Purchase () Order.Cattery (), v.v. Nó sẽ hoạt động tốt trong một ứng dụng máy tính để bàn, nơi chúng tôi giữ các đơn hàng trong bộ nhớ và thực hiện nhiều việc cho cùng một ví dụ.

Nhưng nếu chúng ta có một hệ thống phân tán, với các chương trình chỉ cần một thứ, tức là truy cập vào danh sách các đơn hàng và lần lượt mua từng đơn hàng, hoặc nhận danh sách các đơn hàng và hủy từng đơn hàng thì cả hai Phương thức trên cùng một đối tượng sẽ không giác quan. Chúng ta sẽ phải có hai Tên miền hoặc Bối cảnh:

PurchaseSystemOrder.Purchase()

CancelSystemOrder.Cancel();

Điều duy nhất mà các đối tượng này chia sẻ sẽ là cấu trúc dữ liệu của các thuộc tính.

Khi bạn thêm ngày càng nhiều microservice, bạn sẽ có hàng tá loại Đặt hàng. Sẽ không còn ý nghĩa khi nói về một Đơn hàng là một đối tượng Miền, mặc dù cùng một thứ tự khái niệm đang được xử lý bởi tất cả các hệ thống này.

Điều có ý nghĩa hơn nhiều khi có một mô hình Thiếu máu, Đơn hàng, chỉ gói gọn dữ liệu và đổi tên dịch vụ của bạn theo đó:

PurchaseService.Purchase(Order order)

Bây giờ chúng tôi có thể nói về Đặt hàng một lần nữa và chúng tôi có thể thêm bất kỳ dịch vụ mới nào chúng tôi nghĩ ra để xử lý, mà không ảnh hưởng đến các dịch vụ hiện đang triển khai khác.

Fowler và Co đến từ nền tảng hệ thống nguyên khối, trong thế giới của họ, cách tiếp cận ADM có nghĩa là một ứng dụng duy nhất với tất cả các dịch vụ riêng biệt này được khởi tạo trong bộ nhớ và OrderDTO được truyền qua và biến đổi. Điều này sẽ tồi tệ hơn nhiều so với việc đưa các phương thức lên một mô hình Đơn hàng phong phú.

Nhưng trong một hệ thống phân tán, có nhiều chương trình, mỗi chương trình chỉ yêu cầu một phương thức Đơn hàng duy nhất và chạy nó trên nhiều đơn hàng, tải từng đơn hàng, chạy phương thức và sau đó loại bỏ nó. Nó chỉ yêu cầu một Dịch vụ duy nhất và một luồng các đối tượng dữ liệu.

Xây dựng một mô hình phong phú đầy đủ, lo lắng về các yêu cầu và sự phụ thuộc của tất cả các Phương thức chỉ để gọi một mô hình duy nhất và sau đó loại bỏ đối tượng gần như ngay lập tức là vô nghĩa.

Cộng với một thay đổi đối với một trong những phương thức sẽ yêu cầu cập nhật tất cả các thành phần phân tán vì tất cả chúng đều phụ thuộc vào Mô hình phong phú cho logic của chúng.

Tôi không có chỗ trong (các) cơ sở mã của mình cho những thứ họ không cần


4
Tôi đã từ chối vì tôi nghĩ DDD đặc biệt phù hợp với microservice chính xác do khái niệm bối cảnh bị ràng buộc. Tôi nghĩ vấn đề với câu trả lời của bạn là khái niệm và lớp học của bạn sẽ giống nhau trên mỗi dịch vụ vi mô nhưng tôi nghĩ điều đó không cần thiết cũng không chính xác.
RibaldEddie

Tôi không đồng ý, ADM có thể là DDD nếu bạn gọi Dịch vụ mua hàng CashRegister của bạn và biến nó thành một phần của ngôn ngữ miền của bạn
Ewan

bạn có thể xây dựng? Tôi luôn nghĩ rằng YMMV khi ADM và DDD nằm trong một cơ sở mã RẮN J2EE hoặc .NET C # MVC EF.
RibaldEddie

Điều tôi muốn nói là thứ tự bối cảnh bị ràng buộc, PurchasingSystemOrder.Purchase () sẽ có mã giống hệt với CashRegister.Purchase (Đặt hàng) chỉ là một thay đổi đặt tên trong ngôn ngữ tên miền của bạn. Một mô hình miền phong phú có nghĩa là có cả hai phương thức Mua và Hủy trên cùng một lớp.
Ewan

1
@RibaldEddie, Theo chiều dày của cuốn sách "javaScript, những phần hay", tôi đưa ra hình ảnh này như một cuộc tranh luận (không hoàn toàn nghiêm trọng) chống lại việc sử dụng DDD để triển khai microservice;)
David Arno

3

RẮN và DDD là trực giao với nhau, có nghĩa là chúng thực sự đi theo các hướng khác nhau. Bạn không nên nói rằng cái này được sử dụng để loại trừ cái kia, vì chúng có thể và có lẽ nên tồn tại cùng nhau trong cùng một cơ sở mã.

Các mô hình miền thiếu máu chỉ trở thành một mô hình chống khi miền vấn đề của bạn có nhiều hành vi và bạn có hàng trăm phương thức dịch vụ với rất nhiều logic hoặc phụ thuộc được sao chép trong đó các phương thức của lớp dịch vụ phải gọi các phương thức của lớp dịch vụ khác để thực hiện bất kỳ điều gì.

DDD là một mô hình tuyệt vời cho các dịch vụ vi mô vì khái niệm bối cảnh bị ràng buộc .

Coi chừng sự cám dỗ để xem mã cơ sở hạ tầng là một phần của tên miền của bạn. Mã cơ sở hạ tầng là bất cứ thứ gì bạn không tự viết hoặc bất cứ thứ gì được ghép vào khung hoặc thư viện tương tác với hệ thống của bên thứ ba. Kết nối cơ sở dữ liệu, thư mail SMTP, thư viện ORM, thời gian chạy máy chủ ứng dụng, tất cả những thứ đó là cơ sở hạ tầng và bạn không nên bao gồm hoặc phụ thuộc vào nó trong miền của mình nếu bạn có thể tránh được.

Nguyên tắc RẮN là một tập hợp các khái niệm OOP cho mục đích chung mà bạn có thể sử dụng để tạo mã OOP tốt hơn. Bạn có thể viết một cơ sở mã DDD tốt bằng cách sử dụng chúng.


Liên quan đến việc tách mã cơ sở hạ tầng từ tên miền. Cho đến nay tôi đã coi Thực thể JPA là miền của mình, có các lớp ứng dụng sau: bộ điều khiển -> dịch vụ -> kho lưu trữ -> tên miền (Thực thể JPA). Điều gì sẽ là đúng (hoặc một trong những cách đúng) để mô hình hóa nó theo quan điểm của bạn? Một cái gì đó như: bộ điều khiển -> mô hình phong phú -> x? Làm thế nào và ở đâu tôi sẽ đối phó với giao dịch? Và bản đồ JPA thì sao? Chúng ta sẽ không phải sao chép mô hình phong phú của mình với các thực thể JPA riêng biệt chứ?
codependent

Một thực thể JPA là một đối tượng Java cũ đơn giản. Ánh xạ là một phần của cơ sở hạ tầng nhưng bản thân lớp không cần phải có. Nếu bạn chọn coi nó là một phần của cơ sở hạ tầng thì bạn nên xem nó như một đối tượng truyền dữ liệu được sử dụng trong Nhà máy hoặc Kho lưu trữ để tạo Thực thể miền.
RibaldEddie

1

Một miền phong phú là tốt đẹp khi được thực hiện tốt. Một cơn ác mộng khi không. Một miền thiếu máu luôn luôn là xấu. Nhưng nó là một loại xấu thoải mái quen thuộc.

Nếu một miền thiếu máu là tất cả những gì bạn muốn, bạn đã chọn sai ngôn ngữ khi bạn chọn một ngôn ngữ có mục đích chung. Ngôn ngữ thế hệ thứ 4 chuyên về việc sử dụng cụ thể. Nếu thiếu máu là đủ tốt để sử dụng chúng sẽ làm cho cuộc sống của bạn dễ dàng hơn.

Nhiều khung công tác xâm nhập vào không gian ngôn ngữ cho đến khi bạn không thể quảng cáo công việc như một công việc java nữa. Đó là một công việc Java / Spring. Những gì họ đang làm, bên cạnh việc khiến bạn phụ thuộc vào họ, là biến một ngôn ngữ có mục đích chung thành một hình thức khốn của ngôn ngữ thế hệ thứ 4.

Đó là một thực hành tốt nhất hoặc một mô hình chống? Vâng, ông chủ của bạn chủ yếu chỉ quan tâm đến việc bạn có thể thuê người làm việc trên cơ sở mã. Vì vậy, nếu chúng ta phải giả vờ rằng chúng ta đang sử dụng một ngôn ngữ có mục đích chung để thuê người thì chúng ta sẽ làm.

Nếu bạn ổn với điều đó thì tốt. Bạn chắc chắn không phải là người duy nhất.

Nhưng đừng nói với tôi rằng nó phải như thế nào. Đừng nói với tôi rằng nó làm bất cứ điều gì cho tôi nhiều hơn nó. Tôi biết cách sống mà không có nó. Tôi biết làm thế nào để đẩy nó ra để chỉ một vài điều phụ thuộc vào nó. Nếu bạn yêu cầu tôi nhượng bộ và để nó chiếm lấy mọi thứ chỉ vì chiến đấu là khó khăn thì vâng tôi nghĩ điều đó thật tệ.

Tôi không có chỗ trong cơ sở mã của mình cho những thứ nó không cần.

Đối với RẮN và các nguyên tắc thiết kế khác, tôi phần lớn có thể tuân theo những nguyên tắc đó ngay cả trong một miền thiếu máu. Không theo họ gây ra một loại vấn đề khác.


Tôi đánh giá cao câu trả lời của bạn và hoàn toàn đồng ý rằng một số khung như Spring hoặc JPA-Hibernate đã chinh phục được cảnh quan Java. Tuy nhiên, cũng không thể phủ nhận rằng họ đã cung cấp một loạt các thực tiễn tốt và đơn giản hóa mà Java (JEE) hoàn toàn không giải quyết hoặc đã làm sai. Tôi thực sự nhiệt tình về DDD và muốn hiểu tất cả các nguyên tắc họ nói. trải nghiệm, các nền tảng / ngôn ngữ / khung tốt nhất để hoạt động với các ứng dụng DDD thuần túy (với Mô hình miền phong phú) là gì? Bạn có biết mẫu Github tốt nào không? Như bạn nói tôi muốn làm tốt mọi thứ, không phù hợp với thực tiễn xấu.
codependent

Chúng tôi không làm khuyến nghị tài nguyên ở đây. Nhưng tôi tin rằng một lớp cơ sở hạ tầng thích hợp liên quan đến các khung có nghĩa là bạn có thể sử dụng bất kỳ loại nào bạn thích. Chỉ cần đối xử với họ như một thư viện. Giữ kiến ​​thức về họ ra khỏi miền. Ngoài ra, đừng dựa vào ma thuật. Chống lại sự thôi thúc sử dụng những thứ bạn không thể tự làm. Nguyên nhân một số ngày bạn có thể cần phải.
candied_orange

Quay trở lại điểm ban đầu. Còn nguyên tắc RẮN thì sao? Các mô hình miền phong phú đảm nhận nhiều trách nhiệm, kiên trì (JPA), logic kinh doanh (phải xử lý giao dịch), v.v ... Mặt khác, các mô hình thiếu máu chỉ quan tâm đến sự kiên trì khi tách các dịch vụ xử lý logic kinh doanh. Âm thanh cũng dễ dàng hơn để kiểm tra. Có chuyện gì vậy?
codependent

Điều chính là bạn bắt đầu thực hiện các lựa chọn thiết kế dựa trên nhu cầu hệ thống thay vì nhu cầu ngữ nghĩa. Nó tinh tế, dễ bỏ qua, chi phí không rõ ràng và khó để biện minh cho việc sửa chữa. Nói tóm lại, nó giống như lập luận rằng các đường dây điện nên được chôn chứ không phải trong các cuộc thăm dò. Khi mọi người đã quen với phương án thay thế, nó không có khả năng thay đổi. Ngay cả khi cơn bão đánh sập nguồn điện.
candied_orange

1
Tôi sẽ mang đến cho bạn lợi ích của sự nghi ngờ đối với tuyên bố của bạn rằng "Một miền giàu có là tốt khi được thực hiện tốt. Một cơn ác mộng khi không." Có lẽ tôi chưa bao giờ thấy nó hoạt động tốt, nhưng sau đó bạn đưa ra tuyên bố vô nghĩa rằng "Một miền thiếu máu luôn xấu." Ý kiến ​​vô nghĩa khiến câu trả lời của bạn vô giá trị. -1
David Arno
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.