iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
Modern Web

一個活了六年的 Vue 2 後台,升級到 Vue 3 的那兩年系列 第 21

Day 21|一個叫「表單項」的 hook,寫完之後零次使用

  • 分享至 

  • xImage
  •  

模組四|核心系統改寫(Day 17–21)

先給三個數字:

  • 舊系統的表單項標籤:2,435 次
  • 新系統的表單項標籤:2,842 次
  • 新系統業務頁面用 schema 化表單(寫一份設定物件,讓它生出整張表單)的次數:0

表格被收斂了: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 化的整套表單方案

兩堆的差別只有一個:

抽「具體的業務規則」→ 成功。
抽「通用的表單機制」→ 失敗。

這條線我覺得比「表單能不能 schema 化」這個問題本身有用得多。

為什麼

因為業務規則是重複的,表單結構不是。

「日期區間不能超過三個月」這條規則,在 37 個頁面裡是一模一樣的。抽出來之後,改規則只要改一次。

但「一個表單長什麼樣」在每個頁面都不同:欄位數不同、排版不同、驗證時機不同、欄位之間的連動不同。你抽的不是重複,是「看起來像重複」的東西。

Day 3 講過 DRY(Don't Repeat Yourself)的重點是「同一份知識不該存兩份」。業務規則是知識,表單排版不是。

通用表單方案的問題:介面隔離

那為什麼 schema 化的方案沒人用?

框架的方案很完整:你寫一個設定陣列,它幫你生出整個表單,連驗證、連動、非同步選項都處理好了。3,721 行的機制。

問題在於:要用它,你得先接受它的整組介面。

你買了一台家電,附了一支兩百個按鈕的遙控器。

它什麼都能做。但你實際上只按三個:開、關、調溫度。

而那三個按鈕,被埋在兩百個裡面。

更麻煩的是:有天你想做一件它沒設計到的事——遙控器上沒有那個按鈕,而且你打不開它。

這件事有個名字:介面隔離原則(ISP, Interface Segregation Principle),不要逼使用者依賴他用不到的東西。

而後台系統的表單,永遠會有那個「遙控器上沒有的按鈕」:

  • 選了 A 之後,B 的選項要重新去後端拿
  • 只有某種角色才顯示某個欄位
  • 日期區間上限三個月,但勾了匯出就放寬到一年

這些規則你可以硬塞進設定檔,但塞完之後那個設定檔會長出自己的語法,比手寫還難讀,而且只有寫的人看得懂。

但我們也抽錯了東西

筒裡已經有五支幾乎一樣的刷子,而我手上這支是第六支

不過帳不能只算框架的,我們自己也搞砸了一塊。

專案裡有五個名字高度相似的 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 就是例子。線畫得再好,沒有機制守著就會歪。

帶走什麼

  1. 抽「具體的業務規則」會成功,抽「通用的機制」通常失敗。 前者是真的重複,後者是「看起來像重複」。
  2. 判斷抽象該不該做,看它是不是同一份知識。 業務規則是知識,排版和結構不是。
  3. 完整但要求整組照收的方案,會輸給不完整但零成本接上的小東西。 這是 Day 20 的結論,在表單這裡再次成立。
  4. 抽象做完要回頭量使用率。 一個沒人用的共用元件,比重複的程式碼更糟,因為它會誤導下一個人以為那是慣例。
  5. 看到「同一件事的第三個變體」,就該停下來合併。 我們在第五個的時候才發現。

模組四到這裡結束:路由、權限、請求層、表格、表單,五個系統全部重新設計過。

明天開始模組五,換一個角度看重構——不是「怎麼做」,是「做的過程長什麼樣」。Day 22 從一個數字開始:舊系統的四份語言檔,加起來一萬五千行。


上一篇
Day 20|框架送你一台咖啡機,團隊自己買了三個濾杯
系列文
一個活了六年的 Vue 2 後台,升級到 Vue 3 的那兩年21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言