領域驅動設計(DDD)反對為整個系統建立單一統一模型的想法:相反地,它鼓勵將系統分成限定的內容,每個內容都有自己的模型。 在 DDD 的策略性階段期間,您會對應業務領域並為領域模型定義限界內容。
在戰術性 DDD 中則會更加精確地定義領域模型。 戰術性模式會在單一限界內容中套用。 在微服務架構中,每個限定內容都是微服務候選項目,我們對實體和匯總模式特別感興趣。 套用這些模式可協助我們識別應用程式中服務的自然界限(請參閱 本系列中的下一篇文章 )。 一般來說,微服務應大於彙總,且小於限界內容。 首先,我們將檢閱戰術模式。 然後,我們會將它們套用至無人機遞送應用程式中的出貨界限內容。
戰術模式概觀
本節提供戰術 DDD 模式的簡短摘要,因此如果您已經熟悉 DDD,您可以略過本節。 這些模式在埃裡克·埃文斯著作的第 5 章 - 6 章中更詳細地描述,以及在實作 Vaughn Vernon 的網域驅動設計中。
實體。 實體是具有唯一的身分識別,且會持續一段時間的物件。 例如,在銀行應用程式中,客戶和帳戶會是實體。
- 實體在系統中具有唯一標識符,可用來查閱或擷取實體。 這並不表示標識子一律會直接公開給使用者。 它可以是 GUID 或資料庫中的主鍵。
- 身分識別可能會跨越多個限定內容,而且可能會持續超過應用程式的存留期。 例如,銀行帳戶號碼或政府發行的標識符不會系結至特定應用程式的存留期。
- 實體的屬性可能會隨著時間而變更。 例如,人員的名稱或位址可能會變更,但它們仍然是相同的人。
- 實體可以保存其他實體的參考。
值物件。 值對象沒有身分識別。 它只會由其屬性的值定義。 Value 物件也是不可變的。 若要更新值物件,您一律會建立新的實例來取代舊的實例。 值物件可以有封裝定義域邏輯的方法,但這些方法應該不會對對象的狀態產生副作用。 值物件的典型範例包括色彩、日期和時間,以及貨幣值。
匯總。 彙總定義了一或多個實體周圍的一致性界限。 匯總中只有一個實體是根目錄。 查閱是使用根實體的標識碼來完成。 匯總中的任何其他實體都是根目錄的子系,而且會透過根目錄中的下列指標來參考。
彙總的目的是將交易的不變項目模型化。 真實世界中的事物具有複雜的關聯性。 客戶建立訂單、訂單包含產品、產品具有供應商等等。 如果應用程式修改數個相關物件,其如何保證一致性? 我們要如何追蹤不變項目並加以強制執行?
傳統應用程式通常會使用資料庫交易來強制執行一致性。 不過,在分散式應用程式中,這通常不可行。 單一商務交易可能會跨越多個數據存放區,或可能長時間執行,或可能涉及第三方服務。 歸根結底,應用程式,而不是數據層,以強制執行定義域所需的不因。 這就是匯總的模型。
注意
匯總可能包含沒有子實體的單一實體。 使它成為匯總的是交易界限。
網域和應用程式服務。 在 DDD 術語中,服務是指會實作某些邏輯,而不保留任何狀態的物件。 Evans 區分 網域服務,這些服務會封裝網域邏輯,以及 提供技術功能的應用程式服務,例如使用者驗證或傳送簡訊。 領域服務通常會用以將跨越多個實體的行為模型化。
注意
服務一詞會在軟體開發中多載。 此處的定義與微服務不直接相關。
網域事件。 領域事件可用以通知系統的其他部分有情況發生。 正如其名,領域事件應代表領域中所發生的事物。 例如,「已將記錄插入資料表中」就不是領域事件。 「已取消傳遞」是網域事件。 領域事件在微服務架構中特別具有關聯性。 因為微服務是分散式的且不會共用資料存放區,因此領域事件可提供方式讓微服務相互協調。 Interservice 通訊一文會更詳細地討論異步傳訊。
這裡未列出一些其他 DDD 模式,包括工廠、存放庫和模組。 當您實作微服務時,這些模式可能很有用,但在設計微服務之間的界限時,它們較不相關。
無人機遞送:套用模式
我們從出貨界限內容必須處理的案例開始。
- 客戶可以要求無人機從向無人機遞送服務註冊的商家中挑選貨物。
- 寄件者會產生要放在套件上的標記 (條形碼或 RF)。
- 無人機會從來源位置挑選包裹並運送到目的地位置。
- 當客戶排程遞送時,系統會根據路線資訊、天氣條件和歷程記錄數據提供ETA。
- 當無人機在飛行時,用戶可以追蹤目前的位置和最新的ETA。
- 在無人機接上包裹之前,客戶可以取消交貨。
- 客戶會在傳遞完成時收到通知。
- 寄件者可以透過簽章或手指列印的形式向客戶要求傳遞確認。
- 用戶可以查閱已完成傳遞的歷程記錄。
從這些案例中,開發小組識別出下列 實體。
- 遞送
- 套件
- 無人機
- 客戶
- 確認
- 通知
- 標記
前四個「傳遞」、「套件」、「無人機」和「帳戶」都是 代表交易一致性界限的匯總 。 「確認」和「通知」是「遞送」的子實體,而「標籤」則是「包裹」的子實體。
此設計中的值物件包括 Location、ETA、PackageWeight 和 PackageSize。
為了說明,以下是傳遞匯總的UML圖表。 請注意,它會保存其他匯總的參考,包括 Account、Package 和 Drone。
有兩個領域事件:
無人機在飛行時,無人機實體會傳送DroneStatus事件,以描述無人機的位置和狀態(飛行中、降落)。
每當傳遞階段變更時,傳遞實體就會傳送 DeliveryTracking 事件。 其中包括 DeliveryCreated、DeliveryRescheduled、DeliveryHeadedToDropoff 和 DeliveryCompleted。
請注意,這些事件會描述領域模型中有意義的事物。 它們描述網域的相關內容,且不會系結至特定的程式設計語言建構。
開發小組還識別出另一個功能領域,但無法明確歸類為目前為止所描述的任何實體。 系統的某些部分必須協調排程或更新遞送時所涉及的所有步驟。 因此,開發小組已將兩個網域服務新增至設計:協調步驟的排程器,以及監視每個步驟狀態的監督員,以偵測是否有任何步驟失敗或逾時。這是排程器代理程式監督員模式的變化。
下一步
下一個步驟是定義每個微服務的界限。