iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0
Claude AI

從零開始 Claude Code:30 天打造 AI 任務管理 Web App系列 第 24 篇

[Day 24] 讓 Claude Code 幫我做 Code Review:從 git diff 開始檢查修改

  • 分享至 

  • xImage
  •  

Day 23 我已經把 Git 加進專案,也建立了第一個基準 commit。
現在每次有修改,都可以先用 Git 看差異,再決定要不要保留。
所以 Day 24 我想換一種方式使用 Claude Code:

不讓它直接寫程式,而是先幫我檢查程式。

也就是今天的主題:
Code Review。
今天一樣不新增 Web App 功能,也不急著修目前已知的問題。
主要想確認:

Claude 能不能看懂目前程式
能不能找到真正的問題
能不能區分問題和推測
能不能只 Review,不直接修改

Code Review 是什麼?

我目前先把 Code Review 理解成:

程式寫完之後,再從另一個角度檢查目前的程式或這次修改有沒有問題。

不是只看:

程式能不能跑

還會看:

邏輯有沒有問題
輸入驗證有沒有漏
錯誤處理是否一致
修改範圍是否合理
有沒有不必要的重複
有沒有違反目前專案架構

Claude Code 很適合拿來協助這件事,因為它可以同時讀:

CLAUDE.md
Git 狀態
程式碼
git diff

再依照目前專案的規則去檢查。


Review 和「幫我修」不一樣

以前遇到問題時,我可能直接說:

幫我修這段程式

這樣 Claude 通常就會開始改檔案。
但今天我刻意把:

Review

和:

修改

分開。
Day 24 的流程是:

先 Review
	↓
找出問題
	↓
判斷問題是不是真的
	↓
再決定要不要修

而不是一看到問題就全部交給 Claude 修改。


第一階段:Baseline Review

一開始,我先讓 Claude Code 對目前已存在的程式做一次 Review。
主要閱讀:

CLAUDE.md
app.py
models/task.py
models/category.py

Claude 為了對照,也看了:

schema.sql
config.py
db.py

我這次特別要求:

不要修改任何檔案
不要執行 git add
不要執行 git commit
不要直接幫我修

Prompt:

Day 24 要進行 Code Review。

目前 Git working tree 是乾淨的,
所以這次不是 Review 未提交的 git diff,
而是先對目前已 commit 的程式做 Baseline Review。

請先閱讀 CLAUDE.md,並檢查:
- app.py
- models/

今天不要修改任何檔案,
不要執行 git add 或 git commit,
也不要直接幫我修問題。

請從以下角度 Review:

1. 有沒有明顯的程式邏輯問題
2. 表單輸入驗證是否完整
3. HTTP 400 / 404 的處理是否一致
4. Task status 的處理是否一致
5. due_date 的處理是否一致
6. Category 查詢與 category_id 的處理有沒有不一致
7. 有沒有明顯重複程式碼
8. 有沒有違反 CLAUDE.md 目前的架構限制
9. 有沒有目前可以先記錄、但不需要立刻修正的問題

請把結果分成:
- 已確認的問題
- 可能的風險
- 目前沒有問題的部分

每一項請附上對應檔案與原因。

不要因為看到問題就自行修改。

Claude 沒有直接相信我的前提

我原本在 Prompt 裡寫:

working tree 是乾淨的

但 Claude 實際查看 Git 後,發現:

CLAUDE.md 有未 commit 的 Day 23 更新

也就是我的前提其實不完全正確。
不過:

app.py
models/

沒有未提交差異,所以 Baseline Review 本身還是可以進行。
後來我也把 Day 23 的 CLAUDE.md 更新 commit 掉,讓工作區重新回到:

nothing to commit, working tree clean

這次經驗也讓我發現,Code Review 時 Claude 不應該只是照著 Prompt 裡的前提回答,最好還是先確認實際專案狀態。


Baseline Review 的結果

這次 Claude 找出的內容不少,但不是每一項都代表「一定要修」。
我最後把結果整理成三類:

✓ 已確認的問題
△ 可能的風險
○ 目前只是觀察或未來維護事項

這樣比較不會把 Claude 提出的每個建議都當成 Bug。


✓ 已確認:title 缺少後端驗證

目前 new_task() 和 edit_task() 都是直接取得:

request.form.get("title", "")

然後寫入資料庫。
雖然 HTML 表單有:

required

但這只是瀏覽器端限制。
如果用 Postman 或直接送 Request,還是可以繞過。
另外:

nullable=False

主要是避免資料庫收到 NULL,不能直接解決:

""

或純空白文字的問題。
所以這項是可以直接從目前程式碼確認的驗證缺口。


✓ 已確認:status 驗證不一致

目前合法 status 有:

todo
in_progress
done

update_status() 已經有檢查:

if new_status not in Task.STATUS_LABELS:
    abort(400)

但是:

new_task()
edit_task()

沒有做相同驗證。
所以目前不同入口對 status 的處理方式不一致。
這也是可以直接從程式碼確認的問題。


