2017-03-10 49 views
0

考慮以下情形:DDD - 通過聚合獲取實體,在aggegrate方法後面調用方法或隱藏實體方法?

class Order: 

    def __init__(self): 
     self.lines = [] 

    def order(self, product_id, amount, price, discount=None): 
     item = OrderItem(product_id, amount, price) 
     self.lines.append(item) 

class OrderItem: 

    def __init__(self, product_id, amount, price, discount=None): 
     self.product_id = product_id 
     self.amount = amount 
     self.price = price 
     self.discount = discount or decimal.Decimal(0) 

    def discount(self, amount): 
     self.discount = discount 

在我們想要的折扣添加到特定行項目的情況下,Order總量已創建後,我需要從總量得到OrderItem實體,或暴露聚合方法?

E.g.

class Order: 

    ... 

    def discount_item(self, index, amount): 
     self.lines[index].discount(amount) 

如果我可以調用OrderItem.discount()直接 - 我怎麼跟蹤出版作爲一個結果域的事件?

回答

1

聚合的每一個改變都應該通過聚合根的公共方法來完成。這樣可以確保聚合始終處於一致狀態。否則,您可以通過修改聚合的內部實體輕鬆地破壞聚合的一致性。整個聚合概念是關於保持聚合內的所有實體和值對象處於有效狀態。所以,你的情況,你可以添加類似這樣的Order聚合根的方法:

def applyDiscountForItem(self, itemPosition, amount): 
    // apply the discount on item identified by itemPosition 

如果按照這個規律,總的一致性得到了保證。聚合根是對聚合進行任何更改的單一入口點,因此將所有業務邏輯和驗證添加到根是相當容易的。但是,當您的聚合變大時,根中可能會有很多「代理」方法。如果是這種情況,那麼你的聚合可能變得太大,需要分解成多個聚合。保持總量相對較小通常是一個好主意。通常,最好的聚合只包含一個實體(聚合根本身)和多個值對象。