模組六|工程文化與收斂(Day 27–30)
遷移完成之後,API 層累積了一批「可能沒人用」的函式。
大家都知道它們在那裡。也大概知道哪幾支應該可以刪。但沒有人刪。
不是因為懶,是因為 Day 4 講過的那個問題:你沒辦法證明沒人用。
而這件事的解法,我認為是這個系列裡最值得抄的一段工程實踐:把「刪除」當成一個需要工具支撐的問題,而不是需要勇氣的問題。
團隊為 API 層寫了一組腳本:
| 腳本 | 做什麼 |
|---|---|
| 分析使用狀況 | 掃出每一支 API 被哪些檔案引用 |
| 找出可安全刪除的 | 本篇重點 |
| 執行刪除 | 分批移除 |
| 重構單一 API 檔 | 依規範重排 |
| 重組模組 | 調整檔案劃分 |
| 冒煙測試 | 驗證改完之後結構仍然正確 |
六個腳本裡,第二個是整組的核心。因為「找得出來」比「刪得掉」難得多。
那支腳本的輸出標題,一字不差寫著:
=== Safe to delete (unused + no permission binding) ===
兩個條件:沒有被引用,而且沒有綁定權限。
第一個很直觀。第二個才是這組腳本裡最聰明的地方。

Day 18 講過:這個系統的權限碼就是 API 路徑字串。
所以一支 API 的路徑,可能同時出現在兩個地方:
而第二種完全不會出現在前端的搜尋結果裡。
想像一下這個災難:
你搜尋了整個前端專案,確認某支 API 沒有任何一行程式碼在呼叫它。
於是你刪掉它。但那支 API 的路徑,是後台某個角色權限的一個項目。
刪掉之後,權限設定畫面上那一列變成空白,或者更糟,權限判斷開始回傳未定義。
這條檢查的價值不在技術,在於有人意識到「引用」不只發生在程式碼裡。
「沒人用」這件事,要看的不只是你的搜尋範圍,是「這個東西可能被誰引用」的完整清單。
而這份清單通常不在程式碼裡,在你對系統的理解裡,所以它必須被寫進腳本,否則下一個人不會知道要檢查這一項。
分析腳本用了兩種比對方式:
new RegExp(`\\b${name}\\b`) // 一般的引用
new RegExp(`['"]${name}['"]`) // 被寫成字串的引用
第二條在防什麼?動態呼叫。
如果某處寫的是 apiMap['getOrderList'] 而不是 getOrderList(...),只用一般的識別字比對是抓得到的(因為字串裡也有那個名字),但如果組法更動態一點就會漏。
這正是 Day 4 我提出的那個疑問:「如果有人寫成 this['baseUrl'] 呢」。當時我沒有答案,這裡他們給了一個:把字串形式也列進比對。
不完美(真正動態拼接的名稱還是抓不到),但它把最常見的那一種涵蓋了。

這是我最想講的一段,因為它把 Day 15 的一個遺憾補上了。
Day 15 我說過:
命名規範寫在文件裡擋不住人,要能自動檢查才擋得住。
而那份 235 行的 API 對照表,訂了很多規範:每個模組內要依「查詢 → 修改 → 新增 → 刪除」排序、同類別內按字母序、檔案索引要跟實際檔案對得上。
這些規範後來被寫成了檢查項。
那支冒煙測試腳本驗的東西包括:
Api.XXX 引用真的存在第五、六項就是把文件裡的排序規範,變成會噴錯的東西。
這個轉變的意義很大:
文件是「希望大家這樣做」,檢查是「不這樣做就過不了」。
而且它讓那份 235 行的對照表不會說謊:Day 15 我擔心的「如果有人加了 API 沒更新文件,這份文件就開始說謊」,這支腳本正好防的是這件事。
有了「找得出來」的能力之後,剩下的是執行紀律。我們的做法:
一、一次刪一個模組。 不要一口氣清空。因為如果出事,你要能快速判斷是哪一批造成的。
二、獨立的改動,訊息寫清楚刪了什麼。 這樣還原的時候只要退一步。
三、刪除的東西要留下記錄。 這是 Day 15 講過的:改名的東西還找得到,刪掉的東西沒有痕跡。所以那份對照表裡有一區專門記「這些 API 被移除了」。
四、刪完跑一次冒煙測試。 確認結構仍然完整。
跑分析腳本的過程中,會撈出一些原本不是目標的東西:
這些都不是「沒人用」,但都是問題。
這是量化工具常見的副作用:你為了回答 A 問題而收集資料,結果順便看到了 B。 Day 2 那個「最長 = 最常改」的交叉比對也是這樣來的。
一、六個腳本本身也是要維護的程式碼。 如果 API 檔案的寫法慣例改了,這些腳本就要跟著改。它們現在是專案的一部分,不是一次性的工具。
二、「安全」的定義是專案特有的,不能照抄。 我們的第二條件是「沒有綁權限」,那是因為這個系統的權限碼剛好是 API 路徑。你的專案可能是別的東西:可能是排程設定、可能是外部系統的呼叫、可能是某份 Excel 巨集。
所以真正該抄的不是那兩個條件,是「先列出這個東西可能被誰引用」這個動作。
三、自動化會讓人過度信任。 腳本說「安全」,不代表真的安全,它只代表通過了我們想到的那幾項檢查。Day 14 講的第三個條件(問業務、注意一年只跑一次的功能)沒有辦法被腳本涵蓋。
而工具的存在,反而會讓人跳過那一步。
明天 Day 29 是倒數第二篇,講一個貫穿整個系列的問題:什麼時候該把兩個東西合併成共用的?
我會給一個我們實際走過的兩階段流程:先刻意寫兩份,隔了幾個月,確認它們真的一樣,才合併。