zoukankan      html  css  js  c++  java
  • [實現DDD] 第10章 聚合(1)設計原則

    聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎??

    有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚合過於貧瘠而喪失了保護真正不變條件(業務規則)的目的。

    "實現領域驅動設計"一書的作者,提供了幾個聚合設計原則......

    • 在一致性邊界之內建模真正的不變條件 

      這裡的不變條件指的是一個業務規則,該規則應該總是保持一致的。存在多種類型的一致性,事務一致性(高一致性),最終一致性等。
      在討論不變條件時,就是在討論事務一致性。

      聚合邊界內的對象,可能都實現了某種不變條件,在此邊界內的所有內容組成了一套不變的業務規則。
      任何操作都不能違背這些規則,邊界之外的任何東西與該聚合都是不相關的。因此,聚合表達了與事務一致性相同的意思。
      設計聚合時,我們需要慎重考慮一致性,這意味著每次客戶請求應該只在一個聚合實例上執行一個命令方法

      小結
      聚合是為了封裝真的不變性,而不是單純的將對象組合起來
    • 設計小聚合

      對於大聚合,即便可以成功地保持事務一致性,但它可能限制了系統性能和可伸縮性。 系統可能隨著時間可能會有越來越多的需求與用戶,開發與維護的成本我們不應該忽視。

      怎樣的聚合才算是"小"聚合呢??

      好的做法是使用根實體(Root Entity)來表示聚合,其中只包含最小數量的屬性或值類型屬性。哪些屬性是所需的呢??簡單的答案是:那些必須與其他屬性保持一致的屬性

      比如,Product聚合內的name與description屬性,是需要保持一致的,把它們放在兩個不同的聚合顯然是不恰當的。

      優先選擇值對象

      使用值對象有很多好處

      (1) 根據持久化機制,值對象可以隨著根實體而序列化,需實體則需要單獨存儲區域予以跟踪。

      (2) 實體會帶來一些不必要的操作,比如,在資料庫中我們需對多張表進行聯合查詢 ;而使用值對象只需對單張表查詢,也更安全方便。

      (3) 由於值對象是不變的,測試起來也相對簡單。

      如果你認為有些被包含部分應建模成實體,那應該先思考一下,這個部份是否會隨時間而改變,或該部分是否能被全部替換。如果可以全部替換,請建模成值對象,而非實體。

      小結
      小聚合的好處不僅有性能和可伸縮性上的好處,它還有助於事務的成功執行,即它可以建少事務提交衝突。如此一來,系統可用性也得到了增強。
      聚合內高一致性,聚合之間最終一致性。
    • 通過唯一標識引用其他聚合

      Evans寫到,一個聚合可以引用另一個聚合的根聚合,但此時被引用的聚合不應該放在引用聚合的一致性邊界內。錯誤的引用聚合只會讓聚合邊界模糊而已
      在不持有對象引用情況下,我們是不能修改其他聚合的,因此我們可以避免在同一事務中修改多個聚合。但這種方式缺點在於限制性太強,那我們該怎麼辦呢??

      通過標識引用使用多個聚合協同工作
      這種方式好處創建的聚合也會變的更小,此時所關聯的聚合不會即時加載,模型的性能也隨之變好。

      建模對象導航性

      通過標識引用並不意外我們完全失了對象導航性,這種技術稱為失聯領域模型(Disconnected Doamin Model),而事實上這僅是一種延遲加載的形式。
      另外一種推薦的作法:在調用聚合行為方法之前,使用資料庫或領域服務來獲取所需的對象。

      小結
      唯一標識引用對象在缺點在於在用戶界面層,要組裝多個聚合並予以顯示將變的因難,有損模型使用的方便性;但其他的好處是,小聚合可增強模型的性能和可伸縮性,另外有助於創建分布式系統
      最後強調,我們應避免一個事務操作多個聚合。
    • 在邊界之外使用最終一致性

      如果單次用戶請求需要修改多個聚合實列又需要證模型的一致性時,以下是Evans對聚合模式的定義 ,

           
      任何跨聚合的業務規則都不能總是保持最新狀態。通過事件處理,批處理或者其他更新機制,我們可以在一定時間之肉處理好他方依賴。[Evans, p.128]

      在一個大規模,高吞吐的企業系統中,要使所有的聚合實例完全一致是不可能的。認識這點,你便知道在較小規模的系統中使用最終一致性是必要的。

      在DDD中,有一種很實用的方法可以支持最終一致性,即一個聚合命令方法發布領域事件及時地發送給異步的訂閱方;在接收到事件之後,每個訂閱方都會獲取自己的聚合實例,然後在該聚合上完成相庄操作。每個訂閱方都在單獨的事務中進行操作,也即滿足了"在一個事務中只修改一個聚合實例"的原則。


      小結
      在某些場景下,我們很難決定應該採取事務或是最終一致性,書中提出了一個簡單且實用的指導原則。對於一個用例,問問是否應由執行該用例的用戶來保證數據的一致性?如果是請使用事務一致性;若要其他用戶或者系統來保證數據一致性,請使用最終一致性。

    以上的原則都是可以打破的,但在此之前必須要有充足的理由,那會有什麼樣的理由呢?下一篇再由書中摘錄吧。。。。。

  • 相关阅读:
    自定义异常
    异常的处理方式之二:声明异常(throws子句)
    异常的处理方式之一:捕获异常
    CheckedException已检查异常
    Range Sum Query
    cmd命令结束占用tomcat的进程
    原生js实现瀑布流
    js实现选项卡切换
    (转载)用ul做横向导航
    帝国CMS视频
  • 原文地址:https://www.cnblogs.com/YangMark/p/3686107.html
Copyright © 2011-2022 走看看