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

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

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

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

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

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

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

  • 設計小聚合

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

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

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

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

    優先選擇值對象

    使用值對象有很多好處

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

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

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

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

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

  • 通過唯一標識引用其他聚合

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

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

    建模對象導航性

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

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

  • 在邊界之外使用最終一致性

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

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

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

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


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

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

[實現DDD] 第10章 聚合(1)設計原則的更多相关文章

  1. [實現DDD] 第11章 工廠

    創建過程中須考慮一些重要細節, 否則所創建的聚合將處於不正確的狀態, 使用適當的工廠方法可以確保這一點, 而客戶端只需輸入基本的參數(通常是值對象), 另外, 工廠能更好地表達出通用語言, 使團隊成員 ...

  2. 应用程序框架实战十八:DDD分层架构之聚合

    前面已经介绍了DDD分层架构的实体和值对象,本文将介绍聚合以及与其高度相关的并发主题. 我在之前已经说过,初学者第一步需要将业务逻辑尽量放到实体或值对象中,给实体“充血”,这样可以让业务逻辑高度内聚, ...

  3. DDD分层架构之聚合

    DDD分层架构之聚合 前面已经介绍了DDD分层架构的实体和值对象,本文将介绍聚合以及与其高度相关的并发主题. 我在之前已经说过,初学者第一步需要将业务逻辑尽量放到实体或值对象中,给实体“充血”,这样可 ...

  4. [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)

    這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...

  5. Neo4j中實現自定義中文全文索引

    資料庫檢索效率時,一般首要優化途徑是從索引入手,然後根據需求再考慮更復雜的負載均衡.讀寫分離和分散式水平/垂直分庫/表等手段:索引通過資訊冗餘來提高檢索效率,其以空間換時間並會降低資料寫入的效率,因此 ...

  6. 《构建之法》之第8、9、10章读后感 ,以及sprint总结

    第8章: 主要介绍了软件需求的类型.利益相关者,获取用户需求分析的常用方法与步骤.竞争性需求分析的框架NABCD,四象限方法以及项目计划和估计的技术. 1.软件需求:人们为了解决现实社会和生活中的各种 ...

  7. 敏捷软件开发:原则、模式与实践——第10章 LSP:Liskov替换原则

    第10章 LSP:Liskov替换原则    Liskov替换原则:子类型(subtype)必须能够替换掉它们的基类型(base type). 10.1 违反LSP的情形 10.1.1 简单例子 对L ...

  8. 孙鑫视频学习:对第10章设置线宽时为什么不调用UpDateData(TRUE)的理解

    在第10章10.2.1小节中,首先分别对视图类和对话框类添加了一个名为m_nLineWidth的int型变量,再将用户在CSetting dlg对话框的edit控件中输入的线宽值记录在dlg.m_nL ...

  9. 第10章 系统级I/O

    第10章 系统级I/O 10.1 Unix I/O 一个Unix文件就是一个m个字节的序列:B0,B1,…,BK,…,Bm-1 Unix I/O:一种将设备优雅地映射为文件的方式,允许Unix内核引出 ...

随机推荐

  1. 小议C#接口的隐式与显示实现

    小弟不才,各位大牛嘴下留情... 一.对于继承类里头有相同方法时候,用接口方式去调用,会优先查走显式接口方法 例如 public interface IA { void Test(); } publi ...

  2. 用firebug 进行表单自定义提交

    在一些限制网页功能的场合,例如,防止复制内容,防止重复提交,限制操作的时间段/用户等,网页上一些按钮是灰化的(禁用的),这通常是通过设置元素的 disable属性来实现的.但在后台并没有做相应的功能限 ...

  3. Dapper ORM

    参考地址:https://www.cnblogs.com/lunawzh/p/6607116.html 1.连接语句 var conn = new SqlConnection(Configuratio ...

  4. 转载:ResultMap和ResultType在使用中的区别

    在使用mybatis进行数据库连接操作时对于SQL语句返回结果的处理通常有两种方式,一种就是resultType另一种就是resultMap,下面说下我对这两者的认识和理解 resultType:当使 ...

  5. 如何从Spring官网下载Spring的jar包

    Spring官网:https://spring.io/ 进入官网点击PRODECTS 然后点击Spring Framework 进入下面的页面点击小猫图标: 之后再下面的页面持续向下滚动,找到下图我标 ...

  6. HTML5+CSS实现三列布局自适应

    利用CSS的float属性可以将元素并排,做出三列并排的布局. 如这样的效果 实现的原理:只要将3个元素设置float属性,属性值为left,同时指定不同比例的宽度,及高度. 下面是实现代码 < ...

  7. SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解

    数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  8. JSON的key值为数字时如何使用

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript(Standard ECMA-262 ...

  9. c++继承构造析构调用原则以及特殊变量处理

    一.继承中的构造析构调用原则 1.子类对象在创建时会首先调用父类的构造函数 2.父类构造函数执行结束后,执行子类构造函数 3.当父类构造函数有参数时,需要在子类的初始化列表中显示调用: 4.析构函数调 ...

  10. mtd-util

    1.1.4.1. mtd-util简介 mtd-util,即mtd的utilities,是mtd相关的很多工具的总称,包括常用的mtdinfo,flash_erase, flash_eraseall, ...