「依賴要往內指,不能反向依賴」「不要為了假設性的需求先建抽象層」——這些話,只要當過幾年 tech lead,大概都講過不只一次。問題是,講過的規則,在下一次 code review 之前,很容易就被忘記,尤其當生成程式碼的是一個幾秒鐘就能寫出幾百行的 AI,人審查的節奏根本來不及在每一次產出後,重新覆誦一次這些口頭規則。
今天要處理的問題很具體:能不能把「不要過度設計」這句話,寫成一段程式碼,讓它在 CI 裡自動跑、自動擋,而不是只存在於 code review 時某個人的記憶裡?
一般測試(單元測試、驗收測試)問的問題是「輸入 X 會不會得到輸出 Y」。架構測試問的是完全不同維度的問題:「這個類別有沒有依賴到它不該依賴的東西」「這個資料夾底下的類別,有沒有超過我允許的抽象層數」「有沒有出現我明確禁止的 pattern(例如某種被團隊判定為過度設計高風險的裝飾器鏈)」。
這類工具在不同語言生態都有對應的實作,例如 Java 生態常見的 ArchUnit,PHP 生態也有像 phpunit-architecture-test 這類概念相近的工具——但我要在這裡先坦白一件事:這篇文章不打算示範任何一個工具的具體語法,因為我沒有把握能精準複述每個工具版本之間的 API 細節,與其寫出可能過時或錯誤的程式碼騙你「照抄就對了」,不如把這件事講在概念層次:架構測試工具的共同能力,是讓你用程式碼表達「這個模組不能依賴那個模組」「這一層不能超過幾層」這類結構性規則,然後像跑單元測試一樣把它放進 CI,違反規則就讓 build 失敗。
回頭看這個系列案例裡過度設計版本的兩個具體問題:
SqliteUnitOfWork 的 begin()/commit()/rollback() 全部是 no-op,名字承諾了交易保護,實際上什麼都沒做RetryingArticleRepositoryDecorator 宣告 MAX_ATTEMPTS = 3,但邏輯裡沒有迴圈、沒有真的重試這兩個問題,靠人眼 review 是抓得到的——只要你剛好打開那個檔案、剛好仔細讀了實作內容。但在 745 個檔案的規模下,「剛好打開那個檔案」這件事本身就是碰運氣。架構測試沒辦法直接檢查「這個方法的實作是不是名不符實」(這仍然需要人的判斷),但它可以檢查更前置的結構性問題:例如「裝飾器類別數量超過某個上限就擋下來」「某個目錄底下不能出現超過 N 層的介面繼承」——把「這個系統的抽象層是不是已經失控」這個問題,變成一條 CI 規則,而不是留給 reviewer 憑印象判斷「感覺有點多」。
這正是這個系列主題句要落地的地方:AI 沒有發明過度設計,它只是讓過度設計的速度追上了你按下 Enter 的速度;Review 要跟得上,審的就不能再是程式碼本身,而是產生程式碼的規則。 架構測試就是把這句話裡「規則」兩個字,變成一段真的會執行的程式碼。
架構測試容易被誤用的地方,是有人會期待它能檢查「這個設計合不合理」這種需要人類判斷力的問題。它做不到,也不該被要求做到。它能做的,是結構性、可窮舉的規則——依賴方向、層數、命名慣例、禁止的 pattern;做不到的,是語意層次的判斷——例如「這個 UnitOfWork 有沒有真的做到交易保護」,這仍然需要人讀程式碼、或搭配整合測試去驗證行為。
❌ 常見誤解:以為架構測試能取代所有人工判斷
「我們裝了架構測試,以後就不用 review 設計了」
✅ 正確定位:架構測試負責結構性規則,人負責語意判斷,兩者互補
架構測試擋下:
- Domain 層依賴到 Infrastructure 層的具體實作
- 裝飾器鏈超過團隊約定的層數上限
- 出現團隊明確列為「過度設計高風險」的 pattern(例如未使用的 CQRS Bus)
人工判斷仍然負責:
- 這個抽象層存在的理由是否成立
- 這個實作有沒有名不符實(像 no-op 的 UnitOfWork)
這篇要講清楚的分層是:「用可執行的規則取代口頭約定」這件事是語言無關的原則,換成 Java、TypeScript、Python 一樣適用;但具體工具(ArchUnit、phpunit-architecture-test 或其他生態的等效工具)是各自語言生態的實現方式,工具選擇跟語法細節不是這篇文章的重點,重點是「你的團隊有沒有至少一條這樣的規則存在」。
如果你現在打開自己專案的 CI 設定,有沒有任何一條規則是在檢查「依賴方向」或「抽象層數」,而不是只有單元測試跟 lint?如果沒有,你覺得最值得優先寫成架構測試的第一條規則會是什麼?
Day 20 會給出一個更具體、更好量化的規則:複雜度預算——新增一個欄位,改動檔案數到底該有多少上限,用這個系列案例裡真實量測過的數字當基準。
我以前對「架構測試」這種東西是有點抗拒的,總覺得「這不就是又多一種要維護的測試」,多一份負擔。這幾年看著 AI 產出程式碼的速度越來越快之後,我的想法徹底改變了——口頭講過的規則,人會忘,AI 更不會主動遵守,只有寫成會自動執行的檢查,才是真的存在的規則。這聽起來有點無情,好像在說「不能相信任何人(或任何 AI)會自己記得」,但老實說,這幾年帶團隊的經驗告訴我,這句話大部分時候是對的,不是悲觀,是務實。