2012-05-23 59 views
11

Tôi đang gặp một số khó khăn khi tìm ra cách tốt nhất để xử lý một tình huống khá phức tạp. Tôi đã nhìn thấy khá một vài câu hỏi tương tự, nhưng không ai giải thích kịch bản này cho sự hài lòng của tôi.DDD - Sửa đổi các đối tượng con trong tổng hợp

Một thứ tự (tổng hợp root) được tạo ra với nhiều OrderLines (đơn vị trẻ em). Theo quy tắc kinh doanh, mỗi OrderLine phải duy trì cùng một bản sắc cho cuộc đời của Lệnh. OrderLines có nhiều (20+) tài sản và có thể được biến đổi khá thường xuyên trước khi đặt hàng được coi là "bị khóa". Ngoài ra, có những bất biến phải được thực thi ở cấp cơ sở; ví dụ, mỗi thứ tự dòng có số lượng và tổng số lượng cho các đơn hàng không thể vượt quá X.

Tôi không chắc chắn làm thế nào để mô hình kịch bản này khi xem xét những thay đổi để OrderLines. Tôi có 4 lựa chọn mà tôi có thể quan niệm, nhưng không có sự lựa chọn nào thỏa đáng:

1) Khi đến lúc sửa đổi một Dòng đơn, hãy sử dụng tham chiếu do gốc cung cấp. Nhưng tôi mất khả năng kiểm tra logic bất biến trong thư mục gốc.

var orderLine = order.GetOrderLine(id); 
orderLine.Quantity = 6; 

2) Gọi phương thức theo thứ tự. Tôi có thể áp dụng tất cả các logic bất biến, nhưng sau đó tôi bị mắc kẹt với một sự gia tăng của các phương pháp để thay đổi các thuộc tính nhiều Hang:

order.UpdateOrderLineQuantity(id, 6); 
order.UpdateOrderLineDescription(id, description); 
order.UpdateOrderLineProduct(id, product); 
... 

3) Điều này có thể được dễ dàng hơn nếu tôi đối xử với Hang như một đối tượng giá trị gia tăng, nhưng nó phải duy trì cùng một danh tính cho mỗi yêu cầu kinh doanh.

4) Tôi có thể lấy tham chiếu đến OrderLines cho sửa đổi mà không ảnh hưởng đến bất biến, và đi qua theo thứ tự cho những người làm. Nhưng sau đó những gì nếu bất biến bị ảnh hưởng bởi hầu hết các thuộc tính OrderLine? Phản đối này là giả thiết, vì chỉ có một vài thuộc tính có thể ảnh hưởng đến bất biến, nhưng điều đó có thể thay đổi khi chúng ta phát hiện thêm logic kinh doanh.

Bất kỳ lời đề nghị được đánh giá cao ... đừng ngần ngại cho tôi biết nếu tôi là dày đặc.

Trả lời

5
  1. Không tối ưu vì nó cho phép vi phạm bất biến miền.

  2. sẽ dẫn đến việc lặp lại code và phương pháp nổ không cần thiết.

  3. Giống như 1). Sử dụng Value Object sẽ không giúp duy trì bất biến miền.

  4. Tùy chọn này là những gì tôi sẽ đi với. Tôi cũng sẽ không lo lắng về những thay đổi tiềm năng và giả định cho đến khi chúng hiện thực hóa. Thiết kế sẽ phát triển với sự hiểu biết của bạn về miền và luôn có thể là người tái cấu trúc sau này. Có thực sự không có giá trị trong việc cản trở thiết kế hiện tại của bạn vì lợi ích của một số thay đổi trong tương lai mà có thể không xảy ra.

+0

Cảm ơn bạn đã trả lời của bạn - Tôi nghĩ rằng nó có lẽ là lựa chọn tốt nhất trong những người tôi đã trình bày của tôi. Tôi đã thực sự hy vọng cho một ai đó để đề xuất một mô hình tốt hơn tôi có thể đã bỏ qua;) Tôi là một chút tinh ranh của việc sử dụng nó, bởi vì nó không sạch sẽ. Hoặc có lẽ một cách tốt hơn để đặt nó ... không nhất quán, như @eulerfx chỉ ra. Nhưng tôi đoán nó sẽ làm cho bây giờ ... – Cork

+2

Tôi biết tôi chấp nhận điều này như là một câu trả lời đã ... nhưng tôi nghĩ về một cách tiếp cận khác nhau. Bạn có thể có phương thức Lưu (IOrderLine) trên Đơn hàng không? Sau đó, tôi có thể chuyển một ref tới Order, tránh một loạt các phương thức chi tiết, và vẫn cho phép Order thực thi các bất biến. – Cork

5

