整潔架構——那一條依賴規則
在一張互動畫布上呈現整潔架構:實體、使用案例、介面轉接器與框架,以及那條令核心保持獨立的依賴規則。
整潔架構把代碼組織成一圈圈同心的分層——實體、使用案例、介面轉接器、框架——並由一條規則統管:依賴永遠指向內,所以核心從不依賴任何工具。
整潔架構——那一條依賴規則
The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.
How to read this visual
- 由上而下讀左邊那一欄,那是四個分層,由最內的實體去到最外的框架。
- 然後由上而下讀右邊那一欄,那是統管它們的規則:依賴向內、轉接器居中、核心不被動到。
- 雖然箭頭是由左至右畫出來的,但它們在意義上是由外向內流動——每一個外層的代碼都依賴它裡面那一層。
四個分層
「實體——全企業層級的業務規則」是最內的一圈:不論應用程式以甚麼方式交付都依然存在的物件與規則——一個客戶、一張發票,以及一張發票不能被付款兩次這條規則。「使用案例——應用程式專屬的規則」為某一個應用場景編排實體。「介面轉接器——控制器、呈現器」在使用案例與外部世界之間翻譯,而「框架與驅動——UI、資料庫、網頁」則是工具那外面一圈。
依賴規則
「依賴一律指向內,永不向外」就是整套架構存在的唯一目的所要強制的那條規則:代碼層面的依賴永遠是向內跨越。「外層透過轉接器溝通,而不是直接對核心」則是機制——一個使用案例宣告一個用來儲存發票的介面,由資料庫轉接器去實作,所以那個使用案例從不匯入資料庫程式庫。
回報
「更換框架而不必觸碰核心」與「核心從不匯入任何框架」是用來檢驗那條規則有沒有被守住的:由一個資料庫或一個 UI 遷移到另一個,而實體與使用案例完全不用改。這就是全部的價值主張——最重要、最昂貴的那部分代碼,被隔絕於最容易被取代的那些東西之外。
Key relationships and takeaways
- 依賴永遠指向內——這一條規則就是這套架構本身。
- 核心宣告介面;外圈負責實作——轉接器就是那道接縫。
- 實體與使用案例在構造上就與框架無關。
- 回報就是可替換性:更換 UI、資料庫或網頁框架,都不必觸碰核心。
- 整潔架構講的是依賴方向,而不是分層的數目。
When to use this visual
- 在團隊為一個大型代碼庫定下結構之前,先向他們講解依賴規則。
- 覆核一套架構:一個匯入了 UI 或資料庫程式庫的使用案例就是違反規則,而這在畫布上看得見。
- 規劃一次重寫或遷移——畫布顯示哪些分層必須留下來,哪些可以被替換。
運作方式
把分層改名成你的技術堆疊
把那些通用的圈層名稱換成你真實的名稱——你的實體、你的使用案例類別、你的控制器與閘道,以及你實際用的 UI 與資料庫框架。
畫出介面的接縫
加上核心所宣告的那些介面,以及每一個由哪個轉接器實作,好讓這張圖記錄下依賴規則所跨越的那些接縫。
標出違規之處
為任何目前向外匯入的分層加上標籤或另一種圖形,並附註能夠修好它的那次重構——畫布同時兼作一次稽核。
示範一次真實的更換
加入一條分支,讓一個外層框架被另一個取代,而兩者都透過同一個轉接器連接,最後終結於那個沒有改變的核心。
常見問題
甚麼是整潔架構?
這是一種由 Robert C. Martin 推廣開來的架構模式,它把代碼組織成一圈圈同心的分層:中心是實體,然後是使用案例,再來是介面轉接器,最外緣是框架與驅動。它的統管規則是代碼層面的依賴永遠指向內,因此核心的業務規則從不依賴交付機制——UI、資料庫或者網頁框架。
甚麼是依賴規則?
依賴規則說的是:代碼層面的依賴必須永遠向內跨越;一個外層可以依賴一個內層,反過來則絕不可以。在實務上,內層宣告介面,外層負責實作,所以核心的代碼不會從邊緣的工具匯入任何東西。圖解把它畫成一個獨立的群組,因為這套架構其餘每一項特性都由它推導出來。
整潔架構與分層架構有甚麼分別?
分層架構同樣把職責分開,但它的依賴通常是由上而下流動——展示層呼叫服務層,服務層再呼叫資料層。整潔架構把這個方向倒轉:業務核心坐在中心,其餘一切都依賴它,所以依賴的方向才是兩者的分別所在。圖解中那個指向核心的箭頭,就是把這個分別畫了出來。
小型專案值得用整潔架構嗎?
並非總是值得——當業務規則簡單,或者團隊只得一個人時,這套繁複做法的成本高於它的回報。當業務邏輯複雜到必須比工具活得更久,或者 UI 與資料庫很可能會改變時,這個模式就物有所值。畫布上那幾個講回報的方框把這場交換說得很誠實:核心的安全,是用那些轉接層買回來的。
用 QueryChart(FlowJam)編輯這張圖解
把上面這張整潔架構畫布開啟為你自己的圖表——把分層改名成你代碼庫裡的分層,並把你的依賴畫出來。