終於迎來了鐵人賽的最後一天!![]()
回顧這張踩坑地圖,我才發現這幾天記錄下的不只是錯誤與解法,更是我從前端走進後端後,逐漸蛻變的思考方式。
過去一年,從 Angular 轉戰 NestJS 時,我曾以為自己站在一個相對熟悉的起點,畢竟兩邊都寫 TypeScript,都有 Module、Dependency Injection 與 Decorator,許多專有名詞甚至如出一轍。
但真正開始寫後端後,我才深刻體會最大的門檻從來就不是語法。
過去處理前端問題時,我習慣從「畫面」找線索:哪個元件沒更新?哪個事件沒觸發?哪支 API 沒回應?然而到了後端,眼前不再有直觀的畫面可以追蹤。取而代之的是資料如何流動、物件由誰建立、業務邏輯在哪裡執行,以及一段程式碼究竟處於什麼生命週期與上下文之中。這些看不見的東西,卻決定了程式最後怎麼執行。
這一年下來,我學到的不再只是怎麼修好一個眼前的錯誤,而是當問題發生時,如何找出「框架看到的世界」與「我以為的世界」究竟差在哪裡。因此,在這系列的最後一篇,我想把我平時用來拆解問題的思考流程分享出來。
排錯的起點,不該是「我覺得 DI 壞了」,而是客觀、精準地描述觀察到的現象。至少先釐清:
舉例來說,「傳入 false,篩選結果卻像 true」是現象;「NestJS 把 Boolean 轉換壞了」則是尚未驗證的推測。兩者若混在一起,後面的排錯就很容易淪為尋找支持自己猜想的證據,而錯失真正的問題。
先描述看見了什麼,再討論為什麼。
掌握現象後,下一步是找出能穩定觸發它的條件。固定輸入、設定與操作順序,一次只移除一個變因,直到留下最小但仍會出錯的案例。
這個階段能幫助我們快速將問題分類:
無法重現的問題並非無解,但需要先補足 log、trace 或 metrics,讓它下次發生時留下更多線索,不然每次修改都只是在碰運氣。
案例縮小後,先不要急著改程式。試著沿著資料的實際路徑,找出「最後一個正常的位置」以及「第一個異常的位置」。
對於常見的 NestJS HTTP API,可以依序檢查以下層級:
| 層級 | 先確認什麼 | 可觀察的證據 |
|---|---|---|
| 啟動與 DI | 應用是否成功啟動?Module 與 Provider 是否可見? | 啟動 log、完整 stack trace、Module 設定 |
| Request/Pipeline | 請求是否命中預期路由?Guard、Interceptor、Pipe 是否執行? | 狀態碼、Request payload、階段性 log |
| 業務邏輯 | Service 收到的資料是否正確?分支條件是否符合預期? | 實際參數、結構化 log、unit test |
| Database/外部服務 | 查詢或外部請求是否真的送出?回傳內容與耗時如何? | SQL log、query count、trace、外部回應 |
| Response | Controller 已回傳,還是序列化或送出回應時才失敗? | 回傳值、Interceptor/Filter log、Response body |
定位問題大致發生的層級後,先別急著改程式,這時我們該做的是提出可驗證的假設,並透過實際證據來揪出真兇。
以 Day 16 的 Boolean 問題為例,當 Query 傳入 false 卻走進 truthy 分支時,可以先檢查 Controller 收到的實際值與 typeof。如果收到的是字串 'false',就應該檢查參數轉換的方式;如果已經是布林值 false,則需要進一步檢查後續的判斷邏輯。
有時也可以暫時繞過部分流程,例如直接呼叫 Service、替換 Repository,逐步縮小問題範圍。但切記每次只調整一個變因,才能確認究竟是哪個條件影響了結果。
在 NestJS 中,我也會特別留意幾個容易被框架抽象隱藏的邊界:
new 出來?這些不是固定的排錯答案,但卻會幫助我們順著證據剝絲抽繭,確認問題真正發生的原因。
確認根因後,我們必須用藥在痛點上,而不是只讓表面錯誤暫時消失。
舉例來說,當 API 回傳的資料結構不符合預期時,直接在 Controller 中額外處理,或許能暫時得到正確結果,但如果真正的原因是 DTO 轉換或序列化設定有誤,就應該回到源頭對症下藥,避免相同問題在其他 API 再次出現。
修正完成後,修復工作並未結束,還需要重新執行「最小重現案例」,並測試相關的正常情境與邊界條件。若問題可能再次發生,應盡可能補上 Unit Test、E2E Test,或必要的 Log 與監控。
排錯的終點,不只是讓錯誤消失,而是能夠證明問題已經解決,並降低同類問題再次發生的機會。
即使我們身處 AI 協助開發的時代,我認為這套排錯邏輯依然適用。AI 確實可以協助分析錯誤訊息、閱讀程式碼、羅列可能的病因,甚至產生測試案例,但這些建議仍然需要經過驗證。與其盲目地讓 AI 修改,更重要的是先釐清問題、提供足夠的上下文,再透過實際執行結果確認假設是否成立。
AI 可以加快除錯的效率,但理解問題、判斷根因,以及確認修正是否有效,仍然是工程師需要掌握的能力。
回顧這 28 篇求生手冊,它們真正留給我的,我想不是 28 組死背的標準答案,而是在面對未知與恐懼時,能夠穩步逼近真相的底氣與排雷方法。感謝每一位陪著這個系列走到最後的讀者,特別感謝帶我入門 NestJS 的 HAO,大力推薦他的《NestJS 帶你飛!》,讓我在初期免去了生啃官方文件的陣痛期,也要謝謝 Antonio 的推坑與鼓勵,讓我下定決心報名這次的鐵人賽。
我是 YUN,《NestJS 絕地求生手冊》就在這裡正式劃下句點,有機會我們未來見!
恭喜完賽!!看到你鼓起勇氣參加這次鐵人賽,我心裡其實超開心 > <
平常就常常和你討論技術,一直覺得你的思路很清晰,也很有自己的想法,這次更從你的文章中獲得不少啟發!
很開心能一起完成這次的挑戰!!
感謝安東~也恭喜你順利完賽哈哈