「領域驅動設計」集成有界上下文的策略

在過去的幾周裏,我們研究了領域驅動設計領域中的一些重要主題。

首先,我們看看什麼是領域模型,以及它們爲什麼對領域驅動設計如此重要。領域模型是圍繞業務的特定問題的重點知識。

接下來,我們研究了有界的上下文,以及它們如何適應整個組織的上下文映射。有界上下文是特定域模型周圍的邊界,而上下文映射是每個有界上下文如何適應全局的全局視圖。

絕大多數領域驅動的設計應用程序都有多個有界的上下文。這可能意味着與第三方服務集成,但通常情況下,您還需要與現有的遺留應用程序或同一應用程序的其他模型集成。

有許多技術方法可以集成有界上下文、第三方服務和遺留應用程序。

然而,選擇正確的集成模式非常重要,因爲它將對應用程序的設計和整個項目的未來產生重大影響。

在今天的文章中,我們將討論在域驅動設計應用程序中集成有界上下文的策略,每種策略的優缺點以及如何決定爲項目選擇哪種上下文。

重述域模型和有界上下文

在開始討論集成策略之前,我們先快速回顧一下域模型和邊界上下文。

領域模型是圍繞特定問題的重點知識。這包括實體、值對象和特定於特定問題的重要事物之間的關係。

有界上下文是關於域模型的邊界。在有限的上下文中,對象的語言、名稱和思想應該形成手邊問題的統一模型。有界的上下文將內部模型與外部世界的複雜性隔離開來。每個有界的上下文應該有一個內部模型,團隊的所有成員都能清楚地理解這個模型。這很重要,因爲在大多數組織中,某些術語在不同的部門或業務領域有不同的含義。

最後,上下文映射是每個有界上下文如何在應用程序或組織中相互配合的全局視圖。這個更大的問題視圖確保應用程序的目標不會丟失在每個有界上下文的重點細節中。對於每個有界的上下文,最好有一個真正的內部模型和一層轉換,而不是使用單一的對象來試圖填補不同的、常常相互衝突的工作。

軟件項目的現實

在理想的情況下,每個軟件項目都可以從頭開始,有一個乾淨的 git 存儲庫,沒有遺留問題。

然而,在現實世界中,這種類型的項目非常少見。

絕大多數重要的應用程序開發項目都需要多個有界上下文。

在與現有組織合作時,通常需要與遺留應用程序或第三方服務集成。

因此,您的工作就是將這些遺留應用程序和第三方系統與您正在進行的新項目集成起來。

這些類型的集成的問題是,您可以發現自己處於無限多的情況中。例如,您可能會發現自己受制於第三方服務,或者您可能負責爲現有遺留系統提供接口。

我將在本文中討論許多不同的集成策略。每種策略都有其優點和缺點。

爲特定的情況選擇正確的集成策略非常重要,因爲它將對應用程序的設計和未來的開發路徑產生重大影響。

一個簡單的翻譯例子

在我們開始討論集成策略之前,首先我將解釋一個簡單的示例,以便我們都能理解爲什麼這很重要。

想象一下,我們以顧問的身份進入一家現有的線下零售商,爲該公司創建一個新的在線電子商務網站。

這家公司已經在商業大街上經營了很多年,所以它已經有了現有的股票管理、分銷和金融系統。

我們的任務是創建一個電子商務網站,可以接口與公司現有的系統,提供一個無縫的銷售新渠道。

我們的新開發項目顯然是一個新的有界的環境,在組織作爲一個整體的環境地圖的範圍內。我們不會擴展當前的任何系統,但是我們必須使用並返回來自每個現有系統的數據,以便使新通道無縫地集成到當前的體系結構中。

我們將需要能夠要求從庫存管理系統的數據,以便知道什麼應該提供網上購買。

我們還需要將數據發送到配送和財務系統,以便正確處理訂單和處理公司的會計責任。

如果這是一個真實的情況,我們可能不得不與大量其他現有系統和第三方服務進行交互。但是,希望您能夠通過一層轉換看到與現有系統集成的需求。

而在一個理論的想法世界,如果電子商務銷售、庫存管理、分銷和財務都是一個統一的模型的一部分,那就太好了。然而,這樣一個系統的複雜性將很快失去控制。

相反,我們需要找到通過翻譯層進行集成的方法。以下是 7 種方法。

共享內核

第一個集成策略是使用一個共享內核,其中域模型的一部分在處理相同應用程序的不同團隊之間共享。

共享內核集成策略是有益的,因爲它減少了重複代碼的數量和翻譯層的開銷。

但是,只有當所有的開發團隊都致力於共享和交流共享代碼的需求時,共享的內核才能工作。這意味着共享內核的設計不能像應用程序的其他方面那樣快速發展,任何更改都必須得到每個開發團隊成員的同意。

每個開發團隊還必須承擔維護單元測試的同等責任,以確保共享內核的功能保持一致。

