歡迎來到防禦性設計!

在本章中,我們將探討程式設計師如何確保軟體具有健壯性 (Robust)。一個健壯的程式即使在使用者出錯或發生意外情況時,也不會崩潰或出現異常行為。你可以把它想像成是為你的程式碼穿上「防彈衣」!

我們將學習如何防止使用者破壞我們的程式,以及如何編寫易於閱讀的程式碼。如果剛開始覺得有點技術性,別擔心——這其實只是關於如何更有條理地準備工作!

1. 甚麼是防禦性設計?

想像你在設計一輛汽車。你不能假設駕駛員是一個完美的專業人士,所以你會安裝安全帶、安全氣囊,並在車門未關好時提供警示燈。防禦性設計 (Defensive Design) 的概念也是一樣的,只是它是針對電腦程式。它是一種預先考慮並防止問題發生的實踐。

預期錯誤使用 (Anticipating Misuse)

程式設計師必須預期錯誤使用。這意味著要思考:「使用者在使用我的程式時,可能會做出甚麼最愚蠢或最危險的事情?」
使用者可能會:
- 當程式要求輸入數字時,卻輸入了文字。
- 將必填欄位留空。
- 嘗試猜測密碼 1,000 次(這被稱為暴力破解攻擊 (Brute-force attack))。
- 嘗試輸入系統無法處理的超長資料。

重點複習:防禦性設計旨在使程式保持健壯性,從而確保它能在不崩潰的情況下處理錯誤。

2. 輸入驗證 (Input Validation)

輸入驗證是一種防禦性設計技術,程式會在處理資料之前,檢查使用者輸入的資料是否符合特定規則。如果資料「無效」(錯誤),程式應拒絕接收並要求使用者重新輸入。

常見的驗證檢查:

- 類型檢查 (Type Check):輸入的資料類型是否正確?(例如:是數字而不是文字嗎?)
- 範圍檢查 (Range Check):數字是否在特定限制內?(例如:年齡必須介於 0 到 120 之間)。
- 存在性檢查 (Presence Check):使用者是否有輸入資料,還是留空了?
- 格式檢查 (Format Check):格式是否正確?(例如:郵遞區號是否由正確的字母和數字組合而成?)
- 長度檢查 (Length Check):輸入是否太短或太長?(例如:密碼必須至少 8 個字元)。

類比:想像給幼兒玩的「形狀分類玩具」。如果你試圖將方形積木放入圓形孔洞中,它是放不進去的。這就是物理上的驗證!

關鍵總結:驗證檢查的是規則,而不是真實性。如果程式詢問你的生日,而你輸入了一個符合格式但虛假的日期,程式仍然會接受。它只是確保資料是合情合理的。

3. 身份驗證 (Authentication)

身份驗證是用來確認使用者身份的過程。這關乎確保使用者確實是他們所聲稱的那個人。

最常見的方式是使用使用者名稱和密碼
- 步驟 1:使用者輸入他們的憑證。
- 步驟 2:程式將其與儲存的資料庫進行比對。
- 步驟 3:如果符合,則授予存取權;如果不符合,則拒絕存取。

專業提示:為了讓身份驗證更具「防禦性」,程式設計師可能會限制失敗的登入嘗試次數,以防止駭客猜測密碼。

4. 可維護性 (Maintainability)

一個「健壯」的程式不只是不會崩潰,它還必須讓其他程式設計師能夠在未來理解並進行修正。這被稱為可維護性。如果你寫出雜亂的程式碼,找出並修復臭蟲(錯誤)將會非常困難!

為了保持程式碼的可維護性,我們可以使用這四個技巧(記憶口訣:S.I.N.C.):

1. 子程式 (Sub-programs)

不要寫成一片巨大的「程式碼牆」,而應該將其分解成更小、易於管理的部分,稱為子程式 (Functions and Procedures)
類比:與其寫一份超長的五道菜餐譜,不如為前菜、主菜和甜點分別寫一份菜單。

2. 縮排 (Indentation)

這意味著當程式碼位於迴圈或「if 條件式」內時,需要向右縮排。這能讓程式碼的結構一目了然。
範例:在 Python 中,如果你不縮排,程式甚至無法執行!

3. 命名規範 (Naming Conventions)

為變數和子程式使用描述性名稱
- 壞習慣:x = 50
- 好習慣:user_score = 50
描述性名稱能準確地告訴閱讀程式碼的人這些資料的用途。

4. 註解 (Commenting)

程式設計師會在程式碼中加入註釋(以 # 或 // 等符號開頭),電腦會忽略這些註釋。這些是為了讓人類閱讀者理解程式碼特定部分的作用。
範例:# 此函式用於計算包含稅項後的總價

重點複習箱:
- 子程式:將程式碼分塊。
- 縮排:標示程式碼區塊的開始與結束。
- 命名:使用清晰、合理的變數名稱。
- 註解:向其他人解釋邏輯。

常見錯誤需避免

- 混淆驗證 (Validation) 與核對 (Verification):驗證檢查的是資料是否被允許(例如:這是一個數字嗎?);核對檢查的是資料是否正確(例如:兩次輸入密碼以確保沒有打錯)。
- 認為「健壯」意味著「快速」:一個健壯的程式執行速度可能會稍慢一點,因為它需要處理所有額外的檢查,但它安全性更高!
- 忘記寫註解:你可能會認為自己記得為甚麼寫這行程式碼,但三個月後,如果沒有註解,你(或你的隊友)將會感到非常困惑!

總結:防禦性設計的目的是透過驗證和身份驗證來保護程式免受使用者的錯誤影響,並透過可維護性來保護程式碼,避免未來產生混亂。