2011-01-29 38 views
5

Khi cố gắng hiểu Thiết kế Điều khiển Tên miền, tôi tiếp tục quay lại câu hỏi mà tôi dường như không thể trả lời dứt khoát.Khi nào thì logic thuộc về đối tượng/đối tượng kinh doanh và khi nào thuộc về một dịch vụ?

Làm cách nào để bạn xác định logic nào thuộc về thực thể Tên miền và logic nào thuộc về Dịch vụ miền?

Ví dụ: Chúng tôi có một lớp Đặt hàng cho một cửa hàng trực tuyến. Lớp này là một thực thể và một gốc tổng hợp (nó chứa OrderItems).

Public Class Order:IOrder 
{ 
    Private List<IOrderItem> OrderItems 

    Public Order(List<IOrderItem>) 
    { 
     OrderItems = List<IOrderItem> 
    } 

    Public Decimal CalculateTotalItemWeight() 
    //This logic seems to belong in the entity. 
    { 
     Decimal TotalWeight = 0 
     foreach(IOrderItem OrderItem in OrderItems) 
     { 
      TotalWeight += OrderItem.Weight 
     } 
     return TotalWeight 

    } 
} 

Tôi nghĩ hầu hết mọi người đều đồng ý rằng CalculateTotalItemWeight thuộc về pháp nhân. Tuy nhiên, tại một số thời điểm chúng tôi phải giao hàng cho khách hàng. Để thực hiện điều này, chúng tôi cần thực hiện hai điều:

1) Xác định tỷ lệ bưu chính cần thiết để giao đơn đặt hàng này.

2) In nhãn vận chuyển sau khi xác định cước phí bưu chính.

Cả hai hành động này sẽ yêu cầu các phụ thuộc nằm ngoài thực thể Đơn đặt hàng, chẳng hạn như dịch vụ web bên ngoài để truy xuất tỷ lệ bưu chính. Chúng ta nên hoàn thành hai điều này như thế nào? Tôi thấy một vài tùy chọn:

1) Mã logic trực tiếp trong thực thể tên miền, như CalculateTotalItemWeight. Sau đó chúng tôi gọi:

Order.GetPostageRate 
Order.PrintLabel 

2) Đặt logic trong dịch vụ chấp nhận IOrder. Sau đó chúng tôi gọi:

PostageService.GetPostageRate(Order) 
PrintService.PrintLabel(Order) 

3) Tạo một lớp cho mỗi hành động mà hoạt động trên một thứ tự, và vượt qua một thể hiện của lớp đó để Huân qua Constructor Injection (đây là một biến thể của phương án 1 nhưng cho phép tái sử dụng các lớp RateRetriever và LabelPrinter):

Public Class Order:IOrder 
{ 
    Private List<IOrderItem> OrderItems 
    Private RateRetriever _Retriever 
    Private LabelPrinter _Printer 

    Public Order(List<IOrderItem>, RateRetriever Retriever, LabelPrinter Printer) 
    { 
     OrderItems = List<IOrderItem> 
     _Retriever = Retriever 
     _Printer = Printer 
    } 

    Public Decimal GetPostageRate 
    { 
     _Retriever.GetPostageRate(this) 
    } 

    Public void PrintLabel 
    { 
     _Printer.PrintLabel(this) 
    } 
} 

Bạn chọn phương pháp nào trong logic này nếu có? Lý do đằng sau sự lựa chọn của bạn là gì? Quan trọng nhất, có một bộ hướng dẫn nào dẫn bạn đến lựa chọn của bạn không?

+1

Lệnh khó có thể thuyết bất khả tri về các mục OrderDetail của mình ... Đó có phải là những gì bạn có nghĩa là? –

Trả lời

1

Tôi có xu hướng có một dịch vụ bên ngoài xác định tốc độ giao hàng. Đối với tôi đó là logic ứng dụng chứ không phải logic theo thứ tự cụ thể. Ví dụ: bạn có thể quyết định một khoảng thời gian cung cấp giao hàng miễn phí cho các đơn hàng có kích thước nhất định hoặc cho một nhóm khách hàng trung thành cụ thể. Đối với tôi, logic đó sẽ có xu hướng thay đổi độc lập với cách mà trật tự được xây dựng.

Rất có thể tôi sẽ có mã chịu trách nhiệm đặt hàng (một số loại dịch vụ xử lý đơn đặt hàng, trong một lớp ứng dụng hoặc trong bộ xử lý lệnh) giao dịch vụ để nhận mức phí giao hàng và sau đó vượt qua tỷ lệ đó vào thứ tự, vì vậy tôi đoán tùy chọn 2.

Để in nhãn vận chuyển, tôi muốn hướng tới việc miền nâng cao sự kiện dọc theo các dòng http://www.udidahan.com/2009/06/14/domain-events-salvation/. Một người xử lý riêng biệt sau đó sẽ xử lý việc in nhãn. Một lần nữa, logic cho điều này là cách bạn in nhãn có thể thay đổi độc lập với cách bạn xây dựng một đơn đặt hàng, do đó, nó có ý nghĩa để giữ riêng biệt. Sử dụng một sự kiện tên miền có vẻ là cách sạch nhất để đảm bảo rằng nhãn được in vào đúng thời điểm mà không yêu cầu Thứ tự (hoặc thực sự là bộ xử lý đơn đặt hàng) phải nhận thức được logic in.

+0

Bản năng của tôi là đi theo dòng suy nghĩ của bạn, nhưng nếu chúng ta theo dòng suy nghĩ này, chúng ta sẽ có một tên miền thiếu máu với tất cả logic "thực" của chúng ta bên ngoài thực thể của chúng ta? –

+0

Tôi lo lắng về điều đó là tốt, nhưng nó đã không thực sự panned ra theo cách đó. Chắc chắn một số logic đã kết thúc ở cấp độ ứng dụng, nhưng tôi thực sự nghĩ rằng đó là đúng anyway. – David

+0

Chỉ cần đọc lại câu hỏi ban đầu của bạn. Nếu bạn đang gọi một dịch vụ web bên ngoài cho tỷ giá giao hàng thì logic đó nằm ngoài miền bất kể.Tôi muốn nói đó là quyết định cấp ứng dụng để sử dụng dịch vụ web bên ngoài. Nếu có quy tắc bạn áp dụng cho thông tin bạn đã nhận lại - ví dụ: bạn áp dụng chiết khấu cho tỷ lệ cho khách hàng trung thành hoặc thứ gì đó - logic đó vẫn có thể được áp dụng trong miền, vì vậy bạn sẽ chuyển kết quả của dịch vụ web trở lại miền. – David

0

Quan điểm của tôi: Tên miền là những gì chứa logic của ứng dụng của bạn mà không có cơ sở hạ tầng. Logic là khi một đơn hàng được xác nhận một nhãn được in và tỷ lệ vận chuyển được xác định. Điều đó phải nằm trong miền.

Cơ sở hạ tầng sau đó hoàn thành những gì miền muốn thực hiện. Miền có thể cho phép cơ sở hạ tầng biết thông qua tin nhắn hoặc sự kiện.

Bằng cách đó, không có cơ sở hạ tầng nào bị rò rỉ vào miền, bạn chỉ cần có cách để chuyển thư ra khỏi miền.

+0

Vì vậy, bạn sẽ sử dụng một trong những cách tiếp cận tôi đã đề cập, hoặc một cái gì đó khác nhau? –

1

Tôi sẽ sử dụng (2).

Nó không làm tăng thêm sự phức tạp cho Mục đặt hàng của bạn.

Với tôi, có vẻ như việc sử dụng tự nhiên dịch vụ trợ giúp.

Cập nhật: để đáp ứng với bình luận: Các trạng thái trang wiki:

thiếu máu Domain Model: Với mô hình này, logic thường thực hiện trong lớp học riêng biệt mà chuyển trạng thái của miền đối tượng

+0

Việc sử dụng số 2 có đẩy chúng tôi hướng tới một mô hình miền thiếu máu theo ý kiến ​​của bạn không? –

+0

Tôi không nghĩ vậy, theo như tôi biết, có thể có một đối tượng riêng biệt lấy một loạt các đối tượng khác và đưa ra quyết định dựa trên trạng thái của họ miễn là các đối tượng được đề cập không bị thay đổi hoặc biến đổi. –

+0

Nếu chúng tôi thay đổi trạng thái của đơn đặt hàng bằng cách đặt dịch vụ đặt thuộc tính PostageRate trên đơn đặt hàng ... Điều đó có được tính là chuyển đổi đơn đặt hàng không? Có điều gì đó không đáng kể có nghĩa là chúng ta sẽ thay đổi quyết định ban đầu của mình? Dường như DDD đầy những "Catch 22" này đến nỗi nó trở nên rất khó thực hiện. –

1

Nếu bạn đang truy cập các dịch vụ web bên ngoài để nhận được Tỷ lệ bưu chính, tốt hơn là tạo giao diện trong lớp Ứng dụng, vì evan tự đề xuất rằng nếu bạn muốn nói chuyện với các dịch vụ web bên ngoài, bạn nên xây dựng giao diện trong lớp Ứng dụng, bạn sẽ thực hiện dịch vụ được đưa vào đối tượng miền của bạn. Để in nhãn vận chuyển, vì nhãn chỉ được in khi tỷ lệ bưu chính được xác định, do đó, là một loại sự kiện như PostageRateConfirmed miền của bạn có thể tăng sự kiện này.

http://danhaywood.com/2010/04/30/accessing-domain-services-from-entities/

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