當應用程序的某個方面存在一個共享需求,並且通信水平較高,政治動盪程度較低時,共享內核集成策略比我們將在本文中看到的許多其他集成策略更容易實現。

在我們的電子商務類比中使用共享內核的一個例子可能是,客戶模型在交易團隊和在線營銷團隊之間共享。

交易團隊需要客戶模型來關聯交易和請求支付,而在線營銷團隊需要客戶模型來發送營銷信息來刺激新購買,並讓客戶瞭解新產品和新報價。

與兩個團隊編寫自己的客戶模型並來回轉換不同,他們可以使用一個共同的客戶模型來滿足他們的需求。這意味着團隊需要就客戶模型的規範達成一致,並且任何未來的變更都必須由兩個團隊簽署。

客戶 / 供應商

兩個軟件應用程序之間的常見關係是,下游應用程序需要來自上游應用程序的數據,但上游應用程序不依賴於下游應用程序。

這種關係可以通過許多不同的方式表現出來。

首先,如果上游團隊不考慮下游團隊的需求而進行更改,那麼下游團隊就會受到上游團隊的支配。

另外,如果下游團隊能夠控制他們的應用程序的發展,那麼上游團隊就會感到他們的應用程序的設計和實現受到了限制。

下游團隊依賴於上游團隊,但上游團隊不負責下游團隊的交付。爲了使這種情況起作用,兩個團隊需要有一個正式的關係,其中考慮了下游團隊的需求,就像在任何客戶 / 供應商關係中一樣。

這意味着未來的發展優先事項、任務和要求必須得到兩個工作隊成員的同意。

兩個團隊還應該就一系列驗收測試達成一致,以確保邊界的接口保持一致。這意味着只要接口保持一致,上游團隊就可以發展他們的應用程序,而下游團隊可以確信,他們不會因爲上游團隊的更改而某天醒來發現他們的應用程序被破壞。

當兩個團隊的目標是一致的,或者他們都向相同的管理層報告時,客戶 / 供應商關係工作得最好。當兩個團隊的目標不一致時,關係往往會破裂。

電子商務類比中的客戶 / 供應商關係的一個例子是,一個單獨的分析應用程序必須從電子商務應用程序獲取數據,以生成客戶建議並預測新的趨勢。

分析應用程序位於不同的有界上下文中,因爲它可能使用不同的編程語言編寫,使用與電子商務應用程序非常不同的工具和持久存儲。

分析應用程序依賴於電子商務應用程序來發送事務、客戶概要和跟蹤事件的數據,以便運行分析。

兩隊應就數據的類型、格式和方法以及如何向下遊傳送數據達成協議。如果兩個團隊在提高公司整體的成功和盈利能力上保持一致,這種關係就更有可能奏效。

墨守成規

當客戶和供應商之間的關係不一致時,下游團隊可能最終處於一種受上游團隊支配的情況。

這可能發生在同一家公司,其中每個團隊向具有不同目標的非常不同的管理層報告,或者供應商有許多小客戶,因此每個單獨的客戶對供應商來說不是特別重要。

這意味着上游團隊沒有動力爲下游團隊提供任何類型的優先級甚至一致性。下游團隊必須接受這樣一個事實,即他們不能依賴上游團隊和關係邊界上一致的接口。

如果上游應用程序的價值對下游應用程序至關重要,那麼繼續下去的唯一方法就是堅持上游團隊的想法。

這將意味着上游團隊將完全控制這兩個應用程序的集成,因此下游團隊只能讓它工作。

這將導致下游團隊對上游團隊有很深的依賴性,因此任何未來的開發都將受到形勢的限制。

在我們的電子商務類比中,因循守舊關係的一個例子可能是,我們依賴第三方送貨服務向客戶發送包裹。爲了更新客戶的進度位置,我們需要從第三方交付服務請求更新。

然而,我們只是數以千計的快遞服務客戶中的一員,所以他們沒有動力提供我們需要的數據。交付服務也可以在任何時候自由地更改它們的 API,這可能會破壞我們的集成。

在這種情況下,我們完全處於交付服務的支配之下,因此我們必須負責接受他們的數據和他們提供的請求數據的接口。如果接口發生了變化,我們有責任遵循這些變化並演進我們的集成以滿足那些需求。

反腐敗層

在使用現有的遺留應用程序或第三方服務時,集成需求通常很複雜。雖然一開始似乎很容易避免集成,但是如果其他系統非常重要,那麼集成中可能有更多的價值。

集成其他系統是困難的,因爲其他模型可能通過集成而泄漏,並開始影響新系統自己的模型。過多地適應現有的系統,我們最終會得到一個新的系統,它的模型不一致或者不適合解決它自己的問題。

