識別每個微服務的領域模型界限

提示

本內容節錄自《容器化 .NET 應用程式的 .NET 微服務架構》(.NET Microservices Architecture for Containerized .NET Applications) 電子書,可以在 .NET Docs 上取得,或免費下載可供離線閱讀的 PDF。

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

識別每個微服務的模型界限和大小時,其目標不是為了取得可能最細微的分離,不過您應該盡可能傾向小型微服務。 相反地,您的目標應該是在您的領域知識引導下取得最有意義的分離。 重點不是大小,而是商務功能。 此外,如果以大量相依性為基礎的應用程式有某部分需要明確內聚,這也表示需要單一微服務。 內聚是指定如何將微服務分開或群組在一起的方式。 基本上,當您取得更多有關領域的知識時,您應該反覆地調整微服務的大小。 您不會一次就找到正確的大小。

Sam Newman 是公認的微服務推動者,也是 Building Microservices 一書的作者,他強調您應該根據稍早所介紹的限定內容 (Bounded Context,BC) 模式 (領域導向設計的一部分),來設計您的微服務。 有時候,BC 可能是由數個實體服務所組成,但反之則不亦然。

具有特定領域實體的領域模型會在實體 BC 或微服務內套用。 BC 會界定領域模型的適用性,讓開發人員小組成員對於哪些項目必須內聚、哪些項目可以獨立開發有清楚的共識。 所有微服務都有這些相同目標。

另一個左右設計選擇的工具是 Conway's law (Conway 定律),該定律指出應用程式會反映產生該應用程式組織的社交界限。 但有時候則是相反的情況,公司的組織是由軟體所構成。 您可能需要反轉 Conway 定律,並以您想要的公司組織方式來建立界限 (傾向商務程序諮詢)。

若要識別具有界限的內容,您可以使用稱為 Context Mapping pattern (內容對應模式) 的 DDD 模式。 透過內容對應,您可以識別應用程式及其界限內的各種內容。 例如,每個小型子系統通常會有不同的內容和界限。 內容對應可讓您定義並明確化領域之間界限。 BC 是自主的,並包含單一領域的詳細資料 (領域實體等詳細資料),而且會定義與其他 BC 的整合合約。 這與微服務的定義類似:它是自主的、實作特定領域功能,而且必須提供介面。 因此,內容對應和限定內容模式是識別微服務之領域模型界限的好方法。

設計大型應用程式時,您會看到其領域模型的分割方式。例如,來自目錄領域的領域專家在命名目錄和庫存領域中的實體時,會與運送領域專家不同。 或者,面對想要儲存客戶所有詳細資料的 CRM 專家時,與面對只需要客戶部分資料的訂購領域專家時,使用者領域實體可能會有不同的大小和屬性數目。 您很難釐清大型應用程式所有相關領域的所有領域詞彙。 但最重要的是,您不應該嘗試統一詞彙。 您應該改為接受每個領域所提供的差異與豐富度。 如果您想要讓整個應用程式有統一的資料庫,嘗試統一詞彙並不容易,而且對任何多重領域專家而言也不正確。 因此,BC (實作成微服務) 會協助您釐清哪裡可以使用特定領域詞彙,以及哪裡需要分割系統並使用不同的領域來建立其他 BC。

您會知道,只要領域模型之間有幾個強固的關聯性,每個 BC 和領域模型的界限和大小就正確,而且您通常不需要在執行一般應用程式作業時,合併多個領域模型的資訊。

針對每個微服務的領域模型該有多大的這個問題,最佳答案或許如下:它應該具有自主的 BC 並盡可能隔離,以便您能夠持續工作而不需要經常切換至其他內容 (其他微服務的模型)。 在圖 4-10 中,您會看到多個微服務 (多個 BC) 各自擁有自己的模型,以及根據您應用程式中每個識別領域的特定需求,可如何定義這些微服務的實體。

Diagram showing entities in several model boundaries.

圖 4-10: 識別實體和微服務模型界限

圖 4-10 說明與線上會議管理系統相關的範例案例。 相同的實體會根據界限內容顯示為「使用者」、「購買者」、「付款人」和「客戶」 您已根據領域專家為您定義的領域,識別可實作成微服務的數個 BC。 如您所見,單一微服務模型中就有多個實體,例如「付款」微服務中有多個「付款」。 這些實體實作起來很容易。

不過,您也可能會有多個形狀不同的實體,但在來自多個微服務的多個領域模型之間共用相同的身分識別。 例如,在「會議管理」微服務中已識別「使用者」實體。 具有相同身分識別的相同使用者也是「訂購」微服務中的「購買者」,或「付款」微服務中的「付款者」,甚至是「客戶服務」微服務中的「客戶」。 這是因為根據每個領域專家所使用的通用語言,使用者可能會有不同的檢視方塊,甚至會有不同的屬性。 名為「會議管理」之微服務模型中的使用者實體可能會有其大多數的個人資料屬性。 不過,在「付款」微服務中作為「付款者」或在「客戶服務」微服務中作為「客戶」的相同使用者不一定需要相同的屬性清單。

圖 4-11 說明類似的方法。

Diagram showing how to decompose a data model into multiple domain models.

圖 4-11: 將傳統資料模型分解成多個領域模型

分解具界限內容間的傳統資料模型時,您可以擁有共用相同身分識別 (購買者同時也是使用者) 的不同實體,在每個具界限內容中皆有不同的屬性。 如您所見,使用者會以「使用者」實體出現在「會議管理」微服務模型中,也會以「購買者」實體形式出現在「定價」微服務中,當使用者實際上是購買者時,就會替換成該使用者的相關屬性或詳細資料。 視要解決的問題或內容而定,每個微服務或 BC 不一定需要與「使用者」實體相關的所有資料。 例如,在「定價」微服務模型中,您不需要使用者的地址或名稱,只需要識別碼 (作為身分識別) 和狀態,這會影響每個購買者席次的定價折扣。

每個領域模型中的「席次」實體會有相同的名稱但不同的屬性。 不過,「席次」會依據相同的識別碼來共用身分識別,如同「使用者」與「購買者」的情況。

基本上,存在於多個服務 (領域) 的使用者具有共用概念,因此所有服務會共用該使用者的身分識別。 但在每個領域模型中,可能會有使用者實體的其他或不同詳細資料。 因此,您必須能夠將使用者實體從一個領域 (微服務) 對應至另一個。

不要跨領域共用具有相同屬性數目的相同使用者實體有幾個優點。 一個優點是減少重複,讓微服務模型不會有任何不必要的資料。 另一個優點是具有主要微服務,以針對每個實體擁有一種資料類型,讓該資料類型的更新和查詢完全取決於該微服務。