洋蔥架構

洋蔥架構是由 Jeffrey Palermo 在 2008 年提出的。在我看來,它是基於 Ports & Adapters 架構的構念,將領域(domain)放在應用程式的中心,將交付機制(UI)和系統使用的基礎設施(infrastructure, ex.ORM,搜索引擎,第三方API等)。差別是,它對內部進行了分層。

我們從分層架構學習到最基本的分層通常有:

  • Presentation 呈現層
  • Application 應用層
  • Domain 領域層
  • Persistence 持久層

而 Ports & Adapters 架構隱含了兩個同心層:

  1. 外部:傳遞機制(delivery mechanisms)與基礎設施(infrastructure)
  2. 內部:業務邏輯

Ports & Adapters 和 Onion Architecture 同時擁有一個概念,那就是通過編寫適配器(adapter),將應用程式的核心與基礎設施隔離,以防止基礎設施滲透到應用程式核心中(意思是應用程式核心直接對基礎設施產生依賴)。這使得抽換應用程式使用的工具和交付機制變得更容易,提供了一些對技術、工具和供應商鎖定的保護。

這也賦予應用程式一種愉快的能力,即無需真實的基礎設施或交付機制就能運行,因為它們可以被模擬物件所替換,這易於進行程式碼的測試。

然而,洋蔥架構也告訴我們,在企業應用中,我們將不只有內部與外部這樣簡單的分層,在內部,也就是業務邏輯中,我們會增加一些我們從領域驅動設計(DDD)認識的一些層: onion

此外,它明確地闡述了 Ports & Adapters 架構中關於依賴方向的隱含概念:

  • 外層依賴於內層,
  • 內層對外層一無所知。

這意味著耦合的方向是朝向中心,為我們提供了一個獨立的物件模型(domain model),其核心不依賴任何東西。我們有足夠的靈活性可以改變外層,而不影響內層,更重要的層面。它在架構層面上運用了依賴反轉原則。

  • 洋蔥架構的主要原則:
    • 應用程式是建立在一個獨立的物件模型周圍。
    • 內層定義介面,外層實現介面。
    • 耦合的方向是朝向中心。
    • 所有應用程式的核心代碼都可以獨立於基礎設施進行編譯和運行

此外,任何外層都可以直接呼叫任何內層,這不會破壞耦合方向,並避免創建僅包含無業務邏輯的 proxy methods,甚至是 proxy classes,僅為了符合某種分層方案。這也符合 Martin Fowler 所表達的。

[…] the layers above can use any layer beneath them, not just the layer immediately beneath. - Jeffrey Palermo 2008, The Onion Architecture: part 3
[…] 上層的層次可以使用任何位於其下的層次,而不僅僅是直接下方的那一層。 - 傑弗里‧巴勒莫 2008,洋蔥架構:第三部分

結論

洋蔥架構是建立在 Ports & Adapters 架構的基礎上,根據一些領域驅動設計的概念,為應用程序的業務邏輯增加了一些內部分層。

旨在進一步區分了責任,提供了低耦合和高內聚,並同時提供了更好的可測試性(testability)可維護性(maintainability)