聚合只是將一些實體(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. 关于小程序bindregionchange事件在IOS崩溃的问题

    先说下原因,我在bindregionchange事件触发函数中设置了经纬度,而latitude和longitude是绑定在map组件上的,滑动地图的过程中重新设置了地图中心点的经纬度,会导致地图本身的 ...

  2. ORB SLAM2 学习笔记

    cd ~/Documents/demos/ORB_SLAM2 ./Examples/RGB-D/rgbd_tum Vocabulary/ORBvoc.txt Examples/RGB-D/TUM1.y ...

  3. JavaScript随机数组(数组、随机、取整、取值的过程)

      <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&q ...

  4. kali linux之本地提权

    已实现本地低权限帐号登录,希望获取更高权限,实现对目标进一步控制 系统帐号之间权限隔离(操作系统安全的基础,用户空间,内核空间) 系统帐号(用户帐号登录时获取权限令牌,服务帐号无需用户登录已在后台启动 ...

  5. 洛谷P4494 [HAOI2018]反色游戏(tarjan)

    题面 传送门 题解 我们先来考虑一个联通块,这些关系显然可以写成一个异或方程组的形式,形如\(\oplus_{e\in edge_u}x_e=col_u\) 如果这个联通块的黑色点个数为奇数,那么显然 ...

  6. 控制台解析命行C#

    //---------------------------------------------------------------------   /// <summary> /// Co ...

  7. Windows远程连接CentOS图形化界面

    1.检查是否安装VNC rpm -q tigervnc tigervnc-server 2.安装安装X-Window # yum check-update # yum groupinstall &qu ...

  8. python学习之路---day12

    生成器和生成器表达式一:生成器 生成器实质上就是迭代器. 三种方式获取生成器: 01:通过生成器函数 02:通过各种推导式实现生成器 03:通过数据的转换也可以获取生成器 eg:普通函数 def fu ...

  9. JAVA数据结构--冒泡排序

    冒泡排序(英语:Bubble Sort,台湾另外一种译名为:泡沫排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行 ...

  10. Linux之旅(二)

    上一章讲到,mysql 安装遇到问题 ...莫名其妙好了,此处已回想不起为什么好了,只得跳过. 六.安装php7 参考教程[ http://www.thinkphp.cn/topic/48196.ht ...