iT邦幫忙

2025 iThome 鐵人賽

DAY 14
1
Software Development

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

Day 14- 複雜判斷:抽到具名函式裡

  • 分享至 

  • xImage
  •  

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

消除你程式碼的臭味 Day 14- 複雜判斷:抽到具名函式裡

布林表達式越長,越應該被命名。
程式碼是寫給人看的,只是順便能讓電腦執行而已。

當你寫下一長串充滿 &&|| 的布林表達式時,就是在強迫每一個讀你程式碼的人(包括六個月後的你自己)停下來,拿出紙筆,開始做邏輯運算。

一個好的 if 條件,讀起來應該像一句通順的句子。
它陳述的是「意圖」,而不是「計算過程」。

經典案例:又臭又長的條件

// 🔴 臭味:考驗你的耐心
if ((user.age >= 18 && user.verified && user.role === 'member') || user.role === 'admin') {
  grantAccess();
}
  • 它隱藏了「什麼 What」,只有「如何 How」
    它告訴了我一堆計算步驟,卻沒有告訴我這個判斷的業務意義是什麼。這個條件到底想判斷的是什麼資格

  • 它是一塊 bug 磁鐵
    &&|| 混用,是程式設計中最容易出錯的地方之一。
    少加一個括號,整個邏輯就全錯了,而且這種錯誤在 Code Review 中極難被發現。

  • 它無法被重用
    如果系統的另一個地方也需要這個「資格」判斷怎麼辦?複製貼上嗎?我們前天才說過,那是製造 Bug 的行為。

大腦的運算過程
https://ithelp.ithome.com.tw/upload/images/20250916/2012446274Ehv2LdIP.png

抽成具名函式

要辨識出這個複雜的邏輯,意識到它代表了一個重要的業務概念,然後給這個概念一個名字

// 🟢 好品味:程式碼在說人話。

// 這個函式名稱 isEligible 本身就是最好的文件。
// 它告訴了我們這個邏輯的「意圖」。
function isEligible(user) {
  // 在函式內部,你還可以進一步為子條件命名,讓邏輯更清晰。
  const isVerifiedAdultMember = user.age >= 18 && user.verified && user.role === 'member';
  const isAdmin = user.role === 'admin';

  return isVerifiedAdultMember || isAdmin;
}

// 現在,主流程讀起來像一篇散文,而不是一行代數。
if (isEligible(user)) {
  grantAccess();
}
  • 意圖清晰: if (isEligible(user)) 這行程式碼,任何懂英文的人都能看懂。它把複雜的「如何實現」藏在了函式背後,在主流程中只暴露了清晰的「要做什麼」。

  • 可獨立測試: 你現在可以為 isEligible 這個函式寫一整套單元測試,把所有邊界情況(17 歲、18 歲、未驗證、不同角色)都覆蓋到。要測試原來那坨 if 判斷,可就麻煩多了。

  • 可靠的重用: 任何地方需要這個判斷邏輯,都只要呼叫 isEligible 就行了。這是唯一、可靠的「事實來源」。

大腦的運算過程
https://ithelp.ithome.com.tw/upload/images/20250916/20124462nrc8mxOKyM.png

判斷的方法

  1. 「一口氣」法則: 如果沒辦法把一個 if 條件用一句話通順地讀出來,那它就太長了。

  2. &&|| 混用就是小心: 在同一個表達式裡混合使用 ANDOR 時,就可以肯定要把它抽成一個函式,因為運算子的優先級是個常見的坑。

  3. 陳述「什麼」,而不是「如何」: 在主邏輯裡,條件式應該是 if (user.canPerformAction()),而不是 if (user.role == 'X' && user.status == 'Y')。後者是 canPerformAction 函式內部的實作細節。

拆解複雜條件的作法

  • 臨時變數命名:每個條件取個清楚的名字。
    const isActiveAdmin = user.role == 'admin' && user.status == 'active'

  • 抽函式:把複雜判斷搬進具名函式,主流程保持線性。 if (isEligibleForAction(user) 比一堆 && 乾淨十倍。

  • 查表法:條件對應固定結果,用物件或映射表。

  • 提早返回:條件不滿足就立刻返回,拒絕巢狀地獄。

今日重點

  • 長條件要命名。
  • 主流程只留可讀邏輯,細節藏進函式。
  • 減少錯讀與改壞的風險。

這是對下一個讀你程式碼的人(很可能就是你自己)的尊重,把條件變成好名字的函式,就是在消除你程式碼的臭味。


上一篇
Day 13- 魔術數字:用具備語義的常數取代
下一篇
Day 15- 組合優於繼承:用小能力組出行為
系列文
消除你程式碼的臭味18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言