之前我們提過 聊聊 if 條件句的那些小陷阱 ,在程式設計中佔比最大的不是if,就是迴圈的使用,這在任何一位coding的開發者,都一定會碰過的問題。
if寫得好,可以大大提高效率與可讀性。
我們今天就來談談 防呆條件(Guard condition)
先來一段範例:
PHP
function sendEmail($user) {
if (!$user || !$user->email) {
return; // <-- Guard condition:防呆條件
}
// 實際邏輯
Mail::to($user->email)->send(...);
}
Guard condition 通常在函式或區塊的一開始就出現,作用是:
- 檢查參數是否合法
- 判斷某些狀態是否符合執行邏輯
- 若不符合,就提早 return / throw / continue / break,避免後面程式碼白跑或報錯
適合的Guard Condition 情境
1. 放在函式最前面
「錯誤輸入提早退出函式,正確輸入才繼續。」
- 把 guard condition 放在函式開頭,提早 return,減少巢狀、提升可讀性。
PHP
function process($data) {
if (empty($data)) {
return; // 提早退場
}
// 主邏輯
}
2. 只保護「不合法」或「不必要」的情況
不要用 guard condition 去包「正常流程」
PHP
// 👍 合理的 guard
if (!$user) return;
if (!isset($config['enabled'])) return;
// 👎 錯誤示範:過度包裝正常流程
if ($user) {
// main logic
}
3. 一個條件一個 guard,避免複雜邏輯纏繞
分開判斷比複合 if 來得清楚
PHP
// 👍 建議
if (!$user) return;
if (!$user->isActive()) return;
if ($user->isBanned()) return;
// 👎 不建議
if (!$user || !$user->isActive() || $user->isBanned()) return;
4. 使用「正向條件」撰寫主邏輯
用 guard 去排除異常,讓主流程乾淨俐落
PHP
function save($data) {
if (!$this->isValid($data)) {
throw new InvalidArgumentException("Invalid data.");
}
// 主邏輯只有正常情況
$this->repo->save($data);
}
5. 在錯誤情況下清楚地中斷流程
使用 return / throw / continue / break 作為 guard 的動作
PHP
if (!$user) {
return; // 跳過這次處理
}
if ($data->hasError()) {
throw new RuntimeException("Invalid state."); // 停止整體流程
}
6. 善用 early return,減少巢狀 if
guard condition 讓邏輯扁平化
PHP
// 👍 使用 guard 清晰結構
function foo($x) {
if (!$x) return;
if ($x < 0) return;
// 主邏輯
}
// 👎 過度巢狀
function foo($x) {
if ($x) {
if ($x >= 0) {
// 主邏輯
}
}
}
Bonus:什麼時候需要 guard condition?
情境 | 適合使用 guard? |
---|---|
傳入參數可能為 null、空、無效 | ✅ 是 |
使用者未登入或權限不足 | ✅ 是 |
檢查狀態是否允許繼續進行流程 | ✅ 是 |
執行某操作之前需要特定前置條件 | ✅ 是 |
為了 code style 而硬塞早退邏輯 | ❌ 否 |
為什麼 guard condition 很重要 ?
- 能立刻排除不正常情況 只要觀察特定實例,就能看出函式若事先檢查輸入並及早結束,可以避免後續一連串的問題。這種做法常常帶來顯而易見的好處。
- 讓程式更易讀、更好維護 寫在最前面,清楚地說明「什麼情況不繼續」,能讓主要邏輯呈現得更直觀。如果想確認是不是所有情況都適合,也可多做幾個不同場景的對比測試。
- 專注主要功能,減少預期外干擾 一開始就處理掉異常情境,主邏輯就能假設「輸入已正確」。真實開發中,如果發現情況更多樣,還是得進一步評估是否每個點都要設置。
- 方便擴充與撰寫測試 單元測試時,能很快檢查到「不符預期的輸入」,而且結果一目了然。多個模組互相整合時,也可以更輕鬆地定位錯誤。
- 提升團隊協作效率 當大家都約定俗成地把異常先篩選掉,整段程式就省去不必要的條件判斷。遇到需求變動或問題排查,也能集中注意力在真正該處理的功能上。
簡單來說,先在程式碼開頭用簡單判斷,能直觀地處理邊界案例,並讓後面的邏輯更加明確。要不要全面推行或選擇在哪些函式使用,仍要視實際情況而定,透過更完整的實測與討論,才能更穩健地落地執行。