RaySin on GitHub

從 MVC 到六角形架構


回顧mvc、介紹MVC在現代後端開發中的常見困境及說明六角形架構如何解決這些問題

回顧經典 MVC

在經典的 MVC 模式中,三個元件的職責是:

  • Model (模型)

    代表資料和業務邏輯。負責與資料庫互動,並提供資料給 View。

  • View (視圖)

    使用者介面。在傳統 Web 應用中,它負責將 Model 的資料渲染成 HTML。

  • Controller (控制器)

    接收使用者的 HTTP 請求,呼叫 Model 來更新狀態,並選擇一個 View 來產生回應。

MVC 在現代後端開發中的常見困境

隨著業務變複雜,許多遵循 MVC 模式的專案會不自覺地陷入以下困境:

  1. 臃腫的控制器 (Fat Controllers)

    大量的業務邏輯,因為無處安放,最終都被塞進了 Controller 的方法中。Controller 不僅要處理 HTTP 請求和回應,還要負責資料驗證、流程編排、呼叫多個 Model。這使得 Controller 變得極其臃腫,難以測試和維護。當 Controller 變得過於龐大時,任何小的需求變動都可能牽一髮動全身,導致維護成本大幅提升。

  2. 貧血的模型 (Anemic Models)

    與此同時,Model 逐漸退化成一個只有 Getters/Setters 的「資料袋」,所有的業務邏輯都被抽離到 Controller 或某些 Service 層中,完全違背了物件導向中「資料與操作相結合」的初衷。這種設計讓 Model 失去了主動性,導致業務規則分散在各處,降低了程式碼的可讀性與一致性。

  3. 以資料庫為中心

    在許多 MVC 框架中(特別是 ActiveRecord 風格的),Model 與資料庫的表結構是緊緊綁定的。這導致整個應用的設計都圍繞著資料庫 schema 展開,業務邏輯隱性地依賴於資料庫的實作細節。這使得「脫離資料庫來測試業務邏輯」變得異常困難。當我們想要替換資料庫或進行單元測試時,往往會發現業務邏輯與資料存取層糾纏不清。

六角形架構如何解決這些問題

我們的專案所採用的六角形架構,正是為了解決上述問題而設計的。

  • 針對臃腫的控制器

    我們的 Controller 極其輕薄。它的唯一職責是「翻譯」HTTP 請求,然後委派給 Usecase。所有的業務流程都在 Usecase 中,職責清晰。這樣的設計讓 Controller 易於維護與測試,並且能專注於協調請求與回應。

  • 針對貧血的模型

    我們的 Domain 層是「充血」的。User 物件不僅有資料,更有保護其內部一致性的驗證邏輯和業務方法。它是應用程式中真正「聰明」的部分。這種設計讓業務規則集中於 Domain 物件,提升了程式碼的可讀性、可維護性與一致性。

  • 針對以資料庫為中心

    這是兩者最本質的區別。在我們的架構中,業務領域(Domain)才是宇宙的中心,而不是資料庫。資料庫只是一個可以被隨時替換的「基礎設施」,是一個被動實現了 Repository 介面的「Adapter」。依賴倒轉原則確保了我們的核心業務邏輯對 GORM、對 MySQL 一無所知。這讓我們能夠輕鬆地替換資料存取技術,或在測試時使用記憶體資料庫模擬,極大提升了系統的彈性與可測試性。

思考的轉變:從「分層」到「內外之分」

從 MVC 到六角形架構,最核心的是思維模式的轉變:

  • MVC 的心智模型是「水平分層」

    • UI 層 -> 業務層 -> 資料層。
    • 資料流從上到下,像一個三層蛋糕。
    • 這種分層方式雖然直觀,但容易讓業務邏輯與技術細節混雜,導致層與層之間的界線模糊。
  • 六角形架構的心智模型是「內外之分」

    • 核心是「內部」(Domain, Usecase),其他一切(HTTP, Database, Redis, …)都是「外部」。
    • 依賴的箭頭永遠從「外部」指向「內部」。
    • 這種設計強調「業務邏輯」與「技術細節」的徹底分離,讓核心邏輯不受外部變動影響。

參考


Similar Posts

Comments

Translator
Google AdSense
BloggerAds