模組三|遷移執行法與驗收(Day 12–16)
我數了舊系統的 API 定義:566 個。
然後我數了它們的命名前綴:17 種。
光是「查詢」這一件事,就有五種寫法:get、query、load、find、select。
看到這張表的當下,我的第一個念頭是「這個一定要順手改掉」。而我最後沒有改。 今天講為什麼。
| 前綴 | 出現次數 |
|---|---|
update |
79 |
get |
61 |
query |
58 |
export |
14 |
add |
11 |
delete |
8 |
set |
7 |
check |
6 |
cancel |
5 |
load |
4 |
find / del |
各 3 |
edit / create |
各 2 |
select / refresh / modify |
各 1 |
把它按「語意」分組,問題就很清楚了:
get / query / load / find / select,共 5 種update / edit / modify / set,共 4 種delete / del,共 2 種add / create,共 2 種這不是「有人不會取名字」,是六年裡不同的人各自照自己的習慣寫,而中間沒有人統一。
每一個當下都合理。加起來就變成:新人要查一支 API,得先猜它可能叫什麼。
舊系統的 API 不是函式,是設定物件。長這樣:
const queryOrders = {
url: '/order/list',
method: 'get',
serviceName: 'service-a',
isDummy: false,
loading: true, // ← 這個
}
前面幾個欄位都合理,但最後那個 loading 是畫面的事:它在說「呼叫這支 API 的時候要不要顯示載入動畫」。
有 44 支 API 帶著這個欄位。也就是說,API 定義檔裡混進了 UI 決策。
這種混合當下很方便(不用在每個頁面各自處理 loading),但它讓「這支 API 是什麼」和「這支 API 在畫面上怎麼表現」綁死了。同一支 API 在 A 頁面要 loading、在 B 頁面不要,就沒辦法了。

因為遷移期最忌諱的就是同時改兩個變因。
想像一下這個場景:
你把某個頁面從舊系統搬到新系統,順手把它用到的 8 支 API 全部改名。
搬完之後,某個查詢功能壞了。
現在請問:是搬的時候邏輯搬錯了,還是改名的時候漏改了某一處?
你沒辦法只看畫面判斷。你得回頭把兩件事拆開來查,而這比一開始就不要合在一起做,貴得多。
Day 6 講過同一個原則(不要在遷移的同時搬動檔案位置),Day 10 也講過(不要在遷移的同時開啟嚴格型別檢查)。這是第三次出現:
遷移期的每一個「順手」,都是在把兩種失敗混在一起。
所以我們的順序是:先原樣搬過去,等這個模組穩定了、驗收過了,再統一改名。
改名這件事真正的產出,不是新的名字,是一份「舊名 → 新名」的對照文件。
我們的那份有 235 行,開頭第一句話寫著它是「唯一來源」。裡面長這樣:
| 模組 | 新的函式名 | 對應的路徑常數 | 實際路徑 |
|---|---|---|---|
| 登入認證 | getMenuIdList |
GetMenuIdList |
/manage/menu/get |
updatePassword |
UpdatePassword |
/manage/login/update |
三欄對照:函式名、常數名、實際路徑。
而且它訂了排序規範:每個模組內依「查詢 → 修改 → 新增 → 刪除 → 其他」排序,同類別內按字母序。

這是我後來才理解的一點。
一份 235 行的對照表,沒有人會坐下來從頭讀完。它的價值在別的地方:
一、它是驗收清單。 改名的時候,每一列都是一個「要確認有做到」的項目。沒有這張表,你不知道自己改到哪裡了。
二、它是搜尋的入口。 半年後有人問「舊系統那支撈訂單的 API 現在叫什麼」,答案在這裡,而不是在某個人的記憶裡。
三、它是「已刪除」的墓碑。 這點最容易被忽略——改名的東西還找得到,但刪掉的東西沒有痕跡。所以對照表裡必須有一區專門記「這些 API 被移除了,因為沒人用」。否則半年後有人翻遍全專案找不到某支 API,會以為是自己漏看。
誠實的部分。我數了新系統的命名前綴:
| 舊系統 | 新系統 | |
|---|---|---|
| 前綴種類 | 17 種 | 7 種 |
從 17 種收斂到 7 種,這是明顯的進步。但沒有收斂到「一種語意一個前綴」:
query(143 次)和 get(98 次)兩種並存delete(33 次)和 remove(1 次)add(37 次)和 create(3 次)後面兩組的少數派只有一到三個,是明顯的漏網之魚,規範訂了,但沒有機制擋住例外。
而 query 和 get 的並存不是漏,是沒有人決定哪一個才對。143 比 98,兩邊都太多了,任何一邊要統一過去都是大工程。
所以現況是:它從「猜不到」進步到「猜兩次會中」。 這是進步,但我不會說它解決了。
如果重來一次,我會在改名的當下多做一件事:把規範寫成可以自動檢查的規則(例如 lint 規則),而不是只寫在文件裡。因為文件擋不住下一個人,只有會噴錯的東西才擋得住。
一、「之後再改」有機率變成「永遠不改」。 我們算是有做到,但那是因為剛好有人推。如果當時沒有人接手這件事,那 566 個亂名字會原封不動活在新系統裡——而且因為新系統是「新的」,反而更沒有人會想去動它。
二、改名期間會有一段「新舊名字並存」的混亂。 改到一半的時候,有些檔案用新名、有些還是舊名。這段時間如果有人來問,你會需要解釋兩次。
三、對照表本身要有人維護。 它自稱「唯一來源」,但如果之後有人加了 API 沒有更新它,這份文件就開始說謊——而說謊的文件比沒有文件更糟。
loading: true 當下很方便,代價是這支 API 從此不能在不同頁面有不同的表現。明天 Day 16 是模組三的最後一天,講一個很少被寫進技術文章、但決定你半夜會不會被叫起來的東西:TEST、FAT、UAT 到底差在哪。我會給一組真實的漏斗數字:每 100 個在測試站被抓到的問題,只有 1 到 2 個會溜到正式環境。