✓ 行為已確認,但不一定是 Bug:category 查不到會變成 None

目前:

resolve_category_id()

查不到分類名稱時會回:

None

正常情況下,使用者選「未分類」時,這是合理行為。
但如果繞過前端,送進一個不存在的 category 名稱,它也會變成 None。
在 edit_task() 裡,這代表原本的分類可能被清成未分類。
所以目前可以確定:

查不到 category
→ category_id = None

但這是不是一定要改成 400,還要看之後希望系統怎麼處理非法分類名稱。
因此我把它放在:

✓ 行為已確認
△ 是否需要修正還沒決定

△ 非法 status 寫入 MySQL 的實際結果還沒驗證

Claude 有提醒:

new_task()
edit_task()

目前會讓未驗證的 status 往資料庫走。
但「非法值最後到底會發生什麼」並不能只靠現在的程式碼直接確定。
Claude 提到實際結果可能和:

MySQL sql_mode

有關。
所以這部分不能寫成:

非法 status 一定造成某種結果

目前只能確定:

Flask 這一層沒有先驗證

資料庫實際怎麼處理,要真的送 Request 測過才能確認。


△ edit_task 可能遇到 autoflush

Claude 還注意到一個比較細的地方。
edit_task() 大概是:

先修改 task.title
先修改 task.description
先修改 task.status
		 ↓
呼叫 resolve_category_id()
		 ↓
執行 Category 查詢

SQLAlchemy 在執行查詢前可能進行:

autoflush

把目前 session 中尚未 commit 的修改先送往資料庫。
因此如果前面已經放入非法 status,理論上可能在後面的查詢階段就先發生問題。
不過這次沒有實際測試,所以 Claude 自己也把它標成:

可能風險
尚未驗證

今天就先不改。


○ description 的空字串和 due_date 的 NULL

Claude 注意到:

description 空白
→ ""
due_date 空白
→ NULL

兩者都是可空欄位,但表示方式不同。
這是事實,不過目前沒有功能上的問題。
因為一個是文字欄位,一個是日期欄位,本來就不一定需要使用完全相同的空值表示方式。
所以這項先當作觀察,不列成 Bug。


○ status 定義目前有三份

現在合法 status 同時寫在:

schema.sql
Task.STATUS_LABELS
db.Enum(...)

三個地方都包含:

todo
in_progress
done

目前功能沒有問題。
只是如果以後新增第四個狀態,就有漏改其中一處的可能。
所以這比較像未來維護風險,不是 Day 24 一定要重構的東西。


○ requirements.txt 沒有鎖版本

目前 requirements.txt 只有套件名稱,沒有指定版本。
代表之後重新建立環境時:

pip install -r requirements.txt

可能取得和目前不同版本的套件。
這也是合理的 Review 發現,但不影響現在 Web App 功能,所以先記錄即可。


○ CSRF 目前不處理

Claude 也注意到 POST 路由目前沒有 CSRF 保護。
但它同時有對照 CLAUDE.md:

本機自用
沒有登入
沒有部署
目前不使用 Flask-WTF

所以沒有把它直接列成目前必修項目。
這點對我來說也很重要。
Code Review 不應該變成:

只要大型 Web 專案常見的東西,就全部要求現在加入。

還是要看目前專案本身的範圍。


Review 也確認哪些地方目前沒問題

Claude 不只找缺點,也確認了一些現有設計。
例如 due_date 現在統一走:

parse_due_date()

因此:

空白
→ NULL

格式錯誤
→ 400

new_task() 和 edit_task() 使用同一個 helper,這部分處理是一致的。
另外:

edit
delete
status update

都使用:

Task.query.get_or_404()

不存在的任務會統一得到 404。
Day 20 已經抽出的:

resolve_category_id()
parse_due_date()

也確實減少了一些重複。
剩下 new_task() 和 edit_task() 的欄位讀取雖然相似,但目前只有兩處,而且程式還很簡單,所以沒有必要為了消除一點重複就再增加新的架構。


架構也沒有被 Code Review 帶歪

這次 Claude 也檢查了目前專案架構。
目前仍然沒有:

Application Factory
services/
routes/
Flask-WTF
Flask-Migrate
AJAX
Claude API

路由仍然放在:

app.py

資料庫還是只有:

categories
tasks

也沒有提前加入 AI 欄位。
所以這次 Review 沒有因為想把程式「變得更完整」,就要求我提前擴大架構。


第二階段:真的做一次 Diff Review

前面做的是:

Baseline Review
→ 檢查目前整體程式

但 Day 24 還想實際測一次:

Diff Review
→ 只檢查這一次修改

所以我先把 Day 23 的變更 commit,確認 Git 回到乾淨狀態。
接著故意在 CLAUDE.md 做一個非常小的修改。
原本:

## 目前已完成天數

暫時改成:

## 目前已經完成的天數

只改這一行。


用 Git 確認這次修改

先:

git status

Git 會顯示 CLAUDE.md 被修改。
接著:

git diff

就會看到:

