Appearance
Codex Code Review 实战:让 AI 帮你找 Bug、并发和数据一致性问题
前面几篇我们已经建立了一套比较完整的 Codex 工作方式:
text
Read
↓
Understand
↓
Plan
↓
Implement
↓
Test代码写完、测试通过以后,是不是就结束了?
还没有。
真实的软件开发通常还有非常重要的一步:
text
Code Review过去 Code Review 主要依赖:
text
开发者自己检查
+
同事 Review现在使用 Codex 以后,可以在正式提交之前增加一层:
text
AI Review于是流程变成:
text
Implement
↓
Test
↓
Codex Review
↓
Developer Review
↓
Commit / PRCodex 非常适合做第一轮代码审查,因为它可以:
text
读取 Git Diff
搜索相关代码
追踪调用链
检查上下文
分析边界条件
寻找潜在 Bug但 Code Review 也不是简单输入一句:
text
帮我看看代码有没有问题就结束了。
如果 Review Prompt 太模糊,Codex 很容易:
text
只检查代码风格
输出一些无关建议
为了找问题而找问题
忽略真正高风险的业务逻辑这一篇就专门讲:
如何让 Codex 真正参与 Code Review,而不是只做一次表面的代码点评。
1. 为什么测试通过以后还需要 Review?
因为:
text
测试通过
≠
代码一定正确测试只能证明:
text
已经覆盖到的场景没有出现问题。
但真实代码还可能存在:
text
未覆盖的边界条件
并发问题
事务问题
幂等问题
性能问题
安全问题
兼容性问题
可维护性问题例如:
java
if (balance.compareTo(amount) >= 0) {
balance = balance.subtract(amount);
updateBalance(balance);
}单线程测试可能全部通过。
但是两个请求同时进入:
text
Request A
读取 balance = 100
Request B
读取 balance = 100两边都认为:
text
余额足够于是可能产生:
text
并发一致性问题普通功能测试未必能够发现。
而 Review 可以从:
text
代码结构
+
调用关系
+
并发模型进一步分析。
2. Codex Review 最适合放在哪个阶段?
推荐:
text
需求
↓
Plan
↓
Implement
↓
Test
↓
Review
↓
Developer Review
↓
Commit为什么不建议代码刚写一半就进行完整 Review?
因为:
text
代码还没完成
Diff 还在变化
测试还没跑这时候 Review 很容易浪费上下文。
更适合在:
text
功能基本完成
+
相关测试通过以后进行。
3. Review 的第一步:先看 Git Diff
Codex 做 Review 时,最重要的输入之一就是:
text
Git Diff开发者平时也会:
bash
git status
git diffCodex 同样可以基于这些变更理解:
text
这次到底改了什么例如:
text
修改了 5 个文件
UserBalance.java
UserBalanceService.java
UserBalanceServiceImpl.java
WalletTransactionType.java
UserBalanceServiceTest.java相比让 Codex:
text
重新 Review 整个 Repository基于当前 Diff 更容易聚焦:
text
本次变更4. 为什么 Review 不应该只看 Diff?
只看 Diff 也存在问题。
例如当前修改:
java
userBalanceService.opsBalance(uid, amount);仅仅看这一行,很难判断:
text
opsBalance 内部是否有事务?
是否幂等?
是否允许 amount 为负?
是否记录流水?所以真正有效的 Review 应该是:
text
Git Diff
+
Relevant Context也就是:
text
先看变更
再读取相关上下文可以直接告诉 Codex:
text
Review 当前 Git Diff。
必要时读取相关调用方、被调用方法、Entity、Mapper 和测试,
不要只根据 Diff 表面判断。5. 不推荐:帮我 Review 一下
例如:
text
帮我 Review 当前代码。问题和之前的:
text
帮我优化一下很类似。
Codex 不知道你最关心:
text
代码风格?
Bug?
性能?
事务?
安全?
兼容性?结果很可能输出:
text
这个方法可以拆分
变量名可以更清晰
建议增加注释这些不是完全没价值。
但如果这是一个:
text
钱包扣款需求,真正应该优先关注的可能是:
text
重复扣款
超额扣款
并发
事务
幂等所以 Review 也需要:
text
明确目标6. 一个通用的 Review Prompt
可以直接使用:
text
Review 当前 Git Diff。
不要修改代码。
必要时读取相关上下文,
不要只检查 Diff 表面。
重点检查:
1. 明确的逻辑 Bug
2. 空指针
3. 边界条件
4. 异常处理
5. 并发问题
6. 事务问题
7. 幂等问题
8. 数据一致性
9. 性能问题
10. 向后兼容
11. 安全问题
12. 测试遗漏
对于每个问题输出:
- 严重程度
- 文件
- 代码位置
- 问题原因
- 触发条件
- 可能后果
- 建议修复方式
只报告有明确依据的问题。
如果无法确认,
标记为“需要确认”,不要当成确定 Bug。
不要为了输出内容而猜测问题。最后几句话非常重要。
7. 为什么要告诉 Codex“不要为了 Review 而找问题”?
AI 做 Review 时可能存在一个倾向:
text
用户让我找问题
↓
那我最好输出几个问题于是可能出现:
text
理论上可以优化
可能存在风险
建议考虑……但这些问题:
text
不一定真实所以应该明确:
text
没有问题也可以说没有发现明确问题。例如:
text
只报告能够从代码中得到明确证据的问题。
如果只是风格偏好,
不要作为 Bug 输出。这会明显提高 Review 结果的信噪比。
8. Review 结果最好按严重程度分级
不是所有问题都一样重要。
例如:
text
变量名不够清晰和:
text
可能导致用户重复扣款显然不是一个级别。
可以让 Codex 使用:
text
P0
P1
P2
P3例如:
text
P0
→ 严重数据 / 资金 / 安全事故
P1
→ 高概率生产 Bug
P2
→ 边界条件 / 性能 / 维护风险
P3
→ 低风险改进或者:
text
Critical
High
Medium
Low重点不是具体名称。
而是:
text
让开发者快速知道先看什么9. 一个推荐的严重程度定义
可以直接写进 Prompt:
text
严重程度:
P0:
可能导致资金错误、数据损坏、严重安全问题。
P1:
可能导致主要业务错误、重复执行、事务不一致。
P2:
边界条件 Bug、明显性能问题、异常处理问题。
P3:
低风险维护性问题。
不要把纯代码风格问题标记为 P0/P1。这样 Review 结果会更容易处理。
10. Java Review:空指针
Java 项目中非常常见。
例如:
java
User user = userMapper.selectById(uid);
return user.getName();如果:
text
user 不存在就会:
text
NullPointerExceptionReview 时可以让 Codex 重点检查:
text
Mapper 查询结果
Map.get
List.get
Optional
外部 API 返回值
JSON 字段
数据库 nullable 字段Prompt:
text
重点检查所有新代码中的 null 假设。
特别关注:
- Mapper 查询可能返回 null
- Map.get
- 外部接口返回值
- nullable 数据库字段
- List 为空11. Java Review:BigDecimal
资金项目中非常重要。
常见错误:
java
if (amount.doubleValue() > 0) {
}或者:
java
new BigDecimal(0.1)或者:
java
amount.equals(new BigDecimal("1.00"))可能存在:
text
精度
scale
比较行为问题。
Review 可以明确:
text
检查所有金额处理:
1. 是否使用 BigDecimal
2. 是否使用 double / float
3. compareTo 是否正确
4. 除法是否指定 scale 和 rounding
5. 是否可能产生负余额
6. 金额单位是否一致对于:
text
支付
钱包
奖励
结算这应该是固定检查项。
12. Java Review:事务
Spring 项目另一个重点:
text
@Transactional例如:
text
创建提现订单
↓
扣减余额如果:
text
订单创建成功
余额扣减失败应该怎么办?
或者反过来:
text
余额扣了
订单没创建就可能出现:
text
数据不一致Review 时应该检查:
text
事务边界
事务传播
异常是否触发回滚
自调用
异步方法
跨服务调用13. 一个事务 Review Prompt
例如:
text
重点 Review 当前修改中的事务一致性。
请检查:
1. 哪些方法有 @Transactional
2. 事务边界是否覆盖完整业务操作
3. 是否存在 Spring 自调用导致事务失效
4. 是否捕获异常以后没有重新抛出
5. 是否存在 checked exception 不回滚
6. 是否在事务中执行耗时 RPC
7. 是否存在数据库成功但 MQ / RPC 失败
8. 是否存在余额变化与流水不一致
只报告能够结合实际代码说明的问题。这比:
text
看看事务有没有问题更有效。
14. Java Review:并发
并发 Bug 是 AI Review 很值得尝试的领域之一。
例如:
text
读取余额
↓
判断余额
↓
扣减余额在单线程中完全正常。
但两个线程:
text
Thread A
Read 100
Thread B
Read 100
Thread A
-80
Thread B
-80就可能出现问题。
所以 Review 时可以重点搜索:
text
read-modify-write模式。
例如:
text
查询
↓
Java 判断
↓
更新然后分析:
text
是否存在锁
乐观锁
CAS
条件 UPDATE
数据库事务
唯一约束15. 并发 Review 模板
text
重点 Review 当前修改中的并发安全。
检查:
1. 是否存在 read-modify-write
2. 两个请求同时执行会发生什么
3. 是否依赖先查后改
4. 是否存在乐观锁
5. 是否存在数据库条件更新
6. 是否存在唯一约束
7. Redis 锁是否可能过期
8. 锁粒度是否正确
9. 是否存在重复执行
10. 是否可能产生负余额
对于每个并发问题,
给出一个具体的双请求执行时序。最后一句特别有用。
不要只让 Codex 说:
text
可能存在并发问题而是要求它:
text
给出执行时序16. 什么叫“给出并发执行时序”?
例如:
text
初始余额:100
Request A
→ 查询余额 = 100
Request B
→ 查询余额 = 100
Request A
→ 判断 100 >= 80
→ 成功
Request B
→ 判断 100 >= 80
→ 成功
Request A
→ 更新余额 20
Request B
→ 更新余额 20最终:
text
系统记录两次扣款
余额却只减少一次或者根据实现产生:
text
负余额这种 Review 结果就非常有价值。
因为它给出了:
text
Bug 如何真实发生17. Review:幂等
涉及:
text
支付回调
充值
提现
MQ
定时任务
第三方通知都应该重点检查:
text
Idempotency也就是:
text
同一个业务请求执行两次,
结果是否仍然正确?例如支付回调:
text
第一次
→ 入账 100
第三方重试
→ 再次回调
第二次
→ 还能不能再入账 100?如果可以:
text
严重 Bug18. 幂等 Review 模板
text
重点检查当前修改的幂等性。
对于所有:
- API
- MQ Consumer
- 定时任务
- 支付回调
- 充值确认
- 重试逻辑
分析:
同一个业务请求执行两次会发生什么?
重点检查:
1. 是否存在业务唯一 ID
2. 是否存在数据库唯一约束
3. 是否只在 Java 层判断
4. 判断和写入是否原子
5. 并发重复请求是否仍然安全
6. 失败重试是否可能重复执行副作用
如果发现问题,
给出重复执行的具体路径。19. Review:数据库唯一约束
很多代码看起来有幂等判断:
java
if (!exists(sourceId)) {
insert(record);
}但并发情况下:
text
Request A
exists = false
Request B
exists = false
A insert
B insert如果数据库没有:
text
UNIQUE仍然可能重复。
所以涉及业务唯一性的 Review,要同时检查:
text
Java 判断
+
数据库约束而不是只看 Service。
20. Review:MQ 重复消费
MQ Consumer 通常必须考虑:
text
消息重复例如:
java
@RabbitListener
public void handle(OrderPaidEvent event) {
rewardService.reward(event.getUid(), event.getAmount());
}Review 应该继续问:
text
MQ 重投以后怎么办?
Consumer 崩溃重启怎么办?
业务执行成功但 ACK 失败怎么办?
reward 是否幂等?所以对于 MQ 代码:
text
消费成功不是唯一关注点。
还应该看:
text
重复消费
失败重试
ACK
死信
副作用21. Review:SQL 性能
Code Review 也可以检查性能。
例如:
java
for (Long uid : uids) {
User user = userMapper.selectById(uid);
}可能产生:
text
N + 1如果:
text
uids = 1000就可能执行:
text
1000 次 SQLReview 时可以要求:
text
检查新增代码是否存在:
1. 循环 SQL
2. N+1
3. 全表查询
4. 无分页大结果集
5. 不必要的 count
6. 缺失索引的查询条件
7. 重复数据库查询22. Review:Redis
Redis 相关代码可以重点检查:
text
Key
TTL
并发
缓存一致性
序列化
缓存穿透
缓存击穿
锁例如:
text
数据库更新成功
↓
Redis 删除失败会不会导致:
text
旧缓存继续存在?如果是 Redis Lock:
text
锁有没有唯一 owner?
释放锁时是否可能删掉别人的锁?
TTL 是否可能提前过期?
业务执行时间是否超过 TTL?这些都很适合专项 Review。
23. Review:接口兼容性
一个很容易被忽略的问题是:
text
代码逻辑没 Bug
但是 API 不兼容了例如:
text
字段改名
字段删除
类型变化
null 行为变化
错误码变化
分页结构变化
枚举值变化如果还有:
text
旧 App
第三方调用方
其他微服务就可能直接出问题。
Review Prompt:
text
检查当前 Diff 的向后兼容性。
重点检查:
1. API 字段删除
2. 字段改名
3. 字段类型变化
4. null 行为变化
5. 枚举变化
6. 错误码变化
7. 默认值变化
8. 数据库字段兼容
9. 旧调用方是否仍然可用24. Review:异常处理
常见问题:
java
try {
doSomething();
} catch (Exception e) {
log.error("error", e);
}异常被:
text
吃掉以后,调用方可能认为:
text
执行成功特别是事务方法中:
text
catch
↓
不抛出可能导致事务行为和预期不同。
Review 可以检查:
text
异常是否被吞
错误码是否正确
是否错误重试
是否重复记录日志
是否暴露敏感信息25. Review:测试是否真的有效
有测试不代表测试有价值。
例如:
java
@Test
void testFreeze() {
assertTrue(true);
}当然没意义。
更现实的问题是:
text
测试只覆盖正常路径没有覆盖:
text
余额不足
重复请求
并发
null
异常
回滚
边界值所以 Code Review 也应该 Review:
text
Test Diff例如:
text
检查新增测试是否真正覆盖本次修改风险。
重点关注:
1. 正常路径
2. 边界值
3. 异常路径
4. 重复执行
5. 并发
6. 事务回滚
7. 历史数据兼容
指出当前修改中重要但没有测试覆盖的场景。26. 不要让 Codex 自动修改所有 Review 问题
这是一个很重要的习惯。
第一次 Review 推荐:
text
只输出问题
不要修改代码为什么?
因为 Review 阶段的目标是:
text
发现问题如果一边 Review:
text
一边自动修改就会导致:
text
原始 Diff
↓
Review
↓
产生新 Diff
↓
新的代码又没有 Review流程会变得混乱。
更好的方式:
text
Review
↓
问题列表
↓
Developer 判断
↓
选择问题
↓
Fix
↓
Test
↓
Review Again27. Review 发现问题以后怎么修?
例如 Codex 输出:
text
P1
UserBalanceServiceImpl.java
freeze() 存在并发超额冻结风险。不要直接:
text
全部修复。可以:
text
修复 Review 中的 P1-1。
要求:
1. 使用项目现有乐观锁机制
2. 不新增 Redis 锁
3. 不修改 API
4. 增加并发测试
完成后运行相关测试。
不要处理其他 Review 项。这样修改范围更可控。
28. 修复以后再 Review 一次
完整闭环应该是:
text
Review
↓
Find Issue
↓
Fix
↓
Test
↓
Review Again因为:
text
修 Bug本身也可能:
text
产生新 Bug尤其涉及:
text
并发
事务
数据库最好重新检查。
29. 一个资金业务专项 Review 模板
如果项目涉及:
text
钱包
支付
充值
提现
奖励
结算可以直接保存下面这套:
text
Review 当前 Git Diff。
不要修改代码。
这是资金相关代码,
优先检查正确性和数据一致性,
不要优先讨论代码风格。
重点检查:
1. 重复入账
2. 重复扣款
3. 超额扣款
4. 负余额
5. BigDecimal 精度
6. 事务边界
7. 异常回滚
8. 并发 read-modify-write
9. 幂等
10. 数据库唯一约束
11. MQ 重复消费
12. 定时任务重复执行
13. 流水和余额是否一致
14. sourceId / businessId 去重
15. API 向后兼容
必要时读取:
- Service
- Mapper
- Entity
- SQL
- 调用方
- 测试
每个问题输出:
严重程度:
文件:
位置:
问题:
触发路径:
后果:
证据:
建议:
只报告有实际代码依据的问题。
无法确认时明确标记“需要确认”。
不要为了输出 Review 内容而猜测问题。30. 一个普通 Java 项目的 Review 模板
如果不是资金系统,可以使用更通用的版本:
text
Review 当前 Git Diff。
不要修改代码。
重点检查:
1. 逻辑正确性
2. null
3. 边界条件
4. 异常处理
5. 资源释放
6. 事务
7. 并发
8. 性能
9. SQL
10. 安全
11. API 兼容
12. 测试覆盖
必要时读取相关上下文。
只报告明确、可操作的问题。
不要输出纯个人代码风格偏好。
按照 P0 / P1 / P2 / P3 排序。31. Review 可以拆成多轮
对于大型 Diff,一次 Review 所有问题可能效果并不好。
例如:
text
50 个文件
3000 行修改可以拆成:
text
第一轮
→ Correctness
第二轮
→ Concurrency & Transaction
第三轮
→ Performance
第四轮
→ Compatibility
第五轮
→ Tests例如第一轮:
text
只检查业务正确性。第二轮:
text
只检查事务、并发和幂等。这种:
text
专项 Review通常比:
text
一次检查所有东西更加深入。
32. 什么情况下值得多轮 Review?
比较适合:
text
大型重构
支付
钱包
认证
数据库迁移
跨模块修改
复杂并发
高风险线上修复简单需求:
text
修改一个 DTO就没必要:
text
Review 五轮仍然应该按照:
text
风险决定 Review 深度。
33. Codex Review 不能替代人工 Review
这是必须明确的一点。
Codex 可以帮助:
text
扫描 Diff
追踪调用
发现模式
检查边界
寻找潜在风险但是它并不知道所有:
text
产品规则
历史背景
线上约束
团队决策
隐藏业务需求例如:
text
一个字段看起来完全没用了Codex 可能建议删除。
但你知道:
text
旧版 App 仍然依赖所以最终责任仍然属于:
text
Developer34. AI Review 最合理的位置是什么?
不是:
text
AI Review
替代
Human Review而是:
text
Developer
↓
Codex First Review
↓
修复明显问题
↓
Human Review可以理解成:
text
AI
→ 第一层过滤器
Developer
→ 最终决策者这样可以减少很多:
text
低级错误
明显遗漏
重复劳动把人工精力留给:
text
业务
架构
设计
风险判断35. 推荐的完整 Codex Review 工作流
最终可以固定成:
text
① 完成实现
↓
② 运行测试
↓
③ git status
↓
④ git diff
↓
⑤ Codex Review
↓
⑥ 按严重程度检查问题
↓
⑦ 修复确认的问题
↓
⑧ 再次运行测试
↓
⑨ 再次 Review
↓
⑩ Developer Review
↓
⑪ Commit / PR如果是高风险代码:
text
普通 Review
↓
事务专项 Review
↓
并发专项 Review
↓
幂等专项 Review
↓
兼容性 Review36. 最后怎么理解 Codex Code Review?
如果只记一句话:
text
不要让 Codex 只评价代码写得好不好。
要让它寻找:
什么情况下这段代码会出错。一个好的 Review 不是:
text
建议优化方法命名。而是能够告诉你:
text
当两个提现请求同时到达时:
A 和 B 都读取 balance = 100
A 判断余额足够
B 也判断余额足够
然后两个请求都执行扣减
当前实现没有乐观锁、
条件 UPDATE 或其他并发保护
因此可能产生重复扣款或余额错误。这才是真正有价值的:
text
Code Review最终可以把整个 Codex 开发流程串起来:
text
AGENTS.md
↓
Prompt
↓
Explore
↓
Plan
↓
Implement
↓
Test
↓
Review
↓
Developer Review其中 Review 解决的是:
text
代码已经写出来以后,
还有哪些问题没有被测试发现?当 Codex 不再只是:
text
帮你写代码而开始参与:
text
理解需求
设计方案
实现代码
执行测试
检查 Diff
Code Review它才真正从一个:
text
AI 代码生成器变成:
text
参与软件工程全过程的 Coding Agent