爲了防止模型從外部系統內部泄漏到新系統,我們需要一種方法來在兩個模型之間轉換數據。這通常意味着確保在新模型中解釋數據的上下文是一致的,但也要防止在集成過程中出現不必要的數據泄漏。

爲了實現這一點,我們需要創建一個隔離層,它可以與遺留系統和第三方系統的現有接口進行通信,然後在內部模型之間來回轉換請求。

在我們的電子商務類比中使用反腐敗層的一個例子是,將現有的線下零售系統的客戶忠誠度計劃與新的在線零售系統的客戶忠誠度計劃聯繫起來。

如果現有的線下客戶與零售商之間存在忠誠度平衡,並且她開始在網上購物,那麼這兩個系統應該相互瞭解,這樣客戶就不會失去優惠或折扣。

然而,這兩個系統可能會有不同的模型和不同的支持數據,而這些模型和數據在這兩個系統之間是不相關的。

爲了保持兩個系統的一致性,我們可以設置 Web 掛鉤 (什麼是 Web 掛鉤?),每當客戶忠誠度平衡在關係的一端更新時,它就會發送請求。

當請求被髮送或接收時,它將通過反腐敗層被轉換爲接收應用程序的適當形式。這意味着數據可以在兩個系統之間流動,而不必更改現有的脫機系統,也不必使新系統符合現有系統的模型。

開放主機

當您的應用程序需要與另一個系統集成時,您通常會提供一個轉換層來簡化集成。

然而,當您的應用程序需要與許多其他現有系統集成時,擁有所有這些翻譯層可能會變得難以處理。

不是爲每個集成提供一個獨立的翻譯層,而是提供一組可由任何其他有界上下文使用的服務。

通過將應用程序作爲一系列服務提供,可以減少維護多層翻譯所需的開銷。

隨着新功能在內部創建或從外部使用者請求,這些服務可能會發展。然而,對於一次性集成需求,單層轉換要比犧牲通用服務接口更好。

在我們的電子商務應用程序中使用開放主機策略的一個例子可能是將客戶和交易的數據作爲一系列服務提供。

公司內部的許多現有應用程序可能需要從我們的應用程序請求數據來完成訂單或補充產品庫存,因此,我們可以提供一組服務來減少這種開銷,而不是爲每個系統提供翻譯層。

發佈的語言

將來自外部系統的模型集成到新系統中是困難的,因爲您不希望您的新系統受到外部系統設計的影響。

外部系統的模型可能與您的內部模型不兼容,因此接受它們的模型作爲數據交換語言意味着您的模型依賴於外部系統並受到外部系統的影響。

我們不應該依賴模型作爲數據交換語言,而應該使用通用的發佈語言,如 JSON 或 XML,這些語言允許使用通用格式在不同的系統之間轉換數據。

在我們的電子商務類比中,使用已發佈語言的一個例子可能是每當發生新事務時更新消息傳遞應用程序。消息傳遞應用程序將向客戶發送電子郵件,通知他們產品更新、折扣和相關產品。

我們可以通過將請求的詳細信息發送爲 JSON 或 XML 來確保數據與消息傳遞應用程序兼容。通過將數據作爲公共格式發送,我們並沒有強迫消息傳遞系統遵從我們的內部模型,或者在如何設計內部應用程序方面做出妥協。

分道揚鑣

在許多情況下,集成的成本可能比它的價值要高。這可能是由於墨守成規的情況,或者可能是其他團隊太難以合作。

如果兩個系統之間的功能或數據沒有內在的聯繫,僅僅因爲它是相關的,並不意味着它應該被集成。

另一個有吸引力的選擇是允許兩個系統以各自的方式運行,而不是試圖強制進行集成。

在我們的電子商務類比中,另一種方法的例子可能是向零售商現有的財務部門報告財務統計數據。財務部門使用一個古老的系統,需要很長時間才能與我們新的電子商務應用程序集成。

公司的財務負債需要每週、每月、每季、每年報告一次。對我們的需求來說,花費時間在兩個系統之間構建實時報告的集成是多餘的。

相反,我們可以簡單地確保財務報告能夠以所需的格式導出。這意味着兩個系統根本不需要集成,因此我們失去了使集成工作正常進行的開銷。

結論

在任何重要的應用程序中,幾乎不可避免地需要與現有的應用程序、第三方服務或多個有界上下文集成。

世界上許多不同類型的公司都可以通過在組織內集成新的和現有的系統來獲得巨大的生產力收益。

當您被要求集成兩個非常不同的系統時,理解圍繞集成的通用模式將是一項巨大的資產。

在開發全新的應用程序時,集成也是需要記住的重要內容。通過將您的應用程序作爲一系列的服務來提供,您將使將來與您的應用程序的集成需求變得更加容易!

當分佈式系統可以作爲一個整體進行集成和利用時,軟件的力量就會被放大。瞭解如何在不同的環境下集成應用程序是非常有價值的知識。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-qfI5FDokySeHm9-3Nwf7A