改變程式碼是軟體開發者的日常,但有些改法讓事情更困難,有些則讓事情更容易。要深入理解如何處理棘手的程式碼,我們必須先了解改變的機制

改變軟體的四個理由#

軟體變更可以歸納為四種主要動機:

  1. 新增功能(Adding a Feature)
  2. 修復 Bug(Fixing a Bug)
  3. 改善設計(Improving the Design)
  4. 優化資源使用(Optimizing Resource Usage)

新增功能與修復 Bug#

新增功能看似最直觀的變更類型——軟體目前以某種方式運作,使用者希望它做更多事。但「新增功能」和「修復 Bug」之間的界線往往模糊不清。

行為(Behavior)是軟體最重要的特質。 使用者依賴既有行為運作。當我們新增行為時,使用者樂見其成;但若我們改變或移除他們依賴的行為(引入 Bug),他們就會失去信任。

從技術角度來看,真正重要的區分不是「功能」或「Bug」,而是:

  • 新增行為:只增加程式碼,不修改既有邏輯
  • 改變既有行為:修改現有程式碼的運作方式

幾乎不可能在新增行為的同時完全不改變任何既有行為——即使只是 UI 上多了一個按鈕,也會讓畫面渲染有微妙的不同。

改善設計(重構)#

重構(Refactoring) 是在不改變行為的前提下,改善軟體結構的行為。其核心理念是:透過撰寫測試來確保既有行為不變,然後進行一系列小型的結構性修改,讓程式碼更易於維護。

重構與一般的「程式碼整理」不同:

  • 不是低風險的格式調整或原始碼重新排版
  • 而是有測試保護的小步驟結構調整
  • 從變更的角度看,不應引入任何功能變化(雖然結構改變可能影響效能)

優化#

優化與重構非常相似——兩者都保持功能不變,只改變其他面向。差異在於:

  • 重構改變的是程式結構,目標是更易維護
  • 優化改變的是資源使用方式,目標是降低時間或記憶體消耗

整體比較#

系統中有三個維度可能因變更而改變:結構功能資源使用

新增功能修復 Bug重構優化
結構改變改變改變
新功能改變
既有功能改變
資源使用改變

無論哪種變更類型,保留既有行為始終是最大的挑戰。即使是改變主要功能時,仍有大量既有行為必須保持不變。

Figure 1.1: Preserving behavior

風險變更#

保留既有行為是一項艱鉅的挑戰。每次變更都伴隨著風險,我們需要回答三個關鍵問題:

  1. 我們需要做哪些改變?
  2. 如何確認改變是正確的?
  3. 如何確認沒有破壞其他東西?

保守策略的代價#

大多數團隊用保守的方式管理風險:最小化變更數量、遵循「沒壞就別修」的原則。但迴避改變有嚴重的後果:

  • 程式碼膨脹:避免建立新類別和方法,導致既有程式碼越長越難理解
  • 技能生鏽:不常做的事會越做越不順,拆解大型類別這類技能需要持續練習
  • 恐懼蔓延:團隊對改變的恐懼會與日俱增,直到學會更好的技術才能消退

更多時間和人力檢視程式碼不能替代良好的測試覆蓋。即使投入大量審查資源,仍然無法確信改變是否正確。唯有透過測試回饋,才能真正降低變更風險。