天天看點

教你如何以DDD方式設計雲微服務六邊形架構

前言

雖然微服務一直被認為是領域驅動設計範式的實作,并以正在開發的單個服務的有界上下文為中心,但事實與現實相去甚遠。

雖然 DDD 方法在微服務世界中無處不在,因為它在域和子域中具有獨立/隔離的問題區域,但如果仍然遵循傳統的代碼結構化方式,我們就會錯過這個神奇世界的真正本質。

這篇文章将重點介紹我們今天遵循的實踐,以及符合領域驅動設計和 SOLID 原則的可能解決方案。

這些建議是設計微服務結構的一種固執己見的方式,并且基于雲原生應用程式和相關工作的清潔架構實踐,最初由 Alistair Cockburn、Robert C. Martin 出版和擁有,并且在 Tom Hombergs 所著的書中也有描述。

介紹

在我們的實作過程中,我們都使用設計模式和原則來使我們的應用程式代碼更加健壯、可維護、可了解和可擴充。

但是,如果我們的設計意圖與代碼意圖不相關,我們就無法充分利用這些原則。是以在紙面上,我們确實設計并提到了實作的原則,但代碼可能會朝着完全不同的方向發展。

是以,如果我們遵循 DDD/SOLID/OOPS 并且我們打算開發獨立于 Web、持久性和內建依賴項的服務。而不是域依賴于它們中的任何一個;它們都依賴于域。

對應用程式的任何更改都将是域狀态或行為的更改,相應的服務将相應地适應更改,而不是由 UI 或持久性或任何其他角度的更改來驅動域。

反轉這種依賴關系意味着更容易代碼維護,實施符合項目既定設計指南的治理檢查,并使其更具可擴充性以添加更多功能,否則代碼更改将由于耦合而産生連鎖反應。

否則,每一次新的更改/更新或添加新功能都會使其更加脆弱、固定和僵化,以适應未來的擴充。

背景:六邊形架構

六邊形架構又名端口和擴充卡模式(在某種意義上也可以是管道和過濾器,其中請求和響應在單個方向上模組化)意圖将所有業務邏輯和模型保持在一個地方,其他一切都依賴于此而不是其他方式。

如果我們從任何應用程式層的角度來看,依賴關系将來自控制器/接口和持久性地域,而不是我們通常在項目中建立的分層架構。通過這種方式,我們使這些六邊形獨立并且可以與 DDD 術語中的有界上下文相關聯。通過使用上述類比,我們希望将此架構稱為“插件架構”;您的基本模型保持不變,您可以通過将更多插件實作附加到相同的接口來進一步擴充功能。

教你如何以DDD方式設計雲微服務六邊形架構

擴充卡

這些是核心邏輯接口的具體實作,要麼調用域,要麼被域調用以完成業務。

域對象

代表現實世界的主題。

用例

端口接口的任何業務功能、可通路性和實作。

端口

端口可以​被視為核心邏輯的簡單接口。可能有對應于來自核心邏輯六邊形的傳入和傳出呼叫的入站和出站端口。

Inbound 端口

将核心邏輯暴露給消費擴充卡。

Outbound 端口

通過核心邏輯消費外部服務。

問題陳述

耦合是罪魁禍首

當我們設計我們的應用程式時,我們考慮了世界上的“微服務”、“雲原生開發”。

簡而言之,整個想法是将一個大問題分解為可管理的部分,使其更易于管理、可維護、透明、DevOps/雲就緒,同時快速響應更改,因為更改可能專門位于某些有限的上下文中并且不會對其他人有任何影響。是以,雖然我們使用雲原生開發實踐快速修複和傳遞(利用 CI/CD)功能或對功能的更改,但代碼及其結構應該支援相同的功能。

當且僅當代碼是基于 SOLID 原則編寫的并且在元件之間使用松散耦合以快速響應更改而沒有連鎖反應時,以上所有這些都是可能的。

場景一

傳統的鋪設方式。控制器/接口取決于服務/域和服務/域到 DAO/存儲庫。實際上應該由領域而不是這種方式驅動。

優點

· 熟悉且易于上手。

·看起來與分層架構和層依賴關系更加同步。

缺點

