iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0

https://ithelp.ithome.com.tw/upload/images/20250903/20124462P1N8QjGguI.png

消除你程式碼的臭味 Day 28 - 重構:看見味道就動手

重構不是一定要大改特改,要你把整個架構打掉重練,而是小步小步且精確的日常整理。

也別為了重構而重構。

如果你的程式碼能跑,沒有 Bug,而且所有人都懂,那就別動它。
只有當你看到「味道」,也就是你覺得這段程式碼很難讀懂、很難修改、很難擴充時,那才是重構的時機。

再來變臭的原因是資料結構設計不良,以及對特殊情況的處理方式。

這三個原則把握好:

  1. 資料結構優先:程式碼圍繞資料運轉,而不是反過來。

  2. 消滅分支:好程式碼沒有特殊情況。

  3. 實用主義:做對業務有意義的事,而不是為了抽象而抽象。

重構目標

重構的主要原則:先立安全網,再小步前進。

重構的目的是在不改變程式碼外部行為的前提下,提升其內部品質

這麼做能讓程式碼更易於理解(可讀性)、更易於維護(可維護性)和更易於擴展(可擴展性)。
重構不是浪費時間,而是為了節省未來更多尋找 Bug、開發新功能的時間,人生應該花在更有意義的地方。
https://ithelp.ithome.com.tw/upload/images/20250930/20124462fhPnJr2mQJ.png

重構的流程

  1. 加測試:這是唯一能讓你晚上睡得著覺的東西。如果你要動的程式碼沒有測試,那就先寫一個,因為找 bug 的時間比這個長多了。

  2. 小步修改:一次只動一個東西。你的每個 commit 應該都小到能一眼看完,並且清楚地表達「我做了什麼」。

    1. 一個味道一個分支
    2. PR 只做一件事
    3. 詳細描述動機與風險
  3. 運行測試:每次小改動後,立刻運行測試。確保你沒有改錯任何東西。這是一個簡單的行為驗證,不是什麼複雜的儀式。

經典案例:從資料看問題

發臭的程式碼總是在處理特殊情況。

// 🔴 臭味:這個函式做了兩件事,因為資料結構設計得不好
function save(user, db){
  // 1. 處理資料
  const normalized = {
    id: user.id,
    email: user.email.trim().toLowerCase(),
  };
  // 2. 存進資料庫
  return db.insert(normalized);
}

save() 這個函式,它的名字叫 save,它的職責應該是「」。
但它在裡面做了資料清理(trim()toLowerCase())。

單一職責原則,不只是一個函式只做一件事,還有「函式只做它名字裡說的事」。

// 🟢 好味道:這才叫做單一職責
function createNormalizedUser(u) {
  // 這就是它的唯一職責
  return {
    id: u.id,
    email: u.email.trim().toLowerCase(),
  };
}

// 這個函式現在可以只做一件事,因為它處理的資料是乾淨的
function save(user, db){
  // 這才是真正的 save
  return db.insert(user);
}

這就是重新設計資料結構來消除分支 ,會比「多型」或者「繼承」強一萬倍。

資料結構優先:先把資料整理好,讓它變成一個「乾淨的」使用者物件。這段程式碼創建了一個新的函式 createNormalizedUser 來處理這個問題。

消滅分支:現在 save 函式沒有任何多餘的事情做,它永遠只做 db.insert() 這件事。

重構實戰:資料結構優先

https://ithelp.ithome.com.tw/upload/images/20250930/20124462TUPXDNjQ6g.png

分支與 PR 實戰建議

  • 一個味道一個分支:每次重構只針對一個「程式碼臭味」,並在一個獨立的分支上完成。

  • PR 只做一件事:在 Pull Request 中,只包含單一、原子化的重構提交(commit)。你的 commit 應該比你的晚餐還小。

  • 詳細描述:在 PR 描述中,清楚說明這次重構的動機做法風險,以及如何回滾

  • 風險管控:對於風險較大的重構,先加上遙測(telemetry)與功能開關(feature flag),以便在出現問題時能快速回滾,而無需部署新的程式碼。

  • 最重要的一點: 永遠不要破壞現有的功能。如果你的重構導致任何使用者功能崩潰,那就說明測試不夠,或者根本不明白自己在做什麼。

重構檢查清單

  1. 是否有測試保護?

  2. 每一步是否都可回滾?

  3. 命名是否比重構前更清楚?

  4. 程式碼的複雜度是否下降?

今日重點

  • 用測試做安全網。
  • 小步、連貫、可回滾。
  • 讓結構更清晰、耦合更低。

把重構當成日常清潔,持續去味,重構不是為了讓程式碼看起來更漂亮,而是為了讓它更可靠。就這麼簡單。


上一篇
Day 27- 同步問題:管理多執行緒與競爭條件
下一篇
Day 29-順序依賴:停止設計那種需要記住呼叫順序的 API
系列文
消除你程式碼的臭味30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言