以防衛敘句取代巢狀條件 (Replace Nested Conditional with Guard Clauses)

★★★★★Draft

FromRefactoring

📚 From the Books

以防衛敘句取代巢狀條件 (Replace Nested Conditional with Guard Clauses)Refactoring Moves

條件式通常出現在兩種情境:兩個分支都是正常行為,或一個分支正常、另一個是異常。在後者,用防衛敘句(提早 return)能顯出異常情況並非這個函式的邏輯核心。

🧠 Why It's a Problem

深巢狀的 if/else 逼讀者把每一層條件都記在腦裡,才走得到最裡面的核心邏輯。若某些分支其實只是「處理特例後就結束」,就沒必要讓它們把主線壓在最深處。

TIP

關鍵區分:兩分支都是正常行為時,保留 if/else 反而更誠實;只有在「這是異常、提早出場」時,才換成防衛敘句。

⚖️ Refactoring

機械步驟:① 挑出最外層、可作為防衛條件的分支 → ② 把它改寫成「條件成立就提早 return」 → ③ 測試 → ④ 對其餘的特例分支重複同樣動作 → ⑤ 拉平後,核心邏輯落在函式最後、不再縮排。

前 — 巢狀 if/else 把主線埋在底層
function calculatePay(employee) {
  if (employee.isRetired) {
    if (employee.age > 65) {
      return 0;
    } else {
      return employee.pension;
    }
  } else {
    if (employee.isOnLeave) {
      return 0;
    } else {
      return employee.salary;
    }
  }
}

要看懂「一般在職者領 salary」,得先穿過退休、年齡、請假三層判斷。

後 — 防衛敘句把特例提到前面
function calculatePay(employee) {
  if (employee.isRetired) {
    if (employee.age > 65) {
      return 0;
    }
    return employee.pension;
  }

  if (employee.isOnLeave) {
    return 0;
  }

  return employee.salary;
}

每個特例判斷完就 return 離場,巢狀被拉平;return employee.salary 這條主線落在最後、一目了然。

NOTE

若條件分支不是「特例 vs. 主線」,而是「依型別選不同行為」,那該用的是 Replace Conditional with Polymorphism 而非防衛敘句。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading