模組四|核心系統改寫(Day 17–21)
先給三個數字:
表格被收斂了:Day 20 講過,162 個表格頁面的重複最後收攏進三個自己寫的 hook(抽出來共用的邏輯函式),用了 149 次。表單一次都沒有,標籤數甚至還變多。
我原本以為這是「還沒做」。實際去翻之後發現不是。團隊寫了十幾個表單相關的 hook,只是它們不長那個樣子。
而這批 hook 的成敗,是兩極的。
結論先講:抽「具體的業務規則」的 hook 全被大量採用,抽「通用表單機制」的全數陣亡——分界線不在表單能不能 schema 化,在你抽的是不是同一份知識。
我把團隊自寫的表單相關 hook 拉出來數使用量:
| hook 在做什麼 | 使用次數 | 涵蓋頁面 |
|---|---|---|
| 查詢日期區間的限制規則 | 115 | 37 |
| 查詢條件的組裝 | 76 | 19 |
| 幣別處理 | 74 | 10 |
| 關鍵字搜尋 | 16 | 5 |
| 圖片上傳 | 3 | 1 |
| 單一日期時間區間 | 3 | 1 |
| 表單項 | 0 | 0 |
最後一行是重點。
有人寫了一個叫「表單項」的 hook,然後沒有任何一個頁面用它。

把上面那張表按「成功」和「失敗」分開,形狀非常清楚:
被大量採用的(115 / 76 / 74 次)
沒人用或近乎沒人用的(0 / 3 次)
兩堆的差別只有一個:
抽「具體的業務規則」→ 成功。
抽「通用的表單機制」→ 失敗。
這條線我覺得比「表單能不能 schema 化」這個問題本身有用得多。
因為業務規則是重複的,表單結構不是。
「日期區間不能超過三個月」這條規則,在 37 個頁面裡是一模一樣的。抽出來之後,改規則只要改一次。
但「一個表單長什麼樣」在每個頁面都不同:欄位數不同、排版不同、驗證時機不同、欄位之間的連動不同。你抽的不是重複,是「看起來像重複」的東西。
Day 3 講過 DRY(Don't Repeat Yourself)的重點是「同一份知識不該存兩份」。業務規則是知識,表單排版不是。
那為什麼 schema 化的方案沒人用?
框架的方案很完整:你寫一個設定陣列,它幫你生出整個表單,連驗證、連動、非同步選項都處理好了。3,721 行的機制。
問題在於:要用它,你得先接受它的整組介面。
你買了一台家電,附了一支兩百個按鈕的遙控器。
它什麼都能做。但你實際上只按三個:開、關、調溫度。
而那三個按鈕,被埋在兩百個裡面。
更麻煩的是:有天你想做一件它沒設計到的事——遙控器上沒有那個按鈕,而且你打不開它。
這件事有個名字:介面隔離原則(ISP, Interface Segregation Principle),不要逼使用者依賴他用不到的東西。
而後台系統的表單,永遠會有那個「遙控器上沒有的按鈕」:
這些規則你可以硬塞進設定檔,但塞完之後那個設定檔會長出自己的語法,比手寫還難讀,而且只有寫的人看得懂。

不過帳不能只算框架的,我們自己也搞砸了一塊。
專案裡有五個名字高度相似的 hook,都在做「檢查某個輸入的值是否有效」:
| 行數 | 使用頁面 | |
|---|---|---|
| 精確檢查 A | 90 | 0 |
| 精確檢查 B | 79 | 0 |
| 模糊檢查 B | 87 | 1 |
| 模糊檢查 C | 85 | 1 |
| 驗證並取得 B | 55 | 1 |
396 行,五個 hook,總共用在三個頁面。其中兩個完全沒人用。
這是很典型的一種失敗:同一件事被抽了五次,每次都為了一個特定場景,然後每一個都只服務那一個場景。
它跟前面講的「抽業務規則會成功」不衝突,因為這五個抽的確實是業務規則。問題在於:它們是同一條規則的五個變體,而沒有人把它們合併。
正確的做法應該是一個 hook 加上參數(檢查什麼、精確還是模糊)。而現在的狀態是:下一個人要寫第六個。
這正是 Day 4 那個「11 個全域,8 個沒人用」的翻版,只是換到了 hook 層。新專案也才兩年多。
我在 Day 9 寫過一句話:「這可能只是『還沒想到更好的做法』的體面說法。」
寫完這篇之後,我的答案是:兩者都有。
是刻意取捨的部分:不做 schema 化,這個判斷我到現在還是認為對的。那 3,721 行的方案我們用不上,而抽業務規則的那三個 hook(115、76、74 次)證明了「抽對地方」是有效的。
是藉口的部分:那五個沒被合併的檢查 hook,和那個零次使用的「表單項」hook。它們代表我們知道要抽象,但抽的位置是憑感覺,而且抽完之後,沒有人回頭檢查它有沒有被採用。
第二點才是真正的問題。寫一個 hook 是十分鐘的事,而確認它有沒有用是永遠沒有人做的事。
如果重來,我會加一個很土的習慣:每季跑一次「共用元件與 hook 的使用次數」。零次的就刪掉,一次的就問「那它為什麼要在共用目錄」。
一、表單的重複度沒有下降。 2,842 個標籤是事實。每次新增一個查詢頁,還是要手寫十幾個欄位。我不會說這是勝利,只會說我們選擇了付這個成本,來換「不必發明一種設定語言」。
二、我們累積了一批沒人用的 hook。 而它們跟舊系統那些沒人用的全域掛載,難刪的原因一模一樣——你要先證明沒人用。
三、「抽業務規則」這條線也會鬆掉。 那五個檢查 hook 就是例子。線畫得再好,沒有機制守著就會歪。
模組四到這裡結束:路由、權限、請求層、表格、表單,五個系統全部重新設計過。
明天開始模組五,換一個角度看重構——不是「怎麼做」,是「做的過程長什麼樣」。Day 22 從一個數字開始:舊系統的四份語言檔,加起來一萬五千行。