架構守護代碼化:架構文檔即測試
架構守護代碼化,即使用易于閱讀和維護的領域特定語言,來描述軟件架構守護的規則,對諸如于分層架構、包訪問規則、包數量、繼承命名等進行限制。
PS:我們這里所說的代碼化,所指的是與領域特定語言的方式進行描述。
早先呢,我只是因為使用 Java 編寫的 ArchUnit 不支持其它語言,而在其它語言的生態里呢,也沒有這樣的合適的工具。所以呢,我就想著在 Uncode 里設計一個全新的架構守護工具,也就是 Inherd 開源小組里的 Guarding:https://github.com/inherd/guarding/,一個多語言的架構守護工具 —— 基于 Tree Sitter 解析各類編程語言。它設計了一套外部 DSL,其借鑒于 ArchUnit 設計的內部 DSL 語法。
架構的腐化:為什么我們需要架構守護?
觀察軟件架構在開發過程中的變化, 是一件非常有意思的事情。日常,我經常與中大型規模公司的架構師、技術負責人聊天,討論一些關于架構和規范相關的問題,也是頗有意思的。當我們聊到架構的時候,從聊天的過程來看,都是頗為美好的。但是呢,打開代碼庫,看到代碼的分層實現、代碼的一些規范,我們就會發現結果并非如此。
美好的開始。系統在設計的初期,架構師們都根據了自己的能力和經驗,對系統進行了快速的“精心”的設計。隨后,在迭代的開發中,按自己新捕獲到的知識,對系統進行一些調整。如果這些資深的架構師都在編碼(間歇性的),又或者是經常性的打開代碼庫瞧一瞧。那么,自然而然地系統不會出現過大的偏差。所以,我堅信對于有一定規模的軟件組織來說,他們對系統都是有著良好的設計。
腐化的架構。系統在中后期開發的過程中,先前的架構師缺乏對于架構的關注,又或者是經歷了一些人員的變更,導致了系統出現了一處又一處的架構不一致。當然,其中還有一類典型的原因是,架構相關的文檔和規范缺乏了維護。由于這一系列的種種原因,使得我們看到的系統架構與這些架構師原先的預期是不一致的。
基于上述的種種原因,在架構上實施守護便成為諸多架構師要考慮的問題。
為什么需要架構守護代碼化?
程序員討論寫文檔,也討厭別人沒寫文檔。
對于架構知識的記載、傳播和轉換,也是知識傳遞的范疇。從當前階段來看,它存在以下幾個不同的級別:
- 系統本身沒有架構文檔,文檔存在于人們的腦海里。
- 系統存在架構文檔,難以理解(沒有架構圖)。
- 系統存在架構文檔,只在早期創建,但與實際架構不一致。
- 系統的架構文檔持續更新,但是未能及時反應問題。
- 系統的架構文檔持續更新,并使用了架構守護,以確保兩者的一致性。
- 系統的架構文檔即系統的架構守護測試。
上述的幾點,我想不論是開發者,還是架構師都是深有體會的。
文檔化的架構,需要閱讀和牢記
在架構設計初期,開發人員對于架構的設計往往都是經歷過激勵的討論。所以,每個人對于架構的形態都掌握得差不多,不需要過多的記錄也能知曉設計。沉淀下來的文案往往只是一些決策的結果,缺乏過程式的討論等。
因為這一種種原因,所以在過去的幾年里,我們一直在推崇『架構決策記錄』(ADR),記錄每一項架構上下文、決策和結果等相關的信息。
架構測試的局限性
這是一個老生常談的問題,所以諸如于在 Java 世界里,人們設計出了 ArchUnit 這樣在的工具來守護系統的架構。架構測試作為架構的文檔,缺少易讀性等等的問題。為了在多個項目中使用,還需要大量地復制和粘貼。
PS:在早期,我也嘗試為 JavaScript / TypeScript 世界,設計類似的架構守護工具(即 dilay),但前端世界對于這一類的需要并不迫切。多年后,我又設計了一個新的工具,只是它已經適用于多個語言和框架。
架構守護即代碼:架構文檔即測試
架構守護代碼化,即使用易于閱讀和維護的領域特定語言,來描述軟件架構守護的規則,對諸如于分層架構、包訪問規則、包數量、繼承命名等進行限制。
架構守護 DSL 示例
一個好的架構文檔是個測試,并且可以執行。如 ArchUnit 設計的內部 DSL 語法:
- classes().that().haveSimpleNameStartingWith("Foo")
- .should().resideInAPackage("com.foo")
這句話里,描述了一個規則: Foo 開頭的類應該放在 com.foo 包下。這也是我們在設計架構的時候,會設計的架構文檔。如果我們把它翻譯成英語的話,它應該就是:
- class(startsWith "Foo")) resideIn "com.foo"
另外一種潛在的形式可以是:
- (startsWith "Foo").class resideIn "com.foo"
從實現難度上來說,兩者的差別并不大,但是顯然前者更易于理解和編寫。以此類推,我們可以繼續設計一系列的規則。
其它
歡迎加入 Inherd Guarding 架構測試與守護。
GitHub: https://github.com/inherd/guarding 。
本文轉載自微信公眾號「phodal」,可以通過以下二維碼關注。轉載本文請聯系phodal公眾號。