[Program] 巢狀結構
巢狀程式結構與可讀性
巢狀程式結構,尤其當其深度過深時,會顯著降低程式碼的可讀性,並增加後續維護的難度。通常,為了保持高可讀性,程式碼的深度應最多不超過三層。嚴格遵守此原則的程式設計師,常被稱為 「Never Nester」。
消除(Eliminating)巢狀程式的手法
以下是草稿中提到的消除巢狀程式結構的幾種主要手法:
- Extraction (抽出法)
原理: 從複雜或多層的巢狀結構中,將一部分程式碼抽出成獨立的函式(function)或方法(method)。
說明: 當程式碼內部有重複邏輯、或某個程式區塊承擔了過多的責任時,可以將這部分邏輯提取出來,形成一個新的、具有單一職責的函式。這不僅能減少原始函式的巢狀深度,也能提高程式碼的模組化程度和重用性。
範例:- 將一個複雜的條件判斷邏輯包裝成一個布林函式。
- 將一個迴圈內部的複雜計算過程抽出成一個輔助函式。
- Inversion (反轉法)
原理: 將**跳出函式(Early Exit / Guard Clause)**的判斷條件移至函式的最頂部。
說明: Inversion 的核心思想是盡早處理無效或不需要繼續執行的情況。而不是將判斷條件放在深層的巢狀結構中,將這些「守衛條件」前置,一旦條件不符就立即返回(return)或拋出例外(throw exception)。這能有效減少主邏輯的巢狀深度,使正常執行的路徑更加清晰。
// 原始巢狀結構
if (userIsAuthenticated) {
if (userHasPermission) {
// 核心業務邏輯
} else {
// 處理無權限
}
} else {
// 處理未登入
}
// Inversion 後
if (!userIsAuthenticated) {
// 處理未登入
return;
}
if (!userHasPermission) {
// 處理無權限
return;
}
// 核心業務邏輯 (巢狀深度降低)
- 依據契約式程式設計 (Design by Contract, DbC) 移除不必要判斷
原理: 根據契約式程式設計的原則,假設程式碼的使用者(呼叫端)會傳入合法的參數,進而移除程式碼內部不必要的參數合法性判斷。
說明: 契約式程式設計強調在函式(或方法)的前置條件(Preconditions)、**後置條件(Postconditions)和不變條件(Invariants)**之間建立明確的「契約」。前置條件規定了呼叫端必須滿足的條件才能呼叫函式。如果程式設計師能夠信任呼叫端會確保這些前置條件被滿足,那麼在被呼叫的函式內部就可以省略對這些條件的重複判斷。
重要考量:- 公共介面與內部函式: 對於對外公開的 API 或函式,通常仍建議進行參數驗證,因為無法完全信任外部呼叫者。然而,對於僅供內部使用的函式,如果其前置條件能在呼叫端被保證,則可以考慮移除重複判斷以簡化程式碼。
- 信任與防禦性: 這是信任呼叫端與防禦性程式設計之間的一種權衡。過度的防禦性判斷會增加程式碼複雜度,但過於信任也可能導致未預期的錯誤。
總結
綜合運用 Extraction、Inversion 以及基於 契約式程式設計 的判斷移除,可以有效降低程式碼的巢狀深度,顯著提升程式碼的可讀性、可維護性,並使程式邏輯更加清晰。