六邊形架構是一種用于設計軟件應用程序的架構模式。近年來,它的受歡迎程度有所增加,因為它是傳統分層架構的替代品。
分層架構有什么問題?
這種架構模式應用 SoC(關注點分離)原則將我們的組件分解為層,每一層都有不同的職責。通常,有 3 層:
- 表示層,其中包含用戶界面。
- 業務層或領域層,包含業務邏輯。
- 持久層,處理數據庫操作。
在應用這種架構模式時,我們面臨著層與層之間的依賴關系,即每一層都依賴于緊接其下的層。該模型未能表明我們可以與多個數據庫交互或根本不與任何數據庫交互。此外,表示層沒有考慮到用戶與我們的應用程序交互的方式可能不止一種。
六邊形架構如何克服分層架構的弊端?
該模型將所有業務邏輯置于應用程序的核心,抽象出任何類型的外部依賴。這種隔離使得邏輯更容易測試和維護。
應用程序現在擁有一個或多個處理用戶請求的輸入適配器,而不是表示層。類似地,現在我們有一個或多個輸出適配器來調用外部應用程序或服務,而不是持久層,例如 Amazon S3 中的文件存儲、SendGrid 等電子郵件服務,或者更常見的是數據庫。
業務核心有一個或多個端口。端口定義了一組操作,允許核心與適配器進行交互,從而與應用程序外部的內容進行交互。正如我們有兩種類型的適配器,輸入和輸出,有一個輸入端口和一個輸出端口。輸入端口是內核公開的供外部應用程序訪問的 API,而輸出端口是允許內核使用外部服務的接口。
輸入適配器通過調用輸入端口來處理來自外部世界的請求。這方面的一個例子是實現 REST API 或 gRPC 服務器的 Spring 控制器。
輸出適配器實現了一個輸出端口,該端口通過調用外部應用程序或服務來處理來自業務核心的請求。一些示例是執行數據庫操作的 DAO(數據訪問對象)類,或使用電子郵件服務的 Spring 組件。
到目前為止,我們已經看到了與六邊形架構相關的概念。現在,讓我們將理論付諸實踐,并使用 Kotlin 構建一個 Spring 應用程序。
首先,我個人喜歡將項目分為三個主要包:
- “core”包,包含與核心業務相關的組件。
- “ ports ”包,包含將業務核心與外界通信的輸入和輸出組件。
- “ config ” 包,用于啟動應用程序和處理其內部行為所需的所有配置。
構建核心
放置我們的Article實體。請注意,它使用普通的 Kotlin(或 JAVA),但完美地代表了業務實體。
package com.github.manerajona.blog.coreimport java.time.LocalDateTimetypealias ArticleId = Longdata class Article( val id: ArticleId?, var title: String, var headline: String, var content: String, val addedAt: LocalDateTime?)
其他包括:
- ArticleRepository接口,它允許業務核心與外部服務進行通信。
- ArticleService接口,它允許外部應用程序與業務核心進行通信。在usecase包中,ArticleServiceImpl 類 擴展了ArticleService并包含實際的業務邏輯。
數據庫適配器的輸出端口
ports/output/jpa包包含將數據持久保存到數據庫中的組件。
包含:
- 基于core實體的ArticleJpa類。
- 從 Spring JPA 庫擴展JpaRepository的ArticleJpaRepository類。
- ArticleDao類擴展了ArticleRepository,允許業務核心獲取和持久化數據。
REST 適配器的輸入端口
最后,ports/inputs/rs包包含 Rest Controller,暴露端點以供外部應用程序使用。
為什么架構很重要?
設計軟件時存在一組基本要求,稱為服務質量要求。這些要求定義了我們在構建高質量軟件的過程中必須解決的一些權衡問題,例如可伸縮性、可靠性、可維護性、可測試性和可部署性。
架構很重要,因為如果我們在選擇時足夠明智,那么適合我們項目的架構模式將幫助我們的軟件達到預期的質量,并且也許可以讓我們免去一些麻煩。
示例代碼可在GitHub上找到。