DDD學習(二) 領域建模重要概念

2021-10-10 17:54:51 字數 2885 閱讀 8688

在閱讀之前應該理解了ddd的主要思想和 限界上下文,子域核心域等基礎概念

一些物件主要不是由它們的屬性定義的。它們實際上表示了一條「標識線」(a thread of identity),這條線跨越時間,而且常常經歷多種不同的表示。有時,這樣的物件必須與另乙個具 有不同屬性的物件相匹配。而有時乙個物件必須與具有相同屬性的另乙個物件區分開。錯誤的標識可能會破壞資料。

主要由標識定義的物件被稱作entity。entity(實體)有特殊的建模和設計思路。它們具 有生命週期,這期間它們的形式和內容可能發生根本改變,但必須保持一種內在的連續性。為了 有效地跟蹤這些物件,必須定義它們的標識。它們的類定義、職責、屬性和關聯必須由其標識來 決定,而不依賴於其所具有的屬性。即使對於那些不發生根本變化或者生命週期不太複雜的 entity,也應該在語義上把它們作為entity來對待,這樣可以得到更清晰的模型和更健壯的實現。

當然,軟體系統中的大多數‚entity‛並不是人,也不是其通常意義上所指的‚實體‛或‚存 在‛。entity可以是任何事物,只要滿足兩個條件即可:

比如小明想去看一場演唱會,買了一張門票,門票上寫著座位號為 4排3座 ,那麼該座位在建模時應當是實體,因為小明應該只能坐 4排3座 的座位,其他位置的座位不屬於他。此時 4排3座就是乙個唯一性標識。但如果演唱會門票改為入場券形式,即門票上只說明可以憑此票擁有乙個座位,那麼此時的座位就不再是實體,而應該是「值物件」,也就是說每個座位都是一樣的,只是用來坐而已。後一節我們將會詳細了解值物件的概念。

注意:將與標識有關的屬性留在entity裡,將無關行為和屬性轉移到與核心實體關聯的其他物件中。

識別時注意:是否可以互換?

很多物件不是通過它們的屬性定義的,而是通過連續性和標識定義的。

建立實體身份標識的策略,從簡單到複雜:

用於描述領域的某個方面而本身沒有概念標識的物件稱為value object(值物件)。value object被例項化之後用來表示一些設計元素,對於這些設計元素,我們只關心它們是什麼,而不 關心它們是誰。

value object可以是其他物件的集合。在房屋設計軟體中,可以為每種窗戶樣式建立乙個物件。我們可以將「窗戶樣式」連同它的高度、寬度以及修改和組合這些屬性的規則一起放到「窗戶」物件中。這些窗戶就是由其他value object組成的複雜value object。它們進而又被合併到更大的設計元素中,如「牆」物件。

value object經常作為引數在物件之間傳遞訊息

value object可以用作entity(以及其他value)的屬性

value object應該是不可變的

如果乙個實體持有值物件集合引用,該如何去儲存呢?例如,在許可權管理系統中,乙個使用者a,持有值物件集合,每個值物件也是立體的物件,包括各種屬性,那麼如何將這種關係持久化儲存呢?

使用資料庫實體保持多個值物件

使用聯合表儲存多個值物件

在某些情況下,最清楚、最實用的設計會包含一些特殊的操作,這些操作從概念上講不屬於任何物件。與其把它們強制地歸於哪一類,不如順其自然地在模型中引入一種新的元素,這就是service(服務)。

好的service有以下3個特徵:

與領域概念相關的操作不是entity或value object的乙個自然組成部分。

介面是根據領域模型的其他元素定義的。

操作是無狀態的。

領域服務是用來協調領域物件完成某個操作,而不屬於某個物件;但與物件關係緊密,需要參照物件來設計;用來處理業務邏輯,它本身是乙個行為,所以是無狀態的。狀態由領域物件(具有狀態和行為)儲存。