Một nhược điểm của 4 như trái ngược với 2 là thiếu nhất quán. Trong một số trường hợp, có thể có ích để duy trì mức độ nhất quán liên quan đến việc cập nhật các mục hàng đơn đặt hàng. Có thể không rõ ngay lý do tại sao một số cập nhật nhất định được thực hiện thông qua thứ tự trong khi các cập nhật khác thông qua mục hàng đơn đặt hàng. Hơn nữa, nếu các dòng lệnh có hơn 20 thuộc tính, có lẽ đó là dấu hiệu cho thấy có khả năng nhóm trong số các thuộc tính đó dẫn đến ít thuộc tính hơn trên dòng lệnh. Nhìn chung, cách tiếp cận 2 hoặc 4 là tốt miễn là bạn đảm bảo duy trì hoạt động nguyên tử, nhất quán và tương ứng với ngôn ngữ phổ biến.

+1

Cảm ơn câu trả lời! Tôi đồng ý với sự thiếu nhất quán, nhưng tôi nghĩ đó là lựa chọn tốt nhất của tôi. Chúng tôi thực sự bắt đầu với rất nhiều thuộc tính Dòng đặt hàng trong Đơn đặt hàng, nhưng khi chúng tôi tiếp tục phân tích miền, chúng tôi đã tìm thấy Dòng đặt hàng là một điểm phù hợp hơn. Có thể, tuy nhiên, chúng tôi đã mang đi một chút ... – Cork

5

Có một cách thứ năm để làm điều này. Bạn có thể kích hoạt domain event (ví dụ: QuantityUpdatedEvent(order, product, amount)). Hãy để tổng hợp xử lý nó nội bộ bằng cách xem danh sách các dòng đơn hàng, chọn một sản phẩm phù hợp và cập nhật số lượng của nó (hoặc ủy quyền hoạt động cho OrderLine thậm chí còn tốt hơn)

+1

Khi một thực thể có trẻ em có thể được sửa đổi theo nhiều cách khác nhau, tôi đồng ý rằng các sự kiện miền thường là đúng cách để đi. Jimmy Bogard cũng đã viết một số tác phẩm đẹp [ở đây] (http://lostechies.com/jimmybogard/2010/04/08/strengthening-your-domain-domain-events/) và [ở đây] (http: // lostechies. com/jimmybogard/2014/05/13/a-better-domain-events-pattern /). –

4

Sự kiện miền là giải pháp mạnh mẽ nhất.

Tuy nhiên nếu đó là quá mức cần thiết, bạn cũng có thể thực hiện biến thể số 2 bằng mẫu Đối tượng tham số - có một hàm ModfiyOrderItem duy nhất trên gốc thực thể. Gửi một mục mới, được cập nhật, và sau đó nội bộ Lệnh xác nhận đối tượng mới này và thực hiện các cập nhật.

Vì vậy, công việc điển hình của bạn sẽ biến thành một cái gì đó giống như

var orderItemToModify = order.GetOrderItem(id); 
orderItemToModify.Quantity = newQuant; 

var result = order.ModifyOrderItem(orderItemToModfiy); 
if(result == SUCCESS) 
{ 
    //good 
} 
else 
{ 
    var reason = result.Message; etc 
} 

Các thiếu sót chính ở đây là nó cho phép một lập trình viên để sửa đổi các mục, nhưng không cam kết nó và không nhận ra rằng. Tuy nhiên nó có thể dễ dàng mở rộng và kiểm tra được.

1

Dưới đây là một lựa chọn khác nếu dự án của bạn là nhỏ và bạn muốn tránh sự phức tạp của các sự kiện tên miền. Tạo một dịch vụ xử lý các quy tắc cho Đơn đặt hàng và chuyển nó vào phương thức trên Đơn hàng:

public void UpdateQuantity(int quantity, IOrderValidator orderValidator) 
{ 
    if(orderValidator.CanUpdateQuantity(this, quantity)) 
     Quantity = quantity; 
} 

CanUpdateQuantity lấy dòng lệnh hiện tại và số lượng mới làm đối số. Nó sẽ tra cứu Lệnh và xác định xem bản cập nhật có gây ra vi phạm trong tổng số lượng Đơn đặt hàng hay không. (Bạn sẽ phải xác định cách bạn muốn xử lý vi phạm bản cập nhật.)

Đây có thể là một giải pháp tốt nếu dự án của bạn là nhỏ và bạn không cần sự phức tạp của các sự kiện tên miền.

Một nhược điểm của kỹ thuật này là bạn đang đi qua một dịch vụ xác nhận cho thứ tự vào Hang, nơi mà nó thực sự không thuộc về. Ngược lại, việc tăng sự kiện miền sẽ di chuyển logic Đơn hàng ra khỏi OrderLine. Dòng OrderLine sau đó có thể nói với thế giới, "Này, tôi đang thay đổi số lượng của mình." và logic xác nhận đơn đặt hàng có thể diễn ra trong trình xử lý.

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