· 對資料庫/基礎設施的依賴

· 可以引入雪花

· 由 UI 或持久性驅動

教你如何以DDD方式設計雲微服務六邊形架構

場景二

另一種設計微服務的方法是将所有域對象和接口打包為單獨的工件/元件并讓服務實作它們。

優點

·易于分發和設計到界面。

·根據上下文,接口的多個實作。

缺點

· 服務、域和存儲庫取決于接口,而不是域/核心邏輯。

·考慮消費而非核心邏輯而建構的接口。

·域日志不穩定,由消費者和界面驅動。

教你如何以DDD方式設計雲微服務六邊形架構

領域應該是中心

在任何領域應用程式中,領域對象都是技術人員和業務人員的中心舞台,因為它們描述了現實世界的業務模型。域對象應該暴露給外部世界以被消費以執行業務意義上的操作。由于域對象包含狀态和行為(響應事件),是以它們是用例實作的主要候選對象。用例将包裝域對象以供消費者/客戶通路和分發。

在使用多層應用程式時,我們可以看到相同的真正好處,是以這些層是可替換的,而無需對應用程式/業務層進行任何更改。

解決方案

教你如何以DDD方式設計雲微服務六邊形架構

服務和域/核心模型被隔離并映射到特定的問題域和/或子域,以被視為有界上下文,并且可以實作為具有自己的分布式接口(Web/移動等)及其持久性邏輯的微服務.

出站端口/擴充卡的設計和開發可以被視為支援服務(https://12factor.net/backing-services),因為出站端口的六邊形架構中的目前抽象支援底層實作的無縫更改,而無需對域/核心進行任何更改邏輯。

擴充 OOPS 視圖

我們還可以将六邊形架構實作視為 OOPS 的擴充,用于設計元件,其中服務和域被封裝在單個/隔離的元件中。具有服務接口地域對象展示了必要的抽象并提供接口來通路域的行為,并擴充了域和服務或服務實作的可擴充性(考慮開放/關閉原則)或子產品化。

教你如何以DDD方式設計雲微服務六邊形架構

執行

教你如何以DDD方式設計雲微服務六邊形架構
教你如何以DDD方式設計雲微服務六邊形架構

· 控制器将作為接口子產品服務的一部分。

· 服務接口、領域對象、實作應該是領域子產品的一部分。

· 存儲庫實作應該是持久化子產品的一部分

好處

教你如何以DDD方式設計雲微服務六邊形架構

· 支援多語言消費者,無需更改域和核心邏輯(消息、HTTP、移動裝置等)。

· 對域執行單一職責(SOLID)

教你如何以DDD方式設計雲微服務六邊形架構

· 支援多語言持久性。

· 支援服務虛拟化(用于接口調用服務)。

· 持久性關注點不影響域事實上域會驅動持久性關注點。

· 依賴反轉到域(SOLID)

· 核心邏輯中的存儲庫接口代表實作替換(SOILD)

· 内部接口代表與外部接口配對,而不是一個巨大的接口。(堅硬的)

教你如何以DDD方式設計雲微服務六邊形架構

· 隻有一個/單一的職責與域來管理業務邏輯。(堅硬的)

· 遵循面向對象原則的領域邏輯,對擴充開放,對修改關閉。(堅硬的)

· 支援松散耦合和高内聚設計,因為有界上下文和反向依賴關系,對一個區域的更改可能不會對其他區域産生任何影響。

· 由于獨立的元件和接口設計,域邏輯更容易測試。此外,它獨立于任何接口/內建技術,可以模拟/存根以測試域邏輯。

· 幹淨的域邏輯不受網絡和持久細節的污染。

結論

以這種方式建構微服務可以讓您更加獨立地使用您的領域,這反映了真實世界的模型。這也使您地域/核心邏輯獨立于消費者(網絡/移動等)和內建(持久性/消息等)并且非常接近純 SOLID 原則的實作。這種方法使您更靈活地适應變化,而不會對其他層産生太大的變化影響,尤其是。接口和內建層由于在需要時進行了獨立的代碼更改。由于其隔離和可分發的特性,核心邏輯可以在各種企業場景中擴充/實作,而不是為每個應用程式建立相同的。