六邊形架構入門 - levelup

banq發表於2022-06-27

經營傳統農場絕對是一場噩夢。你必須餵食動物,把它們趕出去,安排獸醫的拜訪,種植莊稼,驅趕害蟲,並同時處理數百項其他任務。
把所有東西都放在正確的地方一定是一份全職工作。雞無意識地四處遊蕩,被狐狸搶購一空,羊跳籬笆,荊棘叢生侵入你的土地。
分離農場的不同功能區域是其成功管理的關鍵。讓那些雞遠離玉米地,並豎起堅固的柵欄以阻止奶牛離開城鎮。

六邊形架構入門 - levelup

Clean分離
同樣,在任何重要的軟體專案中,一半的戰鬥都是管理複雜性。事實上,您可能會爭辯說,任何軟體專業人員的主要作用是馴服複雜性,以使我們工作的系統易於更改
劃分應用程式的功能區域是使其易於管理的關鍵。我們不想將永續性框架的關注點與核心業務邏輯、使用者介面或程式碼中發生的任何其他事情混淆。根據單一職責原則,我們希望將因相同原因而發生變化的事物聚集在一起,並將因不同原因而發生變化的事物分開。這樣做可以簡化程式碼的推理、測試和簡單的舊維護。

將因相同原因而發生變化的事物聚集在一起。將那些因不同原因而改變的東西分開——單一職責原則

分層架構
管理關注點分離的最常見模式之一是使用分層架構。

六邊形架構入門 - levelup
來自 Eric Evans 的領域驅動設計
這些層捕獲應用程式的相關部分。出於類似原因而更改的部分保持在一起(內聚),並與程式中關聯度較低的部分分離(解耦)。任何層都應該只依賴於它自己的一部分或它下面的層。這使我們能夠在應用程式的一個領域工作,而不必擔心其他問題。
這是一種易於理解且廣泛使用的模式,對於許多軟體來說非常有用。然而,它並非沒有問題。

當層變成千層面
儘管分層架構有明確的分離,但邊界並不總是得到很好的維護。
無論是否有意識,開發人員偶爾會模糊架構的線條以將功能推出門外。例如,使用資料庫儲存過程來執行業務級任務會將關注點分散到多個層。當您陷入困境時,這可能並不明顯,因此幾個月後,這些層開始相互滲透,混合在一起,破壞了架構的許多好處。

六邊形架構入門 - levelup
此外,分層方法暗示了架構的單一維度。如果您需要的不僅僅是使用者介面來驅動應用程式——新增 CLI、REST API 或事件流作為輸入怎麼辦?當然,您可以將它們新增到分層架構中,但它們不太適合一維心智模型。

驅動和被驅動
讓我們翻轉一個分層架構。

六邊形架構入門 - levelup
使用者介面驅動應用程式。它是所有互動的源泉。軟體的核心(領域及其應用程式服務)對驅動端的互動做出反應,並依賴於較低層來幫助它滿足這些請求。我們可以說那些較低(最右邊)的層是被驅動的
這裡存在一個有趣的對稱性。驅動端和被驅動端都是與我們應用程式之外的事物的互動。它們本身並不提供核心價值——這是領域的工作——而是幫助我們將核心價值傳遞給世界。
軟體提供的價值儲存在這些中間層中,我們應該使與它們的介面——包括測試——儘可能乾淨。同樣,我們希望防止外部擔憂侵犯我們軟體的核心目的。

六邊形架構/埠和介面卡
既然我們已經斷言我們的應用程式的中心是最有價值的部分,我們可以改變我們的架構來保護它。
我們要做的關鍵改變是讓依賴項向內——在域——而不是像以前一樣指向鏈中的下一層。這樣做可以讓我們根據需要注入細節(資料庫、使用者介面等),並使我們的核心抽象保持乾淨和不受影響。
抽象不應該依賴於細節。細節(具體實現)應該依賴於抽象——依賴倒置原則

應用和領域
我們從領域模型開始。我們將其包裝在應用程式服務(與我們的應用程式層相同)中,作為我們軟體的核心。

六邊形架構入門 - levelup
這個捆綁包通常與技術無關——它只涉及我們的軟體旨在解決的問題。這使得推理、與領域專家討論和測試變得更加簡單。隨著我們的發展,我們不再在頭腦中處理正交問題。

通往外部世界的埠
當然,我們需要在這個核心中插入一些東西,否則它完全沒用。這就是的用武之地。

只是一個介面。在駕駛方面,這個介面是呼叫我們的軟體,詢問它的問題——例如,將 10 美元存入我的銀行賬戶。在驅動端,我們有介面將被域呼叫以使用外部資源——資料庫、外部 API 等。

六邊形架構入門 - levelup
六邊形架構的“六邊形”部分是為了證明一個應用程式可能有許多不同的東西插入這些埠。我們可以使用 GUI 和測試工具驅動軟體,或者在後端插入不同的資料庫技術。

使用介面卡插入
埠只是介面,所以我們需要一些東西來實現它們。我們要與之互動的系統不會相容,因此我們需要使用介面卡模式從一個域轉換到另一個域。
每個埠都可以通過介面卡安裝,以允許外部系統與我們的應用程式對話,或者(在右側)讓我們的應用程式與外部系統對話。
如前所述,這些介面卡被注入,以便介面或資料表為中心的抽象不依賴於它之外的細節。

六邊形架構入門 - levelup


結論

這是六邊形結構的最終形式。我們已經從以層為幌子的善意但最終耦合的架構轉變為更清潔、更健壯的架構。
埠和介面卡使我們能夠在系統中保持牢固的邊界,將不相關的事物很好地劃分。我們在六邊形周圍有多個埠這一事實允許我們在每個埠插入多個系統,並通過測試介面卡確保我們不會意外地將核心與外層耦合(通過三角測量)。
當然,一切都是有代價的。需要定義埠介面,並且需要開發介面卡以在外層和內層的語義之間進行轉換。這並非完全微不足道,並且確實帶有一些維護開銷/樣板。
對於簡單的軟體,六邊形架構幾乎可以肯定是矯枉過正。不過,對於更復雜的應用程式——尤其是那些具有繁忙領域或遵循領域驅動設計的應用程式——它可能是您工具箱中非常有價值的補充,有助於保持軟體易於理解和易於發展。

相關文章