每間開業夠久的畫室,角落總會堆著幾個舊畫架
它們曾經很重要——某一年、某一種畫法,天天用到它
後來畫法換了,新畫架進來,舊畫架就被推到角落,沒有人再碰,也沒有人動手把它搬走
每個新來的學徒都會多問一句:「這個還要用嗎?」
它佔著空間,落滿灰塵,沒有人答得出來,於是它就一直留在那裡
會員狀態判斷邏輯裡,藏著這樣一段程式碼:
public class MemberStatusService
{
private const bool EnableExtraCheck = false;
public string GetMemberStatus(Customer customer)
{
if (EnableExtraCheck)
{
// 2019 年上線的風控規則,後來政策調整就沒再啟用
if (customer.RiskScore > 80)
{
return "受限";
}
}
if (customer.Tier == CustomerTier.Vip)
{
return "VIP";
}
return "一般會員";
}
private string CalculateLegacyStatus(Customer customer)
{
// 改版前的舊會員等級判斷,現在已經沒有任何地方呼叫
if (customer.TotalSpend > 100000)
{
return "白金";
}
if (customer.TotalSpend > 50000)
{
return "黃金";
}
return "一般";
}
}
EnableExtraCheck 永遠是 false,那段風控判斷,實際上從來不會被執行
CalculateLegacyStatus 是一個 private 方法,整個專案裡,沒有任何一行程式碼呼叫它
新加入的工程師,第一次讀到這個類別,通常會先卡在那段 if (EnableExtraCheck):
RiskScore 這個欄位,是不是還有人在維護?」CalculateLegacyStatus 沒人呼叫,但它看起來邏輯挺完整的,是不是哪裡漏接了?」沒有人有把握回答,只好把這兩段一起讀完、一起理解、甚至一起小心翼翼地保留著
多花時間看懂根本不會執行的程式碼
舊畫架站在角落,看起來像是「隨時可以拿來用」,但其實它連顏料都乾了
留著它,不會讓畫室更有效率,只會讓每個路過的人,多想一秒「這個還要嗎?」
更麻煩的是,這段死掉的邏輯,還是會被一起編譯、一起被靜態分析工具掃描、一起佔用測試涵蓋率的分母
它製造的維護成本,是真實的,不是心理作用
無用的程式碼,唯一正確的處理方式,就是直接刪除:
public class MemberStatusService
{
public string GetMemberStatus(Customer customer)
{
return customer.Tier == CustomerTier.Vip ? "VIP" : "一般會員";
}
}
不是註解掉、不是留著「以防萬一以後要用」,是整段刪掉
刪掉之後,常見的兩個猶豫,其實都有現成的安全網:
git log、git blame 隨時可以找回來今天的兩個例子,剛好對應兩種最常見的成因:
EnableExtraCheck 這種旗標,上線時是合理的過渡手段,但一旦決定不啟用,忘了把相關程式碼一起清掉,它就變成了永遠不會執行、卻永遠留在原地的分支
CalculateLegacyStatus 是舊邏輯改版後,沒人記得回頭確認「這個方法還有沒有人在用」這兩種成因,都不是有人故意留下垃圾,是清理這一步,總是排在「先把新功能做完」後面,然後就被忘記了
明天我們看模組四最後一站:一種提早幫「以後可能會用到」買好裝備,結果那個「以後」始終沒有來的壞味道
猜測性通用(Speculative Generality)