2014-02-20 49 views
0

考慮下面的例子合計:DDD - 子實體封裝

public class Order 
{ 
    private readonly IList<OrderLine> _orderLines; 
    public IEnumerable<OrderLine> Lines { get { return _orderLines; } } 

    public Order() 
    { 
     _orderLines = new List<OrderLine>(); 
    } 

    public void AddOrderLine(string sku, int qty) 
    { 
     _orderLines.Add(new OrderLine(sku, qty)); 
    } 

    public void CancelOrderLine(string sku) 
    { 
     OrderLine line = _orderLines.FirstOrDefault(l => l.Sku == sku); 
     if (line == null) 
      return; 

     line.Cancel(); 
    } 
} 

public class OrderLine 
{ 
    public string Sku { get; private set; } 
    public int Qty { get; private set; } 

    public OrderLine(string sku, int qty) 
    { 
     Sku = sku; 
     Qty = qty; 
    } 

    public void Cancel() 
    { 
     // do some cancellation stuff 
    } 
} 

什麼是防止有人從各地聚集根底部並直接修改訂單行?例如:

foreach(OrderLine line in currentOrder.Lines) 
{ 
    line.Cancel(); 
} 

有無論如何有一個真正封裝的聚合根?唯一的解決方案是創建一組平行訂單行值對象,而不是暴露?

感謝您的任何見解。

回答

1

難道你不能從取消方法內部開始,因此它只能在訂單組件中可見嗎? 當然,這個程序集中的其他類也可以訪問取消方法。

也許另一種方法是將OrderLines的集合公開爲IOrderLine接口的集合並以這種方式隱藏Cancel方法。

+0

是的,我認爲使內部的方法減少曝光,並可能會做到這一點。也被視爲接口路由,但有人可以將結果轉換回OrderLine對象並直接調用cancel方法。我知道這與偏執狂有關,但我想我想知道是否有一種「正確」的方式來做到這一點,提供真正的封裝,或者我將不得不在這裏妥協?如果我沒有得到更好的答案,我會接受你的。感謝您的建議。 –

0

你爲什麼暴露行?公開一些快照(DTO),其中包含有關OrderLines的信息,但您不需要OrderLines。這是已知的解決方案。而用CQRS你可能根本不需要暴露它。

+0

從我讀過的書中可以看出DTO在這個領域本身沒有地位。爲我的所有子實體創建快照對象也非常繁瑣。在附註中,我發現返回這樣的列表:public IEnumerable Lines {get {return _orderLines.AsEnumerable(); }}解決了這個問題。修改返回的行不會影響聚合中存儲的行。似乎是一個副本,而不是。 –