測試與程式碼品質

為什麼舊程式碼總是被嫌棄(開發者都能感同身受的故事)

我至今仍清楚記得新公司第一天上班時,拿到儲存庫並首次開啟程式碼的那一刻。

閱讀 3 分鐘
為什麼舊程式碼總是被嫌棄(開發者都能感同身受的故事) 封面圖

我至今仍清楚記得新公司第一天上班時,拿到儲存庫並首次開啟程式碼的那一刻。

一個 3,000 行的檔案裡,各種邏輯糾結在一起。我不禁嘆了口氣。

「到底是誰寫成這樣的……」

但幾個月後,新人看著我寫的程式碼,也露出了完全相同的表情。那時我才明白,舊程式碼不是某一個人的錯。

先說結論。

舊程式碼之所以挨罵,不是因為程式碼很差,而是因為撰寫當時的脈絡已經消失了。

今天想分享我的經驗:為什麼舊程式碼總會成為責怪的對象,以及面對它時如何少受點傷。


什麼是舊程式碼?和老舊的程式碼不同嗎

先釐清一點:舊程式碼不只是「老舊的程式碼」。

依我的經驗,標準只有一個:因為沒有測試而不敢修改的程式碼

Michael Feathers 在《修改舊程式碼的藝術》中將舊程式碼定義為「沒有測試的程式碼」。即使只寫好一週,只要因為沒有測試、每次修改都讓人提心吊膽,那就是舊程式碼。

反過來說,就算是 10 年前的程式碼,只要測試完整,也能放心修改。

所以問題不在年齡,而在於你是否確信「改這裡不會讓其他地方爆掉」。


為什麼舊程式碼總是被嫌棄

整理原因後,大致有三個。

1. 撰寫程式碼的人已不在公司

沒有人可以詢問當初為什麼要這樣寫。沒有註解或文件時,剩下的只有程式碼和我的想像力。

2. 脈絡消失了

糾結得不合常理的程式碼,通常都有它的故事:緊迫的期限、奇怪的需求,或是為了避開特定 OS 版本的錯誤。

當時可能是最佳解,但那些背景不會留在程式碼裡。留下的只有結果,所以現在看來便難以理解。

3. 別人的程式碼本來就看起來很奇怪

老實說,這是最主要的原因。自己的程式碼,流程都在腦中;別人的程式碼,卻得從頭追流程。

那份煩躁最後就會變成「為什麼要這樣寫」。

來看看下面的程式碼。乍看之下,不知道為什麼有這個條件,是很典型的舊程式碼痕跡。

// 沒有人知道為什麼要扣除 30
if user.type == "B" && amount > 0 {
    finalPrice = amount - 30 // 2019年促銷活動的殘留?
}

無從得知這個- 30現在是否仍有必要,或只是舊活動留下的痕跡。這樣的一行行程式碼累積起來,就成了舊程式碼。


那麼,該如何面對舊程式碼

面對陌生的舊程式碼,很容易想著「全部重寫吧」,但其實有更好的方法。

我現在遵守三個原則。

  1. 不要隨便重寫 — 能運作的程式碼裡,融入了多年累積的各種錯誤處理。重新撰寫,就得從頭再踩一次。
  2. 修改前先補測試 — 用測試固定目前的行為,修改後哪裡壞掉就能立即看見。
  3. 留下修改原因的痕跡 — 把理由寫在提交訊息或註解裡,至少能讓下一個人少一點怨念。

尤其第三點很重要。這是唯一能避免把我現在的煩躁傳給未來某個人的方法。


說到底,今天的新程式碼也是明天的舊程式碼

我花了 6 個月才明白一件有點空虛的事:現在用心寫的程式碼,幾年後也會成為被某人嫌棄的舊程式碼。

接受這點後,我反而放鬆了。不再執著於完美,而是轉向替下一個人少留一點麻煩

如果你現在正對著陌生的舊程式碼嘆氣,請偶爾想起,寫下它的人當天也已經盡了最大的努力。然後安靜地先補上測試吧。這似乎是彼此都少受傷的方式。