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


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

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

  • 相关阅读:
    Swift3 重写一个带占位符的textView
    Swift3 使用系统UIAlertView方法做吐司效果
    Swift3 页面顶部实现拉伸效果代码
    Swift3 倒计时按钮扩展
    iOS 获取当前对象所在的VC
    SpringBoot在IDEA下使用JPA
    hibernate 异常a different object with the same identifier value was already associated with the session
    SpringCloud IDEA 教学 番外篇 后台运行Eureka服务注册中心
    SpringCloud IDEA 教学 (五) 断路器控制台(HystrixDashboard)
    SpringCloud IDEA 教学 (四) 断路器(Hystrix)
  • 原文地址:https://www.cnblogs.com/YangMark/p/3686107.html
Copyright © 2011-2022 走看看