ChatGPT Plus / Pro + Codex 老项目实战:如何接手 Legacy Code、定位 Bug、重构遗留系统
很多 AI 编程教程,演示的项目都非常“干净”。
比如:
新建一个 Next.js 项目
然后:
让 ChatGPT 写登录页面
再:
让 Codex 增加数据库
这种场景当然适合展示 AI 的能力。
但真实开发环境往往完全不是这样。
更多时候你面对的是:
一个运行了 5 年的项目
里面可能有:
没有文档
没有测试
命名混乱
历史代码没人敢动
数据库字段意义不清楚
业务逻辑散落在几十个文件
甚至:
前一个开发已经离职
你接手以后,第一件事并不是:
写新功能。
而是:
先弄明白这个系统到底是怎么运行的。
这也是我认为 ChatGPT、Plus、Pro、Codex 真正开始体现价值的一个场景。
因为相比从零生成代码,
理解 Legacy Code,往往才是开发里最耗时间的事情之一。
一、什么是 Legacy Code?
Legacy Code 一般翻译成:
遗留代码
但很多人会误以为:
Legacy Code = 很烂的代码
其实不一定。
一个系统可能代码写得很好。
但是:
作者已经离职
或者:
没有文档
或者:
没人敢修改
它一样可能逐渐变成 Legacy System。
从开发者角度,我更愿意把它理解为:
你无法快速判断修改后会不会出问题的代码。
例如你看到:
if (status === 3) {
updateUser()
}
问题来了:
status === 3
到底代表:
已支付?
已完成?
已审核?
已关闭?
没人知道。
你只能继续往下追。
二、老项目最难的不是“写代码”,而是建立 Mental Model
开发者接手一个新项目时,真正需要建立的是:
Mental Model
也就是:
对系统的整体理解
你需要知道:
请求从哪里进来
↓
经过哪些 Service
↓
修改哪些数据
↓
触发哪些副作用
↓
最终返回什么
如果没有这个模型,
你看到的永远只是:
一个文件
但真实系统可能是:
Controller
↓
Service
↓
Repository
↓
Database
↓
Event
↓
Queue
↓
Worker
↓
Notification
所以我现在接手陌生项目时,很少第一步就修改代码。
更常做的是:
Map the system first.
三、第一个 Codex Prompt:给整个项目画地图
进入陌生仓库以后,可以先让 Codex:
先不要修改代码。
请阅读当前仓库,
帮助我建立这个系统的整体架构地图。
重点找到:
1. 程序入口;
2. API 入口;
3. 核心业务模块;
4. 数据库访问层;
5. 用户认证流程;
6. 消息队列;
7. 定时任务;
8. 外部服务;
9. 配置文件;
10. 测试目录。
然后输出:
System Overview
Request Flow
Core Modules
External Dependencies
Critical Data Flow
Potential High-Risk Areas
暂时不要修改代码。
这一步的目标并不是让 AI:
帮我总结项目
而是建立:
System Map
例如它最后可能告诉你:
Browser
↓
Nginx
↓
Node API
↓
OrderService
↓
PaymentService
↓
MySQL
↓
RabbitMQ
↓
Settlement Worker
你瞬间就比:
一个文件一个文件打开
效率高很多。
四、第二步:找到“真正的核心代码”
一个老项目可能有:
2000 个文件
但真正决定业务的核心文件可能只有:
20~50 个
所以我会继续让 Codex 做:
不要修改代码。
在当前项目中识别“高业务价值代码”。
标准:
1. 被大量模块依赖;
2. 处理核心业务;
3. 涉及数据库写入;
4. 涉及支付;
5. 涉及权限;
6. 涉及账户余额;
7. 涉及订单状态;
8. 修改后影响范围大。
给我列出最关键的 20 个文件。
每个文件说明:
- 作用;
- 谁调用它;
- 它调用谁;
- 修改风险;
- 是否有测试保护。
按风险排序。
然后你可能得到:
High Risk
例如:
PaymentService
OrderStateMachine
UserPermission
SettlementWorker
BalanceRepository
以及:
Low Risk
例如:
Formatter
UI Component
Date Utils
这一步特别重要。
因为:
不是所有代码都值得投入同样的理解成本。
五、Legacy 项目最应该先找“状态机”
很多复杂业务系统,真正难维护的地方都是:
状态变化
例如订单:
Created
↓
Paid
↓
Shipping
↓
Completed
但是老项目里可能写成:
0
1
2
3
4
5
8
10
然后你会发现:
status = 5
在 A 文件代表:
已完成
在 B 文件又有:
if status >= 5
在 C 文件:
status !== 8
这种代码极其危险。
六、Prompt:自动还原业务状态机
可以让 Codex:
不要修改任何代码。
请调查订单状态字段的所有使用位置。
目标:
还原完整订单状态机。
请找出:
1. 所有可能状态;
2. 每个状态的业务含义;
3. 哪些代码会修改状态;
4. 每个状态允许转换到哪些状态;
5. 哪些转换可能是非法的;
6. 是否存在直接更新数据库绕过业务层;
7. 是否有重复状态判断;
8. 是否存在 Magic Number。
最终输出:
State
Meaning
Allowed Transitions
Modified By
Risk
最后用文字画出完整状态流。
这个 Prompt 对:
订单
支付
审批
工单
物流
用户状态
都很好用。
七、Magic Number 是 Legacy Code 的经典问题
例如:
if (order.status === 7) {
谁知道 7 是什么?
可能要翻:
数据库
再翻:
接口
再翻:
历史提交
最后才找到:
7 = Cancelled
这种东西 AI 很适合帮你批量定位。
八、Prompt:找出所有 Magic Number
扫描与业务逻辑相关的 Magic Number。
重点寻找:
- 状态码;
- 角色码;
- 类型码;
- 权限码;
- 支付状态;
- 订单状态;
- 时间常量;
- 金额阈值。
不要修改。
请输出:
Value
File
Meaning
Evidence
Risk
如果同一个数字在不同位置可能有不同含义,
单独标记。
最后建议哪些值应该被替换成 Enum 或常量。
例如把:
if (role === 3)
变成:
if (role === UserRole.Admin)
可维护性会高很多。
但注意:
不要第一步就全项目自动替换。
先识别。
再逐步改。
九、老项目最大的危险:没有测试
现实中非常常见:
核心业务代码
↓
0 个测试
这时你让 Codex:
帮我重构
风险非常高。
因为你根本不知道:
改完以后行为有没有变化
所以重构 Legacy Code 最重要的步骤之一是:
Characterization Tests
中文可以理解成:
特征测试
它的目的不是判断代码:
应该怎么运行
而是记录:
现在实际上怎么运行
十、先写 Characterization Tests,再重构
比如一个非常奇怪的函数:
function calculatePrice(user, order, channel) {
// 300 lines...
}
你不知道它为什么这么写。
不要直接重构。
先让 AI:
不要修改 calculatePrice 的实现。
请分析当前函数。
目标不是判断业务设计是否合理,
而是固定当前行为。
根据现有代码增加 Characterization Tests。
重点覆盖:
1. 普通用户;
2. VIP 用户;
3. 优惠券;
4. 满减;
5. 特殊渠道;
6. 空订单;
7. 边界金额;
8. 历史兼容逻辑。
这些测试的目的:
确保未来重构前后,
对相同输入产生相同结果。
暂时不要优化函数。
这一步很重要。
流程变成:
Unknown Legacy Behavior
↓
Characterization Tests
↓
Behavior Locked
↓
Refactor
比直接重构安全得多。
十一、AI 重构最容易犯的错误:顺手“修正”历史行为
比如旧代码:
if (amount > 100) {
discount = 10
}
你可能觉得:
100 元应该也优惠
于是 AI 修改成:
if (amount >= 100)
从代码审美看似乎更合理。
但这实际上属于:
业务行为变更
而不是:
重构
所以我会非常明确地告诉 Codex:
Refactoring Rule:
Do not fix suspicious business behavior
unless the task explicitly asks for it.
If current behavior looks strange,
report it separately.
Preserve behavior during refactoring.
这条很重要。
因为:
Bug Fix
和:
Refactor
必须尽量分开。
十二、推荐的 Legacy Code 重构流程
我现在更倾向于:
Explore
↓
Map
↓
Test
↓
Refactor
↓
Compare
↓
Review
而不是:
Read
↓
Rewrite
完整一点就是:
1. 找到入口
2. 追踪调用链
3. 理解数据流
4. 找出业务状态
5. 找出隐藏规则
6. 写 Characterization Tests
7. 确认测试通过
8. 小范围重构
9. 再跑测试
10. Review Git Diff
十三、Prompt:让 Codex 追踪一个 Bug 的完整调用链
这是接手旧系统非常高频的 Prompt:
调查以下 Bug:
[Bug 描述]
不要先修改代码。
请从用户操作开始追踪完整调用链:
UI
↓
API
↓
Controller
↓
Service
↓
Repository
↓
Database
↓
Async Job
如果某个阶段不存在可以跳过。
请找出:
1. 数据从哪里进入;
2. 在哪里被转换;
3. 在哪里被校验;
4. 在哪里写入数据库;
5. 是否触发异步任务;
6. 错误最可能在哪里产生;
7. 是否存在多个相似实现。
最后输出:
Execution Path
Most Likely Root Cause
Evidence
Potential Side Effects
Minimal Fix
暂时不要修改。
对于:
“用户支付成功但订单没更新”
这种问题尤其有用。
十四、复杂 Bug 一定要区分“症状”和“根因”
例如:
用户反馈:
偶尔重复扣款
你看到日志:
Payment API 被调用两次
很多人第一反应:
前端按钮 disable 一下
但真正原因可能是:
请求重试
或者:
Webhook 重复
或者:
消息队列重复消费
或者:
接口没有幂等
所以 AI 调试时可以要求:
请严格区分:
Symptom
表面现象
Root Cause
真正根因
Trigger
触发条件
Amplifier
让问题更严重的因素
不要把第一个发现的问题直接认定为 Root Cause。
这在复杂系统里非常有效。
十五、Legacy 系统一定要检查幂等性
尤其是:
支付
退款
积分
余额
订单
消息队列
Webhook
非常容易出现:
第一次请求成功
但客户端没收到。
于是:
自动重试
服务器再次处理。
然后:
重复扣款
重复发积分
重复发货
所以可以直接:
检查以下业务流程是否具备幂等性:
[业务流程]
重点检查:
- HTTP retry
- message retry
- webhook retry
- duplicate submission
- concurrent request
- worker retry
找出所有可能导致重复执行的位置。
对每个位置说明:
Operation
Current Protection
Failure Scenario
Data Impact
Recommended Idempotency Strategy
不要修改代码。
这条非常适合生产系统。
十六、老系统还要重点检查“事务边界”
例如:
创建订单
↓
扣库存
↓
扣余额
↓
写日志
如果中间:
扣余额失败
前面的库存怎么办?
如果没有正确的 Transaction,很容易产生:
脏数据
十七、Prompt:数据库事务审查
调查当前业务流程的事务完整性:
[流程]
请找到所有数据库写操作。
分析:
1. 哪些操作必须原子完成;
2. 当前是否处于同一个 Transaction;
3. 中间失败会发生什么;
4. 是否可能出现部分成功;
5. 是否存在并发修改;
6. 是否需要锁;
7. 是否存在重复写入;
8. 是否存在补偿逻辑。
输出:
Operation
Transaction Boundary
Failure Scenario
Current Behavior
Data Risk
Recommendation
暂时不要修改代码。
这个 Prompt 对:
订单
库存
账户余额
结算
特别有价值。
十八、AI 很适合帮你找“隐式业务规则”
所谓隐式规则,就是:
代码里有
但:
文档里没有
例如:
if (user.createdAt < '2022-01-01') {
fee = 0
}
这可能代表:
老用户免手续费
但新人完全不知道。
十九、Prompt:自动提取业务规则
不要修改代码。
阅读与以下模块相关的所有业务逻辑:
[模块]
尝试提取代码中的隐式业务规则。
重点寻找:
- if / else 业务条件;
- 特殊日期;
- 特殊用户;
- 特殊渠道;
- 特殊金额;
- 特殊状态;
- 白名单;
- 黑名单;
- 历史兼容判断;
- feature flag。
每条规则输出:
Rule
Code Location
Business Meaning
Confidence
Risk If Removed
是否已经有文档说明
最后整理成一份 Business Rules Summary。
这一步甚至可以直接帮助你重新写项目文档。
二十、不要一次性重构 5000 行代码
AI 很容易给人一种错觉:
既然它改代码很快,那就一次改完。
但 Legacy Code 最忌讳:
Big Bang Refactor
例如:
一次改 80 个文件
问题来了:
如果上线出 Bug,
你很难判断:
到底哪一步出的问题
更好的方式是:
Small Refactor
↓
Test
↓
Commit
↓
Next Refactor
二十一、把大型重构拆成可回滚的小任务
可以让 Codex:
我要重构以下 Legacy Module:
[路径]
不要直接修改。
请把重构拆成一组小 Task。
要求每个 Task:
- 可以独立提交;
- 可以独立测试;
- 尽量不改变外部行为;
- 修改文件尽可能少;
- 出问题可以单独回滚。
推荐结构:
Task 1
Add tests
Task 2
Extract constants
Task 3
Extract pure function
Task 4
Separate database access
Task 5
Improve typing
Task 6
Remove dead code
每一步说明:
Goal
Files
Risk
Tests
Rollback Strategy
这样 AI 会更像:
一个有纪律的开发团队
而不是:
一次性代码生成器
二十二、Dead Code 清理非常适合 Codex,但不要盲删
老项目经常存在:
旧接口
旧函数
旧配置
废弃 Feature
但问题是:
没人敢删
因为不知道还有没有地方调用。
AI 可以帮你做静态调查。
Prompt:Dead Code Audit
扫描项目中的潜在 Dead Code。
包括:
- 未使用函数;
- 未使用组件;
- 未使用 API;
- 未使用配置;
- 未使用环境变量;
- 未使用数据库字段;
- 已废弃 Feature Flag;
- 永远不会进入的条件分支。
不要删除。
每个候选项输出:
Location
Why It Looks Unused
References Found
Runtime Risk
Confidence
Safe To Remove?
Yes / Maybe / No
只有高置信度项目才建议删除。
最后一句很关键:
只有高置信度项目才建议删除
因为动态语言项目里:
Reflection
Dynamic Import
Config Loading
都有可能让静态分析误判。
二十三、接手老项目时,Git History 也是上下文
代码只能告诉你:
现在是什么
Git 历史很多时候能告诉你:
为什么变成这样
比如某个奇怪判断:
if (country === "US" && version < 4) {
你看不懂。
但 Git Commit 可能写:
fix legacy mobile checkout compatibility
立刻就懂了。
所以在支持 Git 的开发环境中,可以让 Agent 帮忙调查:
调查这个代码块的历史原因:
[文件 / 函数]
不要修改代码。
检查相关 Git History。
找出:
1. 最早什么时候加入;
2. 为什么加入;
3. 后续修改过几次;
4. 哪些 Bug 与它相关;
5. 当前是否仍然需要;
6. 删除可能造成什么兼容风险。
不要仅根据当前代码猜测。
这是 AI 接手 Legacy Code 很有价值的一个方向。
二十四、ChatGPT 和 Codex 在老项目里的分工
如果是我自己使用,我会比较倾向:
ChatGPT
做:
业务分析
架构理解
技术方案
风险讨论
需求拆解
而:
Codex
做:
搜索仓库
追踪调用
修改代码
跑测试
分析 Git Diff
执行验证
可以理解成:
ChatGPT
=
Thinking Partner
Codex
=
Engineering Agent
对于简单任务,两者可以合在一起。
但对于复杂 Legacy 系统:
先想清楚
再:
执行
仍然非常重要。
二十五、Plus / Pro 用户真正应该看“任务复杂度”
很多人比较 ChatGPT Plus、Pro 时,习惯只问:
哪个回答更强?
对于开发者,我认为可以换一个角度:
我的任务复杂度多高?
例如:
Level 1
解释代码
Level 2
修改单个函数
Level 3
修复跨文件 Bug
Level 4
理解完整模块
Level 5
跨模块开发 + 测试
Level 6
大型 Legacy 系统重构
越往后,
你需要的就越不是:
一次回答
而是:
连续的 Agent 工作过程
所以开发者使用 ChatGPT Plus、Pro、Codex 时,真正值得观察的是:
我每天是在问多少个问题,还是在交给 AI 多少个工程任务?
这两个使用模式完全不同。
二十六、Legacy 项目非常适合建立 AGENTS.md
如果这是一个长期维护的旧项目,我会非常建议整理:
AGENTS.md
例如:
# Legacy Project Rules
## Important
This is a legacy production system.
Backward compatibility is more important
than architectural elegance.
Do not refactor unrelated code.
Do not change database schema
unless explicitly required.
Do not replace existing libraries
without approval.
## Before Changes
For every non-trivial task:
1. inspect current behavior;
2. inspect existing tests;
3. inspect related call sites;
4. identify backwards compatibility risk;
5. propose the smallest change.
## Legacy Behavior
Suspicious behavior must not be changed
during refactoring.
Report it separately.
## Testing
Before modifying critical modules,
run existing relevant tests.
After modification,
run the same tests again.
## High Risk Modules
Changes involving:
- payments
- balances
- orders
- permissions
- authentication
require explicit risk analysis.
这类规则对于老项目特别有价值。
因为 Legacy 项目的核心目标通常不是:
代码最漂亮
而是:
稳定
二十七、老项目重构最重要的一句话
如果只让我保留一句 Prompt,我会保留:
Preserve existing behavior unless the task
explicitly requires a behavior change.
翻译过来就是:
除非需求明确要求改变行为,否则保持现有行为。
因为 Legacy Code 最大的危险并不是:
代码不好看
而是:
你不知道哪些奇怪代码其实承担着兼容责任
二十八、一套可以直接复制的 Legacy Code 万能 Prompt
如果你准备让 Codex 接手一个老项目,可以直接保存下面这一段:
You are working on a legacy production system.
Task:
[描述任务]
Before modifying anything:
1. inspect the related implementation;
2. trace the complete call path;
3. identify business rules;
4. identify database writes;
5. identify external side effects;
6. inspect existing tests;
7. identify backwards compatibility risks.
Important rules:
- Preserve existing behavior unless explicitly required.
- Prefer the smallest reasonable change.
- Do not refactor unrelated code.
- Do not introduce new dependencies unnecessarily.
- Do not change public APIs without explanation.
- Do not modify existing tests merely to make them pass.
For unclear or suspicious legacy behavior:
Do not silently change it.
Report it first.
Implementation:
Make the minimum change necessary.
Verification:
Run relevant existing tests.
Add regression tests for the bug or feature.
Run type checking / lint / build where applicable.
Final Review:
Review the Git Diff for:
- accidental behavior change;
- data integrity risk;
- security issue;
- concurrency issue;
- backwards compatibility;
- missing tests.
Final Report:
1. Root Cause
2. Files Changed
3. Behavior Changed
4. Tests Executed
5. Test Results
6. Compatibility Risks
7. Remaining Unknowns
这段基本能够覆盖大量:
老项目修 Bug
Legacy 重构
接手历史系统
场景。
二十九、AI 时代,Legacy Code 可能反而会变得更容易维护
过去一个老项目最麻烦的地方是:
没人知道代码什么意思
现在 AI 可以帮助:
搜索
↓
追踪
↓
总结
↓
还原业务规则
↓
生成测试
↓
辅助重构
这意味着:
以前可能需要:
2 周
才能大致理解的项目,
未来可能只需要:
更短时间
就能建立基本系统地图。
但这里有一个非常重要的前提:
AI 只能帮助你更快理解代码,不能替你承担业务判断责任。
尤其涉及:
支付
资金
权限
订单
用户数据
仍然必须人工判断。
三十、结语:真正厉害的 Codex 使用方式,不是“写更多代码”
使用 ChatGPT、Plus、Pro、Codex 一段时间后,我越来越觉得:
真正的效率提升不是:
以前一天写 500 行
现在一天写 5000 行
而是:
以前需要一天才能看懂的问题
现在一两个小时能够建立方向
尤其对于 Legacy Code 来说,
AI 最大的价值可能根本不是:
Generate Code
而是:
Understand Code
因为真实软件开发中,大量时间其实花在:
读代码
找调用
查状态
找历史原因
确认修改影响
这些工作上。
所以如果你现在已经在使用 ChatGPT Plus、Pro 或 Codex 编程,
我非常建议不要只测试:
“它能不能帮我写一个新功能?”
还可以真正找一个:
没人愿意碰的旧模块
让 Codex 先:
只读
再:
分析
再:
写测试
最后:
小范围修改
你可能会发现:
AI 编程真正价值最大的地方,恰恰不是新项目。
而是那些:
旧
复杂
缺文档
缺测试
没人敢改
的真实系统。
未来优秀开发者和 AI Coding Agent 的关系,也许越来越像:
Developer
负责判断什么应该改变
+
Agent
负责快速理解什么已经存在
最后形成一套更加高效的:
Human + AI Legacy Engineering Workflow
而这可能才是 ChatGPT、Plus、Pro、Codex 真正进入企业级开发以后,最值得关注的能力之一。
更多推荐


所有评论(0)