2012-05-04 27 views
15

An interesting thread xuất hiện khi tôi nhập câu hỏi này ngay bây giờ. Tôi không nghĩ rằng nó trả lời câu hỏi của tôi mặc dù."Mô hình miền giàu có" có vi phạm Nguyên tắc về trách nhiệm duy nhất không?

Tôi đã làm việc rất nhiều với .NET MVC3, nơi mong muốn có mô hình thiếu máu. Xem mô hình và chỉnh sửa mô hình là tốt nhất như là container dữ liệu câm mà bạn chỉ có thể vượt qua từ một bộ điều khiển để xem. Bất kỳ loại luồng ứng dụng nào cũng đến từ các bộ điều khiển và các khung nhìn xử lý các mối quan tâm về giao diện người dùng. Trong MVC, chúng tôi không muốn bất kỳ hành vi nào trong mô hình.

Tuy nhiên, chúng tôi cũng không muốn bất kỳ logic nghiệp vụ nào trong bộ điều khiển. Đối với các ứng dụng lớn hơn, tốt nhất là giữ mã miền riêng biệt và độc lập với các mô hình, chế độ xem và bộ điều khiển (và HTTP nói chung cho vấn đề đó). Vì vậy, có một dự án riêng biệt cung cấp, trước bất cứ điều gì khác, một mô hình miền (với các thực thể và các đối tượng giá trị, được tổng hợp thành các tập hợp theo DDD).

Tôi đã thực hiện một vài nỗ lực để chuyển từ mô hình thiếu máu sang một mô hình phong phú hơn trong mã miền và tôi đang nghĩ đến việc từ bỏ. Dường như với tôi như có các lớp thực thể mà cả hai chứa dữ liệu và hành vi vi phạm SRP.

Lấy ví dụ một trường hợp rất phổ biến trên web, soạn email. Với một số sự kiện, trách nhiệm của miền là soạn một đối tượng EmailMessage được cung cấp một EmailTemplate, EmailAddress và các giá trị tùy chỉnh. Mẫu tồn tại dưới dạng thực thể có thuộc tính và giá trị tùy chỉnh được cung cấp dưới dạng đầu vào của người dùng. Chúng ta cũng nói vì lợi ích của lập luận rằng địa chỉ FROM của EmailMessage có thể được cung cấp bởi một dịch vụ bên ngoài (IConfigurationManager.DefaultFromMailAddress). Với những yêu cầu, nó có vẻ như một mô hình miền giàu có thể cung cấp cho các EmailTemplate trách nhiệm của soạn EmailMessage:

public class EmailTemplate 
{ 
    public EmailMessage ComposeMessageTo(EmailAddress to, 
     IDictionary<string, string> customValues, IConfigurationManager config) 
    { 
     var emailMessage = new EmailMessage(); // internal constructor 
              // extension method 
     emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues); 
     emailMessage.From = this.From ?? config.DefaultFromMailAddress; 
     // bla bla bla 
     return emailMessage; 
    } 
} 

Đây là một trong những nỗ lực của tôi tại mô hình miền giàu có. Tuy nhiên, sau khi thêm phương thức này, trách nhiệm của EmailTemplate đối với cả hai đều chứa các thuộc tính dữ liệu thực thể và soạn thư. Nó dài khoảng 15 dòng, và dường như làm xao lãng lớp học từ những gì nó thực sự có nghĩa là một EmailTemplate - mà, IMO, là chỉ lưu trữ dữ liệu (định dạng chủ đề, định dạng cơ thể, tệp đính kèm và tùy chọn từ/trả lời địa chỉ).

Tôi đã kết thúc việc tái cấu trúc phương thức này thành một lớp dành riêng, người chịu trách nhiệm duy nhất là soạn một EmailMessage cho các đối số trước và tôi hạnh phúc hơn nhiều với nó. Trong thực tế, tôi bắt đầu thích các tên miền thiếu máu vì nó giúp tôi giữ trách nhiệm riêng biệt, làm cho các lớp và bài kiểm tra đơn vị ngắn hơn, ngắn gọn hơn và tập trung hơn. Dường như việc tạo ra các thực thể và các đối tượng dữ liệu khác "không có hành vi" có thể tốt cho việc phân chia trách nhiệm. Hay tôi đang theo dõi ở đây?

+1

Một mô hình tên miền phong phú chỉ cần đủ phong phú cho ngữ cảnh có liên quan. –

Trả lời

19

Đối số ủng hộ mô hình tên miền phong phú thay vì mô hình thiếu máu bản lề trên một trong các mệnh đề giá trị của OOP, đó là giữ hành vi và dữ liệu bên cạnh nhau. Lợi ích cốt lõi là sự đóng gói và sự gắn kết hỗ trợ trong lập luận về mã. Một mô hình miền phong phú cũng có thể được xem như một thể hiện của mẫu information expert. Tuy nhiên, giá trị của tất cả các mô hình này là chủ quan lớn. Nếu bạn hữu ích hơn trong việc giữ dữ liệu và hành vi riêng biệt, thì hãy là vậy, mặc dù bạn cũng có thể xem xét những người khác sẽ xem mã đó. Tôi thích đóng gói nhiều nhất có thể. Lợi ích khác của mô hình miền phong phú hơn trong trường hợp này sẽ là khả năng làm cho các thuộc tính nhất định trở thành riêng tư. Nếu một thuộc tính chỉ được sử dụng bởi một phương thức trên lớp, tại sao nó lại công khai?

Liệu mô hình miền phong phú vi phạm SRP có phụ thuộc vào định nghĩa trách nhiệm của bạn hay không. Theo SRP, trách nhiệm là một lý do để thay đổi, mà chính nó đòi hỏi một định nghĩa. Định nghĩa này nói chung sẽ phụ thuộc vào trường hợp sử dụng trong tầm tay.Bạn có thể khai báo rằng trách nhiệm của lớp mẫu là một khuôn mẫu, với tất cả các hàm ý nảy sinh, một trong số đó tạo ra một thông báo từ khuôn mẫu. Một thay đổi trong một thuộc tính mẫu có thể ảnh hưởng đến phương thức ComposeMessageTo, cho biết rằng có lẽ đây là một trách nhiệm duy nhất. Hơn nữa, phương pháp ComposeMessageTo là phần thú vị nhất của mẫu. Khách hàng của mẫu không quan tâm cách thức phương thức được triển khai hoặc thuộc tính nào có mặt của lớp mẫu. Họ chỉ muốn tạo thông báo dựa trên mẫu. Điều này cũng bỏ phiếu ủng hộ việc giữ dữ liệu bên cạnh phương pháp.

+0

Câu trả lời hay, cảm ơn bạn. – danludwig

0

Vâng, điều đó tùy thuộc vào cách bạn muốn xem nó.

Một cách khác là: "Nguyên tắc về trách nhiệm duy nhất có vi phạm mô hình tên miền phong phú không?"

Cả hai đều là các nguyên tắc. Không có "nguyên tắc" ở bất kỳ đâu trong thiết kế phần mềm. Tuy nhiên, có thiết kế tốt và thiết kế xấu. Cả hai khái niệm này có thể được sử dụng theo nhiều cách khác nhau, để đạt được một thiết kế tốt.