2010-05-18 27 views
67

Tôi đang cố gắng hiểu Mô hình miền lưu hành và lý do tại sao chúng được cho là chống mẫu.Tránh mô hình miền thiếu máu - một ví dụ thực tế

Đây là ví dụ về thế giới thực.

Tôi có một lớp nhân viên, trong đó có một tấn tài sản - tên, giới tính, tên người dùng, vv

public class Employee 
{ 
    public string Name { get; set; } 
    public string Gender { get; set; } 
    public string Username { get; set; } 
    // Etc.. mostly getters and setters 
} 

Tiếp theo chúng ta có một hệ thống có liên quan đến quay cuộc gọi đến và yêu cầu trang web (được gọi là 'dẫn ') đồng đều giữa các nhân viên bán hàng. Hệ thống này khá phức tạp vì nó liên quan đến các yêu cầu round-robining, kiểm tra các ngày lễ, sở thích của nhân viên, vv Vì vậy, hệ thống này hiện được tách ra thành một dịch vụ: EmployeeLeadRotationService.

public class EmployeeLeadRotationService : IEmployeeLeadRotationService 
{ 
    private IEmployeeRepository _employeeRepository; 
    // ...plus lots of other injected repositories and services 

    public void SelectEmployee(ILead lead) 
    { 
     // Etc. lots of complex logic 
    } 
} 

Sau đó, trên mặt sau của mẫu yêu cầu trang web của chúng tôi, chúng tôi có mã như thế này:

public void SubmitForm() 
{ 
    var lead = CreateLeadFromFormInput(); 

    var selectedEmployee = Kernel.Get<IEmployeeLeadRotationService>() 
           .SelectEmployee(lead); 

    Response.Write(employee.Name + " will handle your enquiry. Thanks."); 
} 

tôi không thực sự gặp phải nhiều vấn đề với cách tiếp cận này, nhưng được cho là đây là điều mà tôi nên chạy la hét vì đó là Mô hình miền thiếu máu.

Nhưng đối với tôi, không rõ nơi logic trong dịch vụ xoay vòng phải đi. Nó có nên dẫn đầu không? Nó có nên đi vào nhân viên không?

Điều gì về tất cả các kho được tiêm vv mà dịch vụ xoay yêu cầu - chúng sẽ được tiêm vào nhân viên như thế nào, vì hầu hết thời gian khi giao dịch với nhân viên, chúng tôi không cần bất kỳ kho lưu trữ nào?

+0

+1 câu hỏi tuyệt vời! – mdma

+0

Vì vậy, những gì hiện một 'ILead' trông giống như, nếu nó không phải là rõ ràng để đặt .SelectEmployee() trong nó? –

+0

Vâng dẫn đầu trong trường hợp này là một cuộc điều tra web, vì vậy nó sẽ có một tài sản bình luận vv Nhưng chúng tôi cũng có điện thoại yêu cầu, ứng dụng, báo giá vv mà là tất cả hơi khác nhau. Giao diện ILead sẽ có các thuộc tính như LocationOfLead, TimeOfLead vv – cbp

Trả lời

49

Trong trường hợp này, điều này không cấu thành Mô hình miền thiếu máu. Mô hình Miền Anemic là specifically about validating and transforming the objects. Vì vậy, một ví dụ về điều này sẽ là nếu một chức năng bên ngoài thực sự thay đổi trạng thái của nhân viên hoặc cập nhật chi tiết của họ.

điều đang xảy ra trong trường hợp này là bạn đang dùng tất cả nhân viên và lựa chọn một trong số họ dựa trên thông tin của họ. Nó là tốt để có một đối tượng riêng biệt kiểm tra những người khác và đưa ra quyết định liên quan đến những gì nó tìm thấy. KHÔNG được phép có một đối tượng được sử dụng để chuyển đổi một đối tượng từ trạng thái này sang trạng thái khác.

Một ví dụ về thiếu máu Domain Model trong trường hợp của bạn sẽ được để có một phương pháp bên ngoài

updateHours(Employee emp) // updates the working hours for the employee 