上面也說了,領域物件是具有狀態和行為的。那就是說我們也可以在實體或值物件來處理業務邏輯。那我們該如何取捨呢?

一般來說,在下面的幾種情況下,我們可以使用領域服務:

比如在銀行系統中,轉賬應該是乙個領域服務,它包含了很多步驟,涉及轉賬方餘額校驗,收款方是否符合規定,扣款,餘額增加,保持事務,轉賬失敗回滾等等業務領域的操作,這些操作無法直接被某個領域物件完全收斂,所以選擇以領域服務進行實現。

注意:要將領域服務和應用服務進行區分!

應用服務是用來表達用例和使用者故事(user story)的主要手段。

應用層通過應用服務介面來暴露系統的全部功能。在應用服務的實現中,它負責編排和**,它將要實現的功能委託給乙個或多個領域物件來實現,它本身只負責處理業務用例的執行順序以及結果的拼裝。通過這樣一種方式,它隱藏了領域層的複雜性及其內部實現機制。

除了定義應用服務之外,在該層我們可以進行安全認證,許可權校驗,持久化事務控制,或者向其他系統發生基於事件的訊息通知,另外還可以用於建立郵件以傳送給客戶等。

應用層作為展現層與領域層的橋梁。展現層使用vo(檢視模型)進行介面展示,與應用層通過dto(資料傳輸物件)進行資料互動,從而達到展現層與do(領域物件)解耦的目的。

比如轉賬的一系列操作,當轉賬完成後,傳送簡訊通知使用者,這個行為我們更偏向於將它建模為應用服務。很顯然,這個傳送簡訊與轉賬這一業務沒有關係,我們要確保領域服務只關心業務邏輯即純粹性。

不要過度使用領域服務

過度使用領域服務將會產生乙個貧血模型,例如資料建模時,我們的實體常用只含有get/set方法,所有的業務邏輯都包含在了service。這樣導致service變成了乙個大泥球。注意區分領域服務與實體,值物件行為。

領域事件是乙個領域模型中極其重要的部分,用來表示領域中發生的事件。忽略不相關的領域活動,同時明確領域專家要跟蹤或希望被通知的事情,或與其他模型物件中的狀態更改相關聯。

領域事件更加關注最終一致性,而不是原子性。

可以對照 事件匯流排 來進行理解。

領域事件經常被用來充當不同聚合間交換資訊的媒介,我們知道聚合的內部是統一的,但有時也要保證不同聚合間的一致性,但又不能直接去做,因為讓不同聚合內部的屬性同步,違反了聚合的設計理念,所以用領域事件來達到最終一致性。

摘譯 面向領域建模

還是原來我在blog中提到過的,微軟的思路 dsl,包括現在說的dsm,其實都是或者說來自mda的思路。只不過是 1 不是用的uml的標準。2 現在通過領域限定來降低目前實現mda支援的難度。而且和微軟的大多數產品一樣,微軟做的東西易用性上會好一些,這一點足夠重要。dsm規避了mda發展中的難題,不...

鄧麗君的領域建模

建模競賽題第2賽季第22輪 請根據以下資訊畫出系統的分析類圖。6分 所有回答者都可以得分。總分數根據時間和答案質量綜合評定,回答時間靠後的分數打折扣,折扣係數0.05。舉例 第乙個答,答案質量得分4分,總分4分 第5個答,答案質量得分5分,總分5 1 5 1 0.05 4分。如果有人喜歡一首歌曲,他...

業務領域建模Domain Modeling

每個業務都有乙個對應的業務模型,這個業務模型設計的時候,完全不需要考慮任何軟體設計的思想,比如物件的抽象 繼承 儲存 效能,等。我們是從業務本身出發,分析業務邊界範圍內的各種業務概念,以及業務概念之間的關係,通常我們可以使用乙個業務模型的圖來表達這些業務概念以及業務概念之間的關係。那麼如何得到乙個業...