iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
ChatGPT & Codex

從 Prompt Engineering 到 Copilot / Codex 實務 30 天系列 第 12 篇

Day 12:【代碼抓漏】貼上 Error Stack Trace:讓 ChatGPT 扮演除錯專家快速定位例外與錯誤

  • 分享至 

  • xImage
  •  

完成了第二週的演算法與資料結構解題後,從今天開始,我們正式邁入工程師日常開發中最耗時、也最考驗功力的環節——「系統維護、代碼重構與除錯(Debug)」。

在實際專案中,我們每天要面對的往往不是乾淨的演算法題目,而是終端機裡動輒幾十行的紅色報錯訊息(Error Stack Trace)。特別是在多層架構(Controller -> Service -> Repository)的 Spring Boot 或 Java 應用中,初學者常常盯著一整頁的堆疊追蹤不知所措,只能盲目下斷點或加 System.out.println。

今天我們就來示範:如何將 ChatGPT 當作資深除錯顧問,藉由結構化 Prompt 快速解讀 Stack Trace,精準抓出空指標(NullPointerException)與語意邏輯錯誤!


一、高效除錯提問法(Debug Prompting Template)

貼報錯給 AI 時,千萬不要只丟一句「這段為甚麼錯了?」。提供足夠的上下文能讓 AI 在 3 秒內定位問題:

【除錯分析提示詞範本】
請扮演資深 Java 後端架構師與除錯專家。我的系統在運行時發生了例外,以下是相關資訊:

  1. 業務場景簡述:[例如:查詢使用者訂單列表時報錯]
  2. 錯誤堆疊(Stack Trace):
    [貼上終端機完整的報錯訊息]
  3. 相關呼叫端代碼:
    [貼上涉及的核心 Class 或 Method]

請依序提供以下診斷:

  • 致命根因(Root Cause):用白話文精確指出是哪一行程式碼、存取了什麼變數導致崩潰?
  • 呼叫鏈分析:在深層框架(如 Spring/Tomcat)的堆疊中,哪一行是我們自己寫的業務代碼(User Code)?
  • 修復方案與防禦代碼:提供修正後的 Java 代碼,並使用 Java 8+ Optional 或防禦性檢查避免再次發生。

二、實戰案例:隱蔽的 NullPointerException

假設我們有一個電商會員服務,負責計算會員的折扣價:
[涉及問題的業務代碼]
public class DiscountService {
public double calculateDiscountedPrice(Order order) {
// 取得會員等級折數
double discountRate = order.getUser().getMembership().getDiscountRate();
return order.getTotalAmount() * discountRate;
}
}

[執行時噴出的錯誤堆疊]
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Membership.getDiscountRate()" because the return value of "User.getMembership()" is null
at com.example.service.DiscountService.calculateDiscountedPrice(DiscountService.java:5)
at com.example.app.OrderController.checkout(OrderController.java:24)
at com.example.app.Application.main(Application.java:12)


三、AI 的根因診斷與盲點剖析

將上述訊息送入提示詞模板後,AI 會直接切中要害:

1. 致命根因指出

  • 錯誤不是出在 order 或 order.getUser(),而是使用者的會員物件 getMembership() 回傳了 null。
  • 呼叫鏈第 5 行:連續鏈式調用(Chained Calls: a.getB().getC().getD())是典型的火車代碼(Train Wreck Code),極易違反迪米特法則(Law of Demeter),只要中間任何一個節點為空就會崩潰。

2. 優化修復:引入 Optional 與預設值機制

AI 提供的現代 Java 防禦性修復方案:

[優化後的防禦代碼]
import java.util.Optional;

public class DiscountService {

private static final double DEFAULT_DISCOUNT_RATE = 1.0; // 無會員預設不打折

public double calculateDiscountedPrice(Order order) {
    if (order == null) {
        throw new IllegalArgumentException("訂單物件不可為 null");
    }

    // 利用 Optional 優雅處理可能為空的多層物件
    double discountRate = Optional.ofNullable(order.getUser())
            .map(User::getMembership)
            .map(Membership::getDiscountRate)
            .orElse(DEFAULT_DISCOUNT_RATE);

    return order.getTotalAmount() * discountRate;
}

}


四、工程師的除錯心法小結

透過 AI 輔助 Debug,我們可以建立起一套標準的排查肌肉記憶:

  1. 尋找「Caused by」與自身套件名稱:
    不要被 Spring 或 Netty 動輒上百行的內部堆疊嚇到,先拉到最下方尋找 Caused by:,並過濾出自己專案 Package(如 com.example)的第一行,那裡就是事發現場。
  2. 警惕連續鏈式呼叫:
    凡是看到超過兩層的 .get().get(),都應該透過 Optional 或提早 Return(Guard Clauses)進行防呆。
  3. 區分語法錯誤與業務邏輯例外:
    語法錯誤編譯器會抓,真正的線上災難往往是空指標、資料庫欄位超長、或數值精度遺失,而 AI 對於這類潛在的 Null 邊界診斷具備極高的敏銳度。

今日小結與預告

今天我們示範了如何透過結構化的 Debug Prompt,讓 AI 快速穿透冗長的 Stack Trace 定位到空指標的核心根因,並利用 Optional 寫出健壯的防禦性程式碼。


上一篇
Day 11:【實戰紀錄】攻克經典 Medium 題目:與 AI 協同解題、除錯與優化的完整思維過程
下一篇
Day 13:【重構優化】消除 Code Smell:利用 AI 重構冗長條件句(If-Else 地獄)
系列文
從 Prompt Engineering 到 Copilot / Codex 實務 30 天 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言