聚合(根)、實體、值對象精煉思考總結


1.      聚合根、實體、值對象的區別?

從標識的角度:

聚合根具有全局的唯一標識,而實體只有在聚合內部有唯一的本地標識,值對象沒有唯一標識,不存在這個值對象或那個值對象的說法;

從是否只讀的角度:

聚合根除了唯一標識外,其他所有狀態信息都理論上可變;實體是可變的;值對象是只讀的;

從生命周期的角度:

聚合根有獨立的生命周期,實體的生命周期從屬於其所屬的聚合,實體完全由其所屬的聚合根負責管理維護;值對象無生命周期可言,因為只是一個值;

2.      聚合根、實體、值對象對象之間如何建立關聯?

聚合根到聚合根:通過ID關聯;

聚合根到其內部的實體,直接對象引用;

聚合根到值對象,直接對象引用;

實體對其他對象的引用規則:1)能引用其所屬聚合內的聚合根、實體、值對象;2)能引用外部聚合根,但推薦以ID的方式關聯,另外也可以關聯某個外部聚合內的實體,但必須是ID關聯,否則就出現同一個實體的引用被兩個聚合根持有,這是不允許的,一個實體的引用只能被其所屬的聚合根持有;

值對象對其他對象的引用規則:只需確保值對象是只讀的即可,推薦值對象的所有屬性都盡量是值對象;

3.      如何識別聚合與聚合根?

明確含義:一個Bounded Context(界定的上下文)可能包含多個聚合,每個聚合都有一個根實體,叫做聚合根;

識別順序:先找出哪些實體可能是聚合根,再逐個分析每個聚合根的邊界,即該聚合根應該聚合哪些實體或值對象;最后再划分Bounded Context;

聚合邊界確定法則:根據不變性約束規則(Invariant)。不變性規則有兩類:1)聚合邊界內必須具有哪些信息,如果沒有這些信息就不能稱為一個有效的聚合;2)聚合內的某些對象的狀態必須滿足某個業務規則;

 

例子分析1:訂單模型

Order(一 個訂單)必須有對應的客戶信息,否則就不能稱為一個有效的Order;同理,Order對OrderLineItem有不變性約束,Order也必須至少有一個OrderLineItem(一條訂單明細),否 則就不能稱為一個有效的Order;另外,Order中的任何OrderLineItem的數量都不能為0,否則認為該OrderLineItem是無效 的,同時可以推理出Order也可能是無效的。因為如果允許一個OrderLineItem的數量為0的話,就意味着可能會出現所有 OrderLineItem的數量都為0,這就導致整個Order的總價為0,這是沒有任何意義的,是不允許的,從而導致Order無效;所以,必須要求 Order中所有的OrderLineItem的數量都不能為0;那么現在可以確定的是Order必須包含一些OrderLineItem,那么應該是通 過引用的方式還是ID關聯的方式來表達這種包含關系呢?這就需要引出另外一個問題,那就是先要分析出是OrderLineItem是否是一個獨立的聚合 根。回答了這個問題,那么根據上面的規則就知道應該用對象引用還是用ID關聯了。那么OrderLineItem是否是一個獨立的聚合根呢?因為聚合根意 味着是某個聚合的根,而聚合有代表着某個上下文邊界,而一個上下文邊界又代表着某個獨立的業務場景,這個業務場景操作的唯一對象總是該上下文邊界內的聚合 根。想到這里,我們就可以想想,有沒有什么場景是會繞開訂單直接對某個訂單明細進行操作的。也就是在這種情況下,我們 是以OrderLineItem為主體,完全是在面向OrderLineItem在做業務操作。有這種業務場景嗎?沒有,我們對 OrderLineItem的所有的操作都是以Order為出發點,我們總是會面向整個Order在做業務操作,比如向Order中增加明細,修改 Order的某個明細對應的商品的購買數量,從Order中移除某個明細,等等類似操作,我們從來不會從OrderlineItem為出發點去執行一些業 務操作;另外,從生命周期的角度去理解,那么OrderLineItem離開Order沒有任何存在的意義,也就是說OrderLineItem的生命周 期是從屬於Order的。所以,我們可以很確信的回答,OrderLineItem是一個實體。

 

例子分析2:帖子與回復的模型,做個對比,以便更好地理解。

變性分析:帖子和回復之間有不變性規則嗎?似乎我們只知道一點是肯定的,那就是帖子和回復之間的關系,1N的關系;除了這個之外,我們看不到任何其他的 不變性規則。那么這個1N的對象關系是一種不變性規則嗎?不是!首先,一個帖子可以沒有任何回復,帖子也不對它的回復有任何規則約束,它甚至都不知道自 己有多少個回復;再次,發表了一個回復和帖子也沒有任何關系;其次,發表回復對帖子沒有任何改變;從業務場景的角度去分析,我們有發表帖子的場景,有發表 回復的場景。當在發表回復的時候,是以回復為主體的,帖子只是這個回復里所包含的必要信息,用於說明這個回復是對哪個帖子的回復。這些都說明帖子和回復之 間找不出任何不變性約束的規則;因為帖子和回復都有各自獨立的業務場景的需要,所以可以很容易理解它們都是獨立的聚合根;那也很容易知道該如何建立他們之 間的關聯了,但是我們要盡量減少關聯,所以只保留回復對帖子的關聯即可;帖子沒有任何必要去保存一個回復的ID的列表;那么你可能會說,當我刪除一個帖子 后,回復應該是沒有存在的意義的呀?不對,不是沒有存在的意義,而是刪除了帖子后導致了回復對帖子的關聯信息的缺失,導致數據不一致。這是因為帖子和回復 之間有一種必然的聯系(1N),回復一定會有一個對應的帖子;但是回復有其自己的生命周期,不應該隨着帖子的刪除而級聯刪除。這種情況下,如果你刪除了 帖子,就導致回復也成為了一條無效的數據;所以,我們絕對不允許刪除任何聚合根,因為一旦你刪除了聚合根,那就意味着與該聚合根相關的其他任何聚合根都會 有外鍵引用缺失的問題,會導致整個領域模型數據的不一致;所以,永遠都不要刪除聚合根;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM