iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Software Development

消除你程式碼的臭味系列 第 12

Day 12- 拒絕複製貼上:抽出共用邏輯

  • 分享至 

  • xImage
  •  

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

消除你程式碼的臭味 Day 12- 拒絕複製貼上:抽出共用邏輯

重複不是省事,是技術債。

在第二個地方貼上相似度 90% 以上程式碼時,就創造了一個混亂區。

讓程式碼庫假裝有兩段獨立的邏輯,而事實上它們是應該永遠保持同步的雙胞胎。

人的記性沒那麼好。
總有一天會修好 A 點的 bug,卻完全忘了 B 點的存在。

同樣的東西寫兩次,就是在養 Bug。

辨識重複的四種類型

  • 相同程式碼塊:一字不差地出現多次。
  • 相似流程:步驟一樣、變化點少量不同。
  • 相同資料轉換:同樣的欄位清理、驗證、映射。
  • 相同 I/O 流程:開關資源、錯誤處理模式一致。

抽取步驟

  1. 將重複區塊選出,放進一個命名清楚的函式。
  2. 把變化點變成參數或回呼。
  3. 把錯誤訊息、預設值一併集中。
  4. 用測試覆蓋抽出後的函式,再刪掉舊重複。

重複的臭味

// 🔴 臭味 同樣的邏輯重複了三次。下一個接手的人祝你好運。
function createUser(u){ if(!u.email) throw Error('bad'); return { id:u.id, email:u.email.trim().toLowerCase() }; }
function updateUser(u){ if(!u.email) throw Error('bad'); return { id:u.id, email:u.email.trim().toLowerCase() }; }
function importUser(u){ if(!u.email) throw Error('bad'); return { id:u.id, email:u.email.trim().toLowerCase() }; }

Write Everything Twice
https://ithelp.ithome.com.tw/upload/images/20250914/20124462ohl0mIdguZ.png

抽出共用函式:給概念一個名字

好的工程師會看到重複,然後停下來,他們會問:「這個重複的模式代表了什麼概念?」
然後,他們會給這個概念一個名字,這個概念叫 normalizeUser,專門定義一個專門的流程,來接收各式各樣可能不標準的使用者資料,並將其清理、轉換成我們系統內部統一的標準格式。

// 🟢 好品味:一次定義,到處引用。

// 這是一個「單一事實來源」(Single Source of Truth)。
// 關於使用者資料如何標準化的所有規則,都只存在於這裡。
function normalizeUser(u) {
  if (!u.email) throw Error('email is required'); // 錯誤訊息也應該清晰
  return { id: u.id, email: u.email.trim().toLowerCase() };
}

// 現在,這些函式變得誠實了。它們清晰地表達了自己的意圖:
// 它們的核心工作,就是執行「使用者資料標準化」。
function createUser(u){ return normalizeUser(u); }
function updateUser(u){ return normalizeUser(u); }
function importUser(u){ return normalizeUser(u); }

Don't Repeat Yourself
https://ithelp.ithome.com.tw/upload/images/20250914/20124462YaAwh2CYBK.png

  • 維護的單點: 現在,所有關於使用者標準化的規則都集中在一個地方。任何修改,一次完成,全局生效。沒有猜測,沒有遺漏。

  • 意圖的彰顯: normalizeUser 這個名字本身就是文件。它告訴了所有人這段程式碼的目的。而之前那三段重複的程式碼,它們的意圖是模糊且隱含的。

  • 這才是真正的「重用」: 不是複製貼上,而是透過一個定義良好的函式來重用一個穩定的邏輯單元。

抽象的務實技巧

  • 重複一次是偶然,重複兩次是巧合,重複三次才是模式。

    • 當你第二次寫下相似的程式碼時,要警覺。

    • 當你準備第三次貼上時,必須停下來重構。在那之前,過早的抽象可能會讓你陷入錯誤的設計。

  • 錯誤的抽象比重複更糟。

    • 如果為了合併兩個只有 50% 相似的流程,而創造了一個充滿 if 判斷和複雜參數的函式,那麼製造的問題會比解決的還多。有時候,一點點重複是可以接受的,它比一個糟糕的、扭曲的抽象要好。保持務實。

檢查清單

  1. 尋找重複的條件、轉換、錯誤訊息。
  2. 是否能用一個命名良好的函式涵蓋?
  3. 是否可把可變部分當參數傳入?
  4. 是否能把重複資料結構提到共用層?

今日重點

  • 一次實作,多處使用。
  • 用好的命名包裝共用邏輯。
  • 減少重複,減少錯誤面積。

一個函式是一個承諾。
它承諾一段特定的邏輯會以一種可預測且一致的方式被處理。

停止複製臭味與 Bug,開始設計可靠的函式。


上一篇
Day 11- 函式的副作用:把計算與 I/O 分離
系列文
消除你程式碼的臭味12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言