先防守在進攻,那些年被過去自己痛歐的日子

別 Gank 未來的自己:我寫了十年 Code 的防禦性程式心法 ​

剛入行的時候,我跟許多人一樣,是個充滿熱情的「進攻型」前端工程師。

接到需求,第一時間想的就是如何用最快的速度、最酷炫的技術,把功能「做出來」。每一次 git push,每一次功能上線,都像是在戰場上攻下一個據點,充滿了成就感。

然而,隨著時間的推移,我慢慢發現,戰場上最可怕的敵人,往往不是眼前的 Bug,也不是隔壁的 PM 或 UIUX 調整,而是那個來自過去、對未來一無所知的——昨天的自己。

寫程式,真的是一趟不斷學習如何「不要 Gank 未來的自己」的旅程。而「先防守,再進攻」,就是我在這趟旅程中,學會的最重要的心法。

為什麼要「先防守」? GANK 無處不在 ​

在寫程式的戰場上,「Gank」是常態。你總會在最意想不到的角落,被過去的自己埋下的地雷炸得灰頭土臉。

我們需要防禦的敵人是誰?

1. 善變的「外部世界」 ​

  • API 是善變的:後端 可能會因為需求調整,在你不知情的情況下,把一個 string 欄位改成 null,把 user_name 改成 username。如果你「盲目進攻」,直接樂觀地使用 response.data.user_name.toUpperCase(),一個 TypeError 就足以讓你的頁面全白。
  • 使用者是善變的:你以為使用者會乖乖在年齡欄位輸入數字,但他偏偏要打個「二十歲」。

2. 健忘的「協作隊友」 ​

  • 你的隊友可能不知道你寫的一個共用元件,它的 props 傳遞有什麼隱含的規則。他傳了一個 undefined 進來,導致了深層的渲染錯誤。

3. 最可怕的敵人:「過去的自己」 ​

  • 半年前的你,為了解決一個緊急問題,寫下了一段「我發誓我明天就回來重構」的 any 類型和骯髒的 if/else,然後再也沒回來過。
  • 一年前的你,寫了一個「聰明」的 one-liner,沒有留下任何註解。今天,你盯著這行程式碼,花了半小時也想不起來它到底在幹嘛。
  • 上個禮拜的你,在 computed 屬性裡寫了一個連鎖的 findIndex,卻忘了處理 -1 的情況。

「先進攻」的程式碼,或許能快速解決眼前的問題,但它建立的是一個充滿隱患、一觸即潰的「紙片屋」。而「先防守」的程式碼,則是在為未來搭建一座堅固的「碉堡」。

如何「舉盾觀察」?防禦性程式設計的具體實踐 ​

「先防守」不是拖延或不做事,而是在動手寫主要功能(進攻)之前,先建立起一套穩固的防禦工事。

1. 邊界意識:建立你的「海關」 ​

任何進入你系統的外部資料,都是不可信的。在你的 Repository 層或 Service 層,使用 zod 建立起嚴格的 Schema,就是你最堅固的盾牌。它能確保所有進入你應用程式核心的資料,都經過了驗證和清洗,變成了你期望的、安全的「核心模型」。

2. 預期失敗:為 undefined 和 error 寫程式 ​

不要只為「快樂路徑」寫程式。在存取任何可能不存在的資料前,都要舉起防禦的盾牌。

  • 用 v-if 守衛你的模板:在渲染 useQuery 的 data 之前,先檢查 isLoading, isError, data 是否存在。
  • 用 ?. 和 ?? 武裝你的邏輯:可選串連 (?.) 和空值合併 (??) 是你在 script 區塊裡最好的防身武器,它們能讓你安全地探索不確定的巢狀結構。
  • 用 try...catch 包圍你的預期:在呼叫 API 或執行可能失敗的操作時,思考一下「如果這裡失敗了會怎麼樣?」,並為它寫好 catch 區塊的劇本。

3. 型別即防禦:讓 TypeScript 成為你的盟友 ​

一個明確的 interface 或 type,遠勝於一萬行註解。避免使用 any,就像避免在戰場上矇著眼睛走路一樣。你為型別付出的每一秒,都會在未來為你省下數小時的 debug 時間。

4. 可讀性 > 聰明:寫給「人」看的程式碼 ​

過去的你寫下的「聰明」程式碼,對未來的你來說就是「天書」。

  • 優先使用簡單、直白、甚至有點囉嗦的寫法。
  • 為「為什麼」寫註解,而不是「做了什麼」。你的程式碼應該已經能說明它做了什麼,但它背後的業務決策或技術權衡,才是最需要被記錄下來的。

何時「進攻」? ​

當你的防禦工事都建立好之後,進攻就成了一件非常愉快的事情。

當你從 useQuery 中解構出的 data,已經是被 Zod 驗證過的、型別完美的「核心模型」時;當你知道你傳給子元件的 props 是 100% 型別安全時——你就可以心無旁鶩地、充滿信心地去實現那些複雜的業務邏輯和華麗的 UI 效果了。

防守,是為了創造一個絕對安全的環境,讓你可以放心地進攻。


寫了這麼多年程式,我越來越覺得,資深與否的差別,不在於知道多少奇技淫巧,而在於對「風險」的敬畏之心。

寫程式,真的是一趟不斷學習如何「不要 Gank 未來的自己」的旅程。而舉起防禦的盾牌,先觀察,再前進,就是我們在這趟旅程中,學會的最重要的技能。