iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Claude AI

買了 Claude Code,然後呢?系列 第 10 篇

Day 10|只改一個欄位,Claude 要先查哪些地方?

  • 分享至 

  • xImage
  •  

封面:桌上攤開設計圖,從一個黃色欄位追查修改可能影響的位置

前幾天,我們一直在問開工前的問題:怎樣才算完成?哪些規則不能忽略?我認為該改的地方,真的找對了嗎?PM 交來的需求,還缺哪些決定?

讀到這裡,可能會想:所以,什麼時候才開始寫程式?(敲碗

前面連著幾篇都在談分析,是因為我越用 AI,越覺得這段不能省。以前寫程式要花時間,還有機會邊寫邊發現需求沒想清楚;現在 Claude Code 很快就能交出實作,沒釐清的假設也可能跟著變成程式。

AI 把寫程式變快了,也讓「到底要寫什麼」變得更重要。 分析不是多寫幾份文件,而是把目的、規則、例外與未決事項攤開,讓規格有依據,讓後面的開發少靠猜。前面花時間做的準備,今天就要拿來用了。

昨天那份訂單取消的需求交接摘要,就是接下來的起點。也就是前篇的「開工卡」:把範圍、規則與未決事項交清楚,讓 RD 接著做設計。範圍比較清楚了,但 RD 還得回答:退款規則放哪裡?哪些地方會收到這個結果?改完要怎麼驗?

從需求分析接到系統設計

Anthropic 的 AI-native SDLC playbook 有一個我想借用的做法:每個階段留下下一步能接著使用的產物。 它把工作分成 Plan、Design、Build、Test、Deploy、Maintain,但這些階段會來回修正,不是走過一次就結束。

前面談過的目的、理由、查證與需求交接摘要,到了這裡,都要變成設計的依據:

開發時要回答的問題 前面怎麼處理 留下的文件或紀錄 接下來怎麼用
為什麼做、怎樣算完成? Day 6:目的與驗收條件 intent.md、spec.md 設計與測試不能偏離目的
有哪些不能忽略的背景? Day 7:理由卡與專案規則 CLAUDE.md、相關決策文件 分析與實作時讀取適用規則
我認為要改的位置對嗎? Day 8:追路徑、找反證 程式位置與查證紀錄 避免從錯誤假設開始修改
這次改什麼,還缺哪些決定? Day 9:需求交接摘要 規格、未決事項與交接摘要 確定設計範圍與待確認條件
準備怎麼改、怎麼驗? Day 10:設計與實作計畫 設計決定、圖與 plan.md 交給後面的實作、測試與審查

這是本系列的工作與文件對照,不是官方規定的一套檔名。需求交接摘要可以直接留在 Jira 或規格裡,不必再多維護一份同樣內容。

前幾篇用了不同案例,練的是不同的判斷方法;接下來,則沿著 Day 9 的同一份訂單取消程式,把設計、實作、測試與交付走下去。承接的是方法,不把前面不同案例的實跑拼成同一張票。

用我熟悉的分工來說,前面偏系統分析(SA):釐清問題、規則與完成條件。今天往系統設計(SD)走:決定元件責任、資料與介面,以及失敗時怎麼處理。這不是單向交棒,設計發現需求有缺口,仍要回去確認。

功能需求告訴我系統要做什麼,非功能性需求則限制它必須在什麼條件下做到。 延遲、容量、可靠性、安全與可觀測性不能等程式寫完才想;它們應在分析時提出,在設計時變成取捨與驗法。AI 能加快提出方案,不會替我們決定系統可以慢多久、資料可以丟多少。

用只改一個欄位,走一次設計

Day 9 還有待確認的問題,不能到了今天就當成全部有人回答。本篇用教學規格 rules-v2.md 固定一個條件:已付款、未出貨的訂單,第一次取消時退款旗標為 true;重複取消則為 false。這裡的旗標表示本次取消的結果,不是訂單退款歷史,也不會真的呼叫金流。

只讀條列規格,容易漏掉「已付款,但早就取消過」這種交叉條件。我會先把規則畫成流程圖,沿每條分支走一次:先看已出貨,再看是否重複取消,最後才看付款狀態。圖呈現的是預期結果,不規定程式只能照這個分支順序寫。

依教學規格區分已出貨、重複取消與首次取消的付款條件

流程圖回答「遇到這個條件,應得到什麼結果」。它是 rules-v2 的閱讀輔助,不代表舊程式已經做到。

這是示範採用的規則,不是公司 Owner 的正式核准。真實專案可以先比較設計,但未確認的規則仍得列在待決事項,不能直接當成上線依據。

昨天把需求文件與程式分組給 Claude,看它各自能查到什麼;今天把規格、需求交接摘要、Domain、API 放在一起,再追到教學用的通知接收端 FakeSink,看看送出的內容是否真的留下可核對的紀錄。仍只提供 Read、Grep、Glob 工具,請它追資料流、比較規則落點、草擬計畫與循序圖,不修改功能。

第一輪十二個回合、一百一十秒,它交回一份約四千字的設計審查包。我接下來要做的,是把這些分析收成開發能照著走的計畫。

先追這個值,誰算、誰傳、誰保存?

先看這些元件的位置,再追退款旗標經過的邊界:

同一 API 程序內的 Domain、儲存、佇列與 Worker,以及外部 FakeSink;身分與訂單授權待設計

元件位置與結果流向的閱讀示意,不表示執行先後。Domain 與 Worker 都在同一 API 程序;HTTP 與日誌是輸出,不是另外兩個服務。虛線註記的正式授權尚未完成。

Claude 整理出的資料流,讓「只改一個欄位」具體了起來:

位置 做什麼 固定快照中的依據
Domain 算出 result.RefundRequested Cancellation.cs:13、:21
API 把結果放進 HTTP 回應、日誌、通知物件 Program.cs:89、:88、:79
通知發送端 把旗標序列化進 JSON body,送給 FakeSink Program.cs:200 同步、:231 非同步
FakeSink 保存通知識別資料,但沒有保存退款旗標 FakeSink/Program.cs:17-26

FakeSink 有收據,不代表收據包含通知的所有內容。

這張表讓後面的驗證有了位置:除了 Domain 算得對,還要看 HTTP、日誌與送出的 payload 是否帶著同一個結果。只看單元測試,還看不到這些邊界。

規則只算一次,不代表只測一處

沿用 Day 6 的做法,先確認這次要完成的行為與限制:提出退款要求,但不執行退款。接下來才問:在 API 改,還是在 Domain 改?Claude 建議留在 Domain。我把兩個選項放在一起看:

做法 對這份程式的影響 這次的選擇
在 Domain 的 Cancel 計算退款旗標 API 繼續轉發同一份結果,Domain 測試能直接核對規則 採用
API 收到結果後,另外依 Paid 重算 HTTP、日誌與通知可能拿到不同版本的判斷;Domain 測試也管不到新增的 API 規則 不採用

這不是因為「業務邏輯就該放 Domain」這句口號。核對目前程式,退款旗標確實由 Cancel 產生,API 只是把它接出去。API 仍有出貨狀態對應 HTTP 狀態碼的條件,不能因此說它完全沒有判斷。

所以這次的設計決定很小:退款規則留在 Domain,公開介面不變;測試則分別確認規則本身與 API 轉發結果。 不需要為了改一個旗標,把整個 API 重寫。

功能對了,還有哪些設計條件要問?

把退款旗標算對,只回答功能的一部分。沿著同一條取消路徑,還會遇到這些問題:下面是依既有程式整理的設計盤點,不是新增壓測或故障實驗。

設計面向 放到這個案例,要問什麼? 目前能說到哪裡/下一步怎麼驗
相容性 布林型別沒變,其他呼叫端是否仍把它當退款歷史? 已追到 HTTP、日誌與通知;外部使用者未知,要補契約與消費端核對
可靠性與並行 兩次取消同時到,或入列後程序重啟,會怎樣? 讀、判斷、寫回非整體原子;儲存與佇列在記憶體。並行與重啟需另驗,不能保證不重複或不遺失
可觀測性 有收據,能否證明送出的退款旗標正確? FakeSink 未保留該欄位;測試接收端需留下 payload,才能核對內容

這些問題不代表本輪都要修。它們讓設計能交代:哪些沿用、哪些本次處理、哪些還不能承諾。缺少目標就留下待決事項,不請 Claude 自行填一個漂亮的 p95 或可用率。

接收端沒保存,不等於送出去的內容沒變

資料流查得出來,結論仍可能跨太遠。Claude 在第一輪寫道:

本輪修改 BR-03 的可觀察外部影響實際只有兩個:API JSON 回應、logs.jsonl 這一行紀錄。通知送達與否不受影響。

這段要拆開看。FakeSink 沒保存退款旗標,是程式能核對的事;發送端的 payload 仍包含它,規則改了,送出去的內容也可能改變。因此,不能只因接收端沒記錄,就把通知內容排除在驗證之外。

但反過來也一樣:payload 改變,不代表通知會送不到。 這輪只讀程式,沒有執行通知送達驗證,不能把兩件事混成同一個結論。

我把它改成計畫裡的一個具體要求:用會保留 payload 的測試接收端,核對 refund_requested,不能只拿「收到一張收據」當成內容正確。

相同輸入與提示共跑三次,資料流都追到相同位置,影響範圍的說法卻有寬有窄。這些紀錄足以提醒我回查推論,不能拿來估算模型錯誤率。

循序圖也要查:先入列,還是先回應?

它畫出的首次取消循序圖,把 API 回 200 放在通知入列之前。正常首次取消的非同步分支,程式卻是先 await 入列,再寫日誌、回應。

程式實際的順序是這樣(節錄 src/Api/Program.cs,省略號為略過的欄位):

if (transitioned)
{
    var n = new Notification(..., result.RefundRequested);
    metrics.Inc("notify_enqueued_total");
    await channel.Writer.WriteAsync(n);   // ← 第 84 行:先等入列完成
}
log.Write(new { ..., queue_depth = channel.Reader.Count });
return Results.Json(new { ..., refund_requested = result.RefundRequested },
                    statusCode: status);  // ← 第 89 行:才回應

看那兩行註解:await 在回應之前。原圖把兩者對調,一個箭頭的位置就改變了 API 對呼叫端的承諾。

前面的流程圖查業務分支,這裡的循序圖查元件交接:API 呼叫 Domain 得到結果,更新狀態,再通知與回應。兩張圖一起看,才能分清「結果應該是什麼」與「現在怎麼把結果送出去」。

這會影響讀圖的人怎麼理解 API 的承諾。我另外開一個乾淨的唯讀 session,只給 API、Domain 與那張圖,請 Claude 逐箭頭核對程式,附行號並分清「順序畫錯」與「省略分支」。

正常首次取消的非同步分支:原圖先回 200 再入列,程式實際先等待入列再回應;送達由背景 Worker 處理

只看正常首次取消的非同步分支:這張圖將原始循序圖簡化為順序對照,左邊保留原圖錯誤,右邊依程式重排。入列在 HTTP 回應之前,通知送達與回應則沒有固定先後。

三次設計輸出中,兩次畫反、一次正確;另做的三次逐箭頭核對都找到了錯誤。對圖時提供的檔案也減少了,不能把結果全歸因於換了提示,更不能保證另開 session 就一定查得出來。

對這份設計,我留下兩個重點:正常首次取消要先完成入列再回應;入列不等於送達,更不等於已經可靠保存。 重複取消也可能回 200,卻不新增通知,不能把所有 200 都解釋成「剛放了一筆通知」。

圖可以簡化,但得標明畫的是哪個分支。這次保留圖,也把核對後的順序與限制一起帶進計畫。

收計畫之前,先問一次有沒有漏想

把查到的問題直接排成開發步驟,還是可能漏東西。收計畫之前,我先把這次修改往外展開一次:

訂單取消修改的六個盤點分支:目的範圍、設計協作、開發驗證、安全品質、發布維運、未決責任

每一枝只要標「本次處理」「沿用既有」「待確認」或「不適用及理由」,不是要求一個小修改把整套系統重做一次。

這一輪真的問出兩件原本不在步驟裡的事:正式授權未完成,不妨礙在本機驗證退款規則,但會擋住把教學 API 當成正式服務上線;程式退版也撤不回已經送出的通知,回復方式得另外想。兩項都進了計畫的「這輪沒解的事」。

圖的用處是讓分歧有位置可談。同一句「取消後發通知」,有人理解成放進佇列就完成,有人以為要等對方收到—指著同一條箭頭問「這裡要等嗎、失敗誰接住」,比再讀一次文字快。Claude Code 可以先讀規格與程式起草,人再拿圖對規則與呼叫順序。

但Mermaid 方便保存與比較,不保證內容正確:本篇那張原始圖就是 Mermaid,順序照樣畫反。先核對依據,再用圖協作。

plan.md 要寫到 RD 知道改哪裡、怎麼驗

討論完不能只留「加強安全性」「補測試」。我會把四千字分析拆成下面這種工作:指定修改位置、說清楚動作,再寫下如何判斷做完。這是待執行的計畫,今天的唯讀分析沒有完成這些測試。

每項工作都用同一條線寫清楚:依據 → 修改位置 → 動作 → 驗收方式 → 證據位置 → 待決與停止條件。 圖與設計理由可以引用原文件,不必整份複製進 plan.md;證據位置則先指定,執行後才填結果,不能預先寫通過。

工作 RD/Claude Code 接下來做什麼 怎麼驗收
先確認規則差異 在 tests/DomainTests/Program.cs 依 rules-v2.md 的 SC-01~SC-07 調整預期 舊實作在哪些情境失敗,能對回這次改變的規則;不為了綠燈任意改預期
修改退款判斷 改 src/Domain/Cancellation.cs,API 繼續轉發結果,不重算、不接金流 七個規格情境通過,再確認公開介面沒有改動
查結果有沒有一路傳對 補 API 邊界測試,讓測試接收端保留必要的通知欄位 HTTP、日誌與通知的 refund_requested 對得上;依序重送不新增通知

授權也寫成工作,不寫成一句「加強安全性」。這份教學 API 目前只讀 X-Actor、有值就繼續;那證明請求帶了欄位,不證明身分,更不證明他有權取消這張訂單。退款算得對,也不能讓任何人都取消別人的訂單。 計畫裡因此多一列:改用已驗證的使用者身分、補拒絕路徑的測試、定義日誌可記哪些欄位—本輪都未實作,列進「這輪沒解的事」,不當成已完成。

同樣地,「依序取消兩次」不等於「同時取消兩次」。目前讀取、判斷、寫回不是整體原子操作,儲存與佇列又在記憶體裡;並行、重啟與外部相容性仍是待驗事項。教學功能可以先完成,但不能據此說正式上線條件都齊了。

換成自己的專案:先設計,再獨立核對

先用本篇的分析包練習,再換成自己的專案。配套目錄為 days/day10/lab-design;目前已整理在本機配套 repo,尚未推送,遠端讀者入口待公開後提供。這是固定快照的閱讀分析包,不含完整 .NET 建置環境。

取得分析包後,在 PowerShell 切到該目錄,先核對既有原件,再選擇是否呼叫 Claude:

cd days/day10/lab-design
python verify.py
# 需先安裝並登入 Claude Code;每次使用新的 run 名稱
python run.py my-design-01 reader

第一行檢查不呼叫模型;看 hashes_match 與 analysis_completed 是否為 true,而 dotnet_executed 應為 false。這只核對固定輸入及第一次分析紀錄,不代表設計正確。第二個指令才會消耗模型用量;runner 把回覆存到 runs/my-design-01/result.md,另留 trace.jsonl、meta.json 與 stderr.txt。名稱若已存在,改用 my-design-02,不要覆蓋舊結果。

先準備指定版本的需求、相關實作與測試,讓 Claude 做設計分析。兩次操作都限制為 Read、Grep、Glob,不只在提示裡說「不要改」。下面是依本次整理補強的設計提示,包含非功能性檢查,尚未用它新增實跑。前述 runner 的 reader 仍使用歷史提示,兩者不能當成同一輪。要套用新提示,可存成 design-request.txt,沿用下方唯讀 CLI 呼叫方式、輸出另存 design-result.md:

以指定版本的需求、決策文件、既有程式與測試為依據,只讀不改檔。
先依目的範圍、設計協作、開發驗證、安全品質、發布維運、未決責任六個分支查漏。
各項標本次處理、引用既有做法、待確認或不適用及理由,附依據。
列已確認與未決的功能需求、品質目標及限制,缺數值就提問,不代填。
追蹤誰算、誰讀、誰傳、誰保存本次修改的值,附檔案位置。
比較至少兩個合理的設計選項與代價;不必要的方案說明為何排除。
檢查相容性、效能、可靠性、安全與可觀測性:
每項列依據、未知、需由誰決定,以及準備怎麼驗。
安全檢查需指出:身分從哪裡驗證、在哪裡檢查訂單權限、哪些欄位能記日誌。
列出合法與越權請求的測試,拒絕時還要驗證狀態未變、沒有新增通知;未知權限不代填。
用 Mermaid 表達必要的 C4 架構視圖、流程與循序關係,分清現況與預期;
C4 先選層次,不把同一程序內的元件畫成獨立服務;三種圖對齊相同範圍與版本。
節點與箭頭對回規格編號或程式位置,不為湊三張圖補不存在的關係。
最後輸出供團隊討論的設計說明與 plan.md 草稿:
每項寫依據、修改位置、動作、驗收方式、證據位置、待決與停止條件。
未決事項列待確認的負責角色,說明阻擋哪一步;不要虛構已有人接受。
分開本輪功能修改與正式上線前的待辦,不把安全提案或未跑測試寫成已完成。

若要用上面的補強提示,存檔後執行:

Get-Content -Raw design-request.txt | claude -p --tools Read,Grep,Glob --allowedTools Read,Grep,Glob > design-result.md

這次看 design-result.md;沿用歷史 runner 的讀者則看 runs/my-design-01/result.md,不要把兩份回覆混為同一次執行。

拿到圖後,把回覆中的 Mermaid 原始碼複製到 diagram-to-check.md,不要先修掉可疑箭頭。這個檔案由你保存;唯讀 Claude 不會替你建立它。

接著把下面的提示存成 check-my-diagram.txt。其中先指名 specs/rules-v2.md、src/Api/Program.cs、src/Domain/Cancellation.cs 與 diagram-to-check.md,讓第二次操作核對同一份快照:

讀取 specs/rules-v2.md、src/Api/Program.cs、src/Domain/Cancellation.cs、diagram-to-check.md。
不修改檔案。逐箭頭核對這張圖與提供的程式,附行號。
若圖是現況,對回程式;若圖是預期行為,對回指定規格,勿混成同一標準。
特別查 await、條件分支、入列、HTTP 回應與背景送達的先後。
核對品質目標是否有來源與驗證方法;未執行的測試不得寫成通過。
分開列出順序錯誤、省略的分支與目前材料無法判定的部分。
不要把「入列完成」解釋成「已送達」或「已可靠保存」。

在同一個分析包目錄執行以下指令,這是新的非互動呼叫,不接續上一輪對話。若結果檔已存在,先換檔名保留前次紀錄。

Get-Content -Raw check-my-diagram.txt | claude -p --tools Read,Grep,Glob --allowedTools Read,Grep,Glob > diagram-check.md

diagram-check.md 由 PowerShell 保存 Claude 的文字回覆;工具白名單限制這次模型能呼叫的工具,不等於檔案讀取範圍隔離。核對完,再由你把接受的設計決定保存為 plan.md,交給下一輪開發。

第二份回答仍要核對。我至少抽一條跨邊界的資料流,從產生值的位置走到接收端,再把成立的結果補回計畫。遇到需求未決,就回去找能決定的人,不讓設計草稿替他批准。

回到一開始:只改一個欄位,Claude 要先查哪些地方?

原本以為只是把 false 改成 true,走完設計才發現,要交代的是四件事:

  • 規則在哪裡算: 退款判斷留在 Domain,API 轉發同一份結果。
  • 結果往哪裡傳: HTTP、日誌與通知 payload 都要看,接收端沒保存不代表內容沒變。
  • 哪些品質條件還沒回答: 相容性、延遲、授權、並行與重啟不能只靠功能測試帶過;已知限制與待驗事項一起交接。
  • 每個邊界怎麼驗: 單元情境對規格,邊界檢查對內容,循序圖回到程式核對順序。

Claude Code 幫我展開資料流、比較方案與起草圖;圖讓團隊對齊理解,Git 留下修改與決定,plan.md 再把共識變成具體開發與驗收工作。查不清楚的地方仍要留下,不能靠一張完整的圖掩蓋。

設計做完,不是多了一份文件,而是下一步要改什麼、怎麼知道改對,都有了依據。 昨天的需求交接摘要走到這裡,才接得上實作。接下來,就從計畫的第一步開始:先寫測試,再讓 Claude 改程式。


參考資料:

本文實作說明

  • 教學輸入為共同訂單服務固定快照 885e521,含 Domain、API、FakeSink、rules-v2.md 與 Day 9 的需求交接摘要;通知決策包含沿用項與未接受的新提案,本篇不把新提案當成已核准規格。退款旗標是記憶體標記,不連付款服務。
實跑 輸入 參數 回合/秒/費用估值(美元) 原件
設計審查包(×3) Domain、API、FakeSink、規格、需求交接摘要 claude -p、sonnet、medium、--safe-mode、--tools Read,Grep,Glob 12/110/0.18;12/111/0.18;12/141/0.21 examples/day10-design-lab/runs/design-01~03(後兩次用乾淨副本):完整回覆含 Mermaid 原圖、trace、來源雜湊。正文引第一次;循序圖順序 01、03 錯,02 對
對圖 seqcheck-01~03 只給 API 與 Domain 兩檔的乾淨副本,提示內附上面那張圖 同上 3/32/0.05;3/17/0.03;3/16/0.03 examples/day10-design-lab/runs/seqcheck-01~03;三次皆判「圖錯:回應應在入列之後」
  • design-01 由 Codex 執行 CLI,seqcheck 由本文作者的 Claude Code session 執行;驅動端只是按下執行的角色,被評的是 Claude Code 的輸出。所有實跑為 AI 操作、唯讀分析,未修改功能、未執行 .NET 測試、未部署。
  • 正文核對影響範圍與入列順序:接收端未保存旗標不足以驗證 payload;payload 改變也不代表送達受影響;原始回覆保留不改,核對版另存 verification-notes.md。引用的 Claude 回覆為原文節錄,重排格式;追蹤表為原表節錄。
  • 非功能性需求盤點、圖碼協作方式、開發與安全工作、官方方法對照及補強提示為編輯整理;安全現況依固定快照原始碼檢查,未新增模型或效能/安全實驗,未完成正式授權機制。
  • 流程圖為編輯依 rules-v2 整理;元件位置圖依固定快照重繪,心智圖為計畫盤點示意。三者均非六次模型實跑的新產物,也不新增驗證結果。
  • 循序圖對照圖依 design-01 原始 Mermaid 與 Program.cs 第 63–89 行重繪,只呈現正常首次取消的非同步通知分支,重複取消與同步通知分支未畫。

官方文件

實作附件

  • 配套 repo:Claude Code, Then What?:Day 10 分析包已整理至本機 days/day10/lab-design,尚未推送,不能把 repo 首頁當成附件已公開。包內包含設計審查原件、三次對圖與 verify.py;公開後補上直接入口。閱讀既有紀錄不需呼叫模型;重跑 runner 會消耗用量,輸出不保證相同。

上一篇
Day 9|需求寫好了,Claude 就能開工嗎?
下一篇
Day 11|計畫寫好了,怎麼讓 Claude 自己改、自己驗?
系列文
買了 Claude Code,然後呢? 共 11 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言