mà phải mất một đối tượng Employee và cập nhật giờ nó làm việc trong tuần, đảm bảo rằng lá cờ được nâng lên nếu giờ vượt quá giới hạn nhất định. Vấn đề với điều này là nếu bạn chỉ có các đối tượng Employee thì bạn không có kiến ​​thức về cách sửa đổi giờ của họ trong các ràng buộc chính xác.Trong trường hợp này, cách để xử lý nó sẽ là di chuyển phương thức updateHours vào lớp Employee. Đó là mấu chốt của mô hình chống mô hình miền không ổn định.

+0

Nhưng nếu nhân viên là một đối tượng liên tục cho cơ sở dữ liệu. Tại sao tôi nên đặt một phương pháp trong đó? Cùng một câu hỏi là hợp lệ cho DTO 's nơi bạn không đặt phương pháp bên trong. Bạn sẽ đặt phương thức updateHours ở đâu? – Pascal

+0

'updateHours' thuộc lớp Employee. Bạn nên vượt qua nó bất kỳ dữ liệu cần thiết để cập nhật giờ, ví dụ như nhiệm vụ đã được hoàn thành. Các đối tác cộng tác cũng tốt, nhưng tốt hơn là không có dịch vụ. – MauganRa

29

Tôi nghĩ rằng thiết kế của bạn là tốt ở đây. Như bạn đã biết, mô hình chống mô hình miền thiếu máu là một phản ứng ngược với xu hướng tránh bất kỳ hành vi nào được mã hóa trong các đối tượng miền. Nhưng ngược lại, nó không có nghĩa là tất cả các hành vi liên quan đến một đối tượng miền phải được đóng gói bởi đối tượng đó.

Theo quy tắc chung, hành vi được gắn liền với đối tượng miền và được xác định hoàn toàn dưới dạng một cá thể đối tượng tên miền có thể được bao gồm trong đối tượng miền. Nếu không, để giữ cho trách nhiệm rõ ràng, tốt nhất là nên đặt nó bên ngoài trong cộng tác viên/dịch vụ như bạn đã làm.

+5

chính xác. Điều này thực sự là một mô-đun bên ngoài (LeadQueueManager hoặc bất cứ điều gì) với rất nhiều logic nội bộ - điều này hoàn toàn không phải là một mô hình miền thiếu máu. Một nhân viên biết gì về lập kế hoạch xếp hàng cuộc gọi? Không có gì;) – TomTom

13

Đó là tất cả trong đầu của bạn - hãy xem xét dịch vụ xoay vòng là một phần của mô hình miền và sự cố đã tan biến.

Xoay cần giữ thông tin về nhiều nhân viên, vì vậy nó không thuộc về chì, cũng như đối với bất kỳ đối tượng nhân viên nào. Nó xứng đáng là một đối tượng miền trong chính nó.

Chỉ cần đổi tên "RotationService" thành một thứ như "Organization.UserSupportDepartment".

0

Nếu mô hình miền của bạn chỉ chứa vai trò và mọi thứ, không phải hoạt động dưới dạng hành vi, thì đó là thiếu máu. Tuy nhiên, tôi đang nói về hành vi liên quan đến mô hình không phải là đối tượng . Tôi nói về sự khác biệt giữa chúng trong câu trả lời khác ... https://stackoverflow.com/a/31780937/116442

Từ câu hỏi của bạn, bạn phá vỡ hai miền quy tắc xây dựng mô hình phân tích đầu tiên của tôi: -

  1. hành vi mô phỏng như hoạt động (ghi) là trung tâm của một mô hình miền. Thêm chúng trước.
  2. Hoạt động miền mô hình dưới dạng Lớp học, không phải là phương pháp.

Tôi sẽ thêm hoạt động "Yêu cầu" vào mô hình. Với nó, mô hình có hành vi và có thể kết hợp và hoạt động như một nhóm đối tượng không có bộ điều khiển hoặc tập lệnh bên ngoài.

EnquiryHandlerModel

Các vấn đề liên quan