-## 目前已完成天數
+## 目前已經完成的天數

這個例子很小,但剛好適合拿來測 Code Review。


git diff 看完怎麼退出?

如果 git diff 內容比較多,Git 可能會進到分頁檢視畫面。
畫面底下可能出現:

(END)

這時候要退出,直接按:

q

就會回到 PowerShell。
所以我先記:

git diff
   ↓
查看差異
   ↓
按 q 離開

如果 diff 很短,有時會直接顯示完並回到命令列,就不需要另外按 q。


讓 Claude 只 Review 這次 diff

接著我給 Claude:

請 Review 目前尚未 commit 的修改。

先查看 git status 和 git diff。

不要修改任何檔案,
不要執行 git add 或 git commit。

請告訴我:
1. 這次改了哪個檔案
2. 實際改了什麼
3. 這個修改是否合理
4. 有沒有影響專案功能或規則

只做 Review,不要修正。

這次 Review 的範圍非常明確:

只看現在這次未 commit 修改

Diff Review 找到什麼?

Claude 確認:

只有 CLAUDE.md 被修改
沒有 untracked 檔案
diff 只有一行

它也判斷這個修改:

不影響 Web App 功能
不影響技術棧
不影響架構
不改變原本規則內容

但它還注意到一個細節。
雖然只是把:

目前已完成天數

改成:

目前已經完成的天數

但 CLAUDE.md 其他地方仍然使用:

目前已完成天數

作為這個區塊的名稱。
所以 Claude 判斷:

內容本身合理
但文件內的命名變得不一致

如果真的要改標題,就應該同步其他引用;否則就維持原名稱。
這次 Review 沒有把它誇張成嚴重 Bug,而是很清楚地區分:

功能沒有問題
文件一致性需要注意

這正是我想測的效果。


Review 完成後沒有讓 Claude 幫我修

這次 Prompt 已經寫:

只做 Review
不要修正

Claude 也確實沒有改檔案。
我自己把測試文字改回:

## 目前已完成天數

再執行:

git status

確認工作區重新回到乾淨狀態。


Baseline Review 和 Diff Review 的差別

實際做過一次之後,我比較能分清楚兩者用途。

Baseline Review
→ 看目前整體程式狀態
→ 適合找既有問題

Diff Review
→ 只看目前這次修改
→ 適合確認這次改動有沒有問題或超出範圍

它們不是互相取代。
如果正在整理既有專案,可以做 Baseline Review。
如果剛完成一個功能,則更適合 Review git diff。


Code Review 不能取代實際測試

今天另一個很重要的地方,是 Claude 有把一些內容明確標成「推測」。
例如:

非法 status 最後送到 MySQL
實際會發生什麼?

只讀程式碼還不能完全回答。
Code Review 能幫我找:

值得注意的地方
可能的邏輯問題
維護風險
修改範圍

但真正的執行結果還是要測。
所以之後比較完整的流程會是:

Claude Code 修改
	↓
git status
	↓
git diff
	↓
Code Review
	↓
實際測試
	↓
確認結果
	↓
git add
	↓
git commit

而不是:

Claude 說沒問題
     ↓
直接 commit

Day 24 實際確認結果

今天實際做了兩種 Review,最後可以整理成:

Baseline Review                    ✓
Diff Review                        ✓
Claude 能找到已知驗證缺口          ✓
能區分確認問題和未驗證風險         ✓
能對照 CLAUDE.md 的架構限制        ✓
能發現 Prompt 前提和實際 Git 不一致 ✓
能指出小型 diff 的文件一致性問題   ✓
沒有擅自修改檔案                   ✓
沒有擅自 git add / git commit      ✓
知道 git diff 可以按 q 離開        ✓
測試後 working tree 恢復乾淨       ✓

Day 24 最大的改變

做到今天,我開始發現 Claude Code 不一定只能當:

寫程式的人

它也可以當:

規劃者
除錯助手
Code Reviewer

而且不同角色,要使用不同的 Prompt。
Code Review 最重要的也不是:

Claude 找越多問題越好

而是:

它找到的問題,有沒有真的被程式碼、Git diff 和目前專案規則支持。


Day 24 做完後

Day 24 沒有新增 Web App 功能。
但現在我的開發流程又多了一層:

修改前確認 Git
	 ↓
Claude Code 修改
	 ↓
git diff 看真正差異
	 ↓
Claude Code 做 Review
	 ↓
自己判斷問題是否成立
	 ↓
 實際測試
	 ↓
最後才 commit

Day 23 解決的是:

Claude 到底改了什麼?

Day 24 再往前一步:

這些修改到底有沒有問題?

接下來,才要正式進入這個專案最重要的功能之一。
前面的任務新增、編輯、刪除、狀態、分類和資料庫都已經建立起來。
下一步要讓「AI 任務管理」裡的 AI 真正出現。


上一篇
[Day 23] Git + Claude Code:開始用版本控制保護每次修改
系列文
從零開始 Claude Code:30 天打造 AI 任務管理 Web App 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言