Appearance
用 Codex 做可回退的重构与迁移
重构的风险不在于改动行数,而在于“行为保持不变”很难证明。让 Codex 一次性搬完整个模块,往往会把结构变化、行为变化和顺手优化混在一起。本章用分阶段迁移把风险变成可以逐步验证的差异。
先定义“不变”和“允许变化”
示例:
text
目标:拆分 auth 模块中的令牌解析、会话加载和权限判断,消除循环依赖并提高可测试性。
必须保持:
- 所有公开接口、错误码和响应结构;
- 登录态过期和刷新行为;
- 现有数据库结构;
- 线上配置字段名称。
允许变化:
- 内部目录和私有类型;
- 模块依赖方向;
- 测试组织。
不在范围:
- 更换认证方案;
- 升级框架;
- 修改 UI;
- 性能优化。边界越清楚,Codex越不容易把重构变成重写。
第一步:建立行为基线
要求 Codex找出现有保护网:
text
先只读分析 auth 模块。列出公开入口、调用方、状态变化、错误类型、配置字段、数据库访问和现有测试。找出行为没有测试保护的区域,并提出最小特征测试,不要开始重构。对关键行为补“特征测试”:不评价现状是否优雅,只固定当前外部行为,以便后续发现意外变化。
第二步:画依赖与迁移地图
输出至少包含:
- 当前模块依赖图;
- 目标模块边界;
- 每个调用方迁移顺序;
- 临时适配层;
- 可删除旧代码的条件;
- 每个阶段的回滚点。
提示:
text
把迁移拆成最多 5 个阶段。每个阶段必须能独立构建和测试,说明修改文件、兼容策略、验证命令和回退方式。不要在同一阶段同时迁移所有调用方并删除旧入口。第三步:先建立新边界,不迁移行为
第一阶段通常只做:
- 新建接口或内部模块;
- 把旧实现包在兼容层后面;
- 增加契约测试;
- 保持所有调用方不变。
如果这一步已经改变用户行为,切片仍然太大。
第四步:逐个调用方迁移
text
只迁移调用方 [名称/目录] 到新边界。其他调用方继续走兼容层。完成后运行该调用方测试、auth 模块测试和类型检查,并比较公开行为。每迁移一批都检查 Git diff。必要时用独立 worktree 处理不同但不重叠的调用方,禁止多个任务同时编辑同一核心文件。
第五步:处理数据库和公共 API 迁移
需要改变数据或接口时,不再是纯重构,应单独设计兼容方案:
- 先加后删;
- 旧字段继续可读;
- 写入幂等;
- 迁移脚本可重复或能检测已执行;
- 有回滚脚本或备份;
- 新旧版本可在发布窗口内共存;
- 通过指标确认旧路径已无流量。
不要让 Codex只根据代码搜索结果判断“旧字段已经没人用”。还要检查报表、脚本、外部客户端和线上流量。
第六步:最后删除兼容层
只有满足以下条件才删除旧代码:
- 所有内部调用方已迁移;
- 外部兼容期结束;
- 完整测试和构建通过;
- 日志或指标显示旧入口无使用;
- 文档和配置已经更新;
- 回滚策略不再依赖旧实现。
删除阶段单独提交最容易审查,不要与核心迁移混在一起。
使用 Codex 云任务或 Subagents 的边界
适合并行的工作:独立调用方迁移、测试补充、文档更新、静态引用盘点。
不适合无约束并行的工作:核心接口设计、同一迁移脚本、同一公共类型、会产生冲突的格式化。
并行前明确:文件所有权、基线分支、接口版本和合并顺序。
验证阶梯
每个阶段至少运行:
- 新增契约/特征测试;
- 当前模块测试;
- 已迁移调用方测试;
- 类型检查或编译;
- 跨模块集成测试;
- 完整构建;
- 关键用户路径;
- 公开 API 或数据差异检查。
常见失败
重构中顺便修业务
把行为修复拆成独立任务,否则出现回归时无法判断来源。
计划只有文件列表
文件列表不说明迁移顺序和兼容性。要求每阶段都能独立运行。
过早删除旧入口
先迁移并观测,再删除。代码搜索不是唯一使用证据。
测试也被一起重写
至少保留一层从用户或公开接口角度验证行为的独立测试,避免实现和测试一起“自洽地变错”。
完成报告模板
text
保持不变的行为:[列表]
迁移阶段:[完成/未完成]
当前兼容层:[位置和删除条件]
验证结果:[命令和结果]
仍在使用旧路径的调用方:[列表]
回滚点:[分支/提交/开关或明确步骤]下一步
重构完成后用 代码审查、Git 与 PR 闭环 检查差异。如果需要并行代理,继续学习 Subagents 实战。