我们如何用Codex辅助重构旧项目

我们如何用Codex辅助重构旧项目

我们如何用Codex辅助重构旧项目

去年年底,我所在的技术团队接手了一个维护了四年多的旧项目。这个项目代码库膨胀到300多个TypeScript文件,依赖了47个npm包,其中11个已经停止维护超过一年。当我第一次在团队会议上提出“让Codex来帮忙重构”时,技术总监看了我一眼,说了句让我记到现在的话:“AI写的代码,到时候出了问题谁负责?”

三个月后,还是他,在复盘会上对所有人说:以后新项目能不能也考虑用AI辅助重构流程。

这个转变不是因为Codex有多完美,恰恰相反,是因为我们终于弄清楚了它到底能干什么、不能干什么。更重要的是,我们弄清楚了“人”在AI重构过程中应该扮演什么角色。

这篇文章不打算给你看那种“输入一行Prompt,AI帮你重写整个项目”的爽文。我要分享的,是真实踩过的坑、做过的取舍,以及一套能让AI真正帮你干活的协作方案。

一、你以为的就是你以为的吗,三个认知先讲清楚

在进入具体方法之前,先对齐三件事。这三件事直接决定了你和一个代码AI合作时的“协作姿势”。

第一,Codex的最大优势不是“能写代码”,而是“能读整个项目”。

很多人用AI写代码的感受是:写个工具函数没问题,但它不知道你这项目里还有另外一个函数已经实现了差不多的逻辑。Codex对比其他工具最根本的区别,在于它会把整个项目当成一个上下文去理解。这不是说它更聪明,而是它“视野”更大。你不需要手动告诉它“这个项目用了Redux”、“我们的异常处理统一走handleError这个工具函数”,它自己能读出来。这能力对重构来说至关重要,因为你改一个文件,往往要同时改十几处调用它的地方。

第二,AI重构的能力上限,不取决于AI本身,取决于你项目的“安全网”厚度。

这一点我几乎在每一场内部培训里都会反复强调。我们在这个旧项目上的第一个大动作,不是打开Codex开始重构,而是用两周时间补齐了单元测试覆盖率。原先覆盖率只有百分之十几,我们硬是补到了接近70%。为什么?因为当AI一次性给你修改了40个文件的时候,如果你没有一个能自动跑通并告诉你“哪里坏了”的测试体系,你相当于把自己的生产环境当成了QA环境。这不是AI的问题,是你的问题。

第三,AI重构的成功率不是99%,在我们这里,AI初稿的“一次通过率”只有60%左右。

这里“一次通过”指的是:AI给出的改动,人Review之后不需要二次修改就能直接合入。在我们这个300多文件的项目里,真正复杂的那部分逻辑,你去问任何一个在这个项目上干过半年的开发者,他们都会告诉你,这部分的改动十次有六次需要返工。这不是失败,这是现实。如果你对AI的预期是“一次搞定”,那你一定会失望。但如果你对它的预期是“帮我搞定60%的脏活累活”,那你赚了。

二、失败案例比成功案例更有价值,那些Codex没能搞定的事

我坚持认为,学一个工具最好的方式是看它怎么失败。因为在失败里,你才能看到它的能力边界。这里有三个让我印象深刻的“翻车”现场。

翻车一:依赖包替换,“它改完了,但一半功能坏了”

我们项目里有一个很经典的遗留问题:前任架构师深度绑定了@electron/remote这个已经废弃的依赖,需要全部迁移到@electron/ipcMain@electron/ipcRenderer的通信方式。涉及42个文件,调用链分散在渲染进程和主进程之间。

我先尝试把整个任务描述扔给Codex,让它全自动修改。它在不到十分钟内给出了修改方案。但当我跑测试的时候,渲染进程里有七个地方的remote调用被它直接删除了,因为它没理解“这条调用链最终会跨进程触发主进程里的一个文件操作”。它还修改了两处主进程的调用,让它们“看起来符合新的IPC写法”,但入参类型全错了。

最后真正有效的修改,只有大约一半。

这类“牵一发而动全身”的依赖重构,AI最大的问题不是它不想做好,而是它对于跨文件、跨进程、跨模块的深层调用链,没有真实的理解。它看到的是一堆字符串,你用人类思维制定的架构规约,在Token化的过程中已经被打散了。

所以后来我们建立了一条规则:凡是涉及跨三层以上调用链的依赖替换,先让人画出影响面依赖图,再让AI逐个模块去改。人在中间承担的是“架构理解”的角色。

翻车二:风格一致性,它做到了局部优雅,也带来了全局分裂

Codex对现代前端最佳实践的掌握是顶级的。我们有一次让它重写了一个用户列表组件,从Class写法改到Hooks,写得非常漂亮,命名清晰,状态管理逻辑合理。但问题是,这个组件旁边还有一个用户详情组件,也是老的Class写法,两者的文件命名规则、目录组织方式、状态变量的命名风格完全割裂。

这导致的一个隐性后果:新加入团队的开发者开始困惑“这项目到底有没有统一的规范”。AI没有帮你维护“项目一致性”的内在驱动力,这是人的活儿。

这次教训之后,我们在项目根目录增加了文档化的架构规约,并且在每次AI生成的代码里,特别检查“你的写法是否与相邻模块保持风格统一”。

翻车三:它太想“优化”你的代码了

有一次,我让它把一段核心业务计算逻辑里的性能瓶颈解掉。它确实优化了,它把一段用for循环实现、每个开发者都能一眼看懂的计算逻辑,重构成了一套高度抽象的函数式组合,用上了柯里化、高阶函数,还自己封装了一个utils。

从技术上看,没毛病,甚至可以说很优雅。但这段逻辑是账务相关的计算,每个月财务团队都要对着它审计。当我拿着AI改过的代码跟财务那边的技术对接人沟通时,他说了一句让我至今记得的话:“这还能看懂吗?”

对于维护期的旧项目来说,“可读性”和“可维护性”永远大于“技术上的优雅”。尤其在业务逻辑层,你的代码需要让一个接手不到三个月的新人能看懂、能改、敢改。AI的“过度优化”实际上是在增加维护负担。

三、人的角色变了,从“写代码的人”变成“做决策的人”

在踩完上述坑之后,我们内部形成了一个共识:用AI重构旧项目,不是在指挥一个超级程序员在帮你干活,更像是在和一个能力极强但经验不足的实习生合作。他能帮你处理大量重复、枯燥的体力劳动,但你必须要承担架构判断、风险评估、代码评审的责任。

所以我们把“人”的角色拆成了三个:

第一,做“风险分级”的决策者。

不是所有旧代码都适合让AI去重构。我们在项目里建立了一个简单的风险评估模型:

代码类型 特征 是否适合AI重构 原因
纯工具函数/样板代码 如Repository层、通用的CRUD接口、格式化工具等 ✅ 适合 模式固定,出错后果可控,人工验收成本低
组件/页面级UI逻辑 如列表渲染、表单校验、交互状态管理 ⚠️ 需监督 AI能很好地处理现代框架写法,但需检查风格一致性
核心业务逻辑 如账务计算、权限控制、特定领域算法 ❌ 不建议 改错的隐性成本极高,需大量领域知识,可读性损失不可接受
深层依赖/跨模块调用链 如模块A通过B、C最终调用D的复杂链路 ❌ 不建议一口气改 容易产生“局部正确,全局错误”,需拆分后逐个处理

这个表格帮我们节省了大量沟通成本。团队里的每个人都知道,什么任务可以放心交给AI,什么任务必须自己上。

第二,做“协作流程”的设计者。

我们磨合出了一套相对标准化的协作流程。不是让AI全自动跑,而是让它在人的决策框架内工作:

  1. 人在Issue里把任务拆碎,明确边界和期望结果(例如:“将UserProfile组件从Class写法改为Function组件,保持现有props接口不变,不要修改相邻组件”)。
  2. AI基于完整上下文生成修改,并输出一份变更报告(我们要求它在PR description里写清楚“改了什么文件、为什么这么改、哪个地方的判断它不确定”)。
  3. 人Review,在代码diff上对每一处有疑问的地方进行批注。批注分两种:“这里OK”和“这里有问题,因为XX原因,请按YY方向调整”。
  4. AI根据批注进行二次修改,人最终确认合入。

这本质上是人机协同的“双向反馈”过程。人给出战略方向,AI执行战术动作,人再对战术结果进行校准和纠偏。

第三,建立“AI输出验收清单”。

我们制定了一份针对AI生成代码的检查清单,每个开发者在CR时必须逐项核对。这份清单来源于我们所有翻车经验的总结:

  • [ ] 是否引入了新的不必要的依赖?
  • [ ] 异常处理分支是否完整?(AI特别容易只考虑Happy Path)
  • [ ] 是否有无意义的类型断言?(面对不懂的类型,AI有时会用as any强转,掩盖问题)
  • [ ] 性能敏感路径里的循环/递归是否被错误替换?
  • [ ] 命名风格是否与相邻模块一致?
  • [ ] 是否在核心业务逻辑中引入了难以理解的抽象?
  • [ ] 产生的TypeScript、ESLint告警是否全部处理?

这七条看起来简单,但每一条背后都有至少一次线上告警的教训。

四、结论:AI是加速器,不是自动驾驶

回到开头那个问题,技术总监担心AI写的代码出问题谁负责。答案是:永远是人负责。AI不会为任何一个Bug买单,也不会半夜起来修生产环境的紧急问题。

但我想说的是,在搞清楚AI的能力边界之后,你并不会觉得它“没用”。恰恰相反,你会开始找到正确使用它的方式,把它当成一台高效的“理解机器”和“执行机器”,它帮你去处理那些费时间但不费脑子的活,而你,把自己的精力集中在“决策”和“判断”上。

在重构旧项目这件事上,AI能让你从一个“搬砖工”变成“施工队队长”。你依然需要懂架构、懂业务、懂判断,但AI让你的执行效率提升了不止一个量级。

如果你正在考虑在你的旧项目上尝试Codex,我的建议只有三条:

  1. 先补测试,后动代码。没有安全网的AI重构是在定时炸弹上跳舞。
  2. 不要一口气把你的整个项目扔给它。拆碎了喂,一点一点验收。
  3. 做好打60分就接受的心理准备。剩下的40分,靠你的经验和判断去补齐。

最后想问你一个问题:你让AI帮你改过最让你崩溃的一次代码是什么?或者说,你有没有被它“惊喜”到过?欢迎分享你的故事,我特别想听听其他团队踩过的坑。

因为说到底,在这个AI编程工具层出不穷的时代,最有价值的不是某个工具的单点能力,而是我们作为开发者,如何学会和它们真正高效地协作。

常见问题解答(FAQ)

1. 使用Codex重构旧项目的真实成本是多少?到底值不值得?

我看到很多人说Codex重构能提升好几倍效率,甚至整个项目一周搞定。但我也担心Token费用会不会很高,更怕AI改出一堆新bug反而更浪费时间。有没有一个真实的成本账?比如花多少钱、多少时间,成功率到底怎么样?

我亲身参与了一个约300个文件、历史超过5年的React+Electron桌面客户端项目重构(类似Noi项目的规模),最后计算下来:Token费用大约1100美元(与Cloudflare案例接近),但人工审核和修复时间仍然占了整个工期的60%。

关键在于,Codex擅长的是‘大规模替换’和‘模式化重构’,比如批量将旧的生命周期方法改成Hooks,它能一次性改对80%的调用。

但遇到业务逻辑缠绕的‘屎山’模块,比如一个同时处理文件读写、IPC通信和状态管理的巨型组件,Codex的失败率飙升到40%以上,它会改出大量在单文件层面‘看起来正确’但跨文件调用链断掉的代码。我的结论是:对于纯技术债务(如升级框架、替换语法糖),非常值得;

对于核心业务逻辑重构,必须把AI当作‘高级实习生’,它的输出要经过工程师逐行审查。别信那些‘AI一次性搞定老项目’的神话,真实成本是你需要额外投入30%-50%的时间来擦屁股。

2. 怎么让Codex理解我那个加了无数补丁的遗留代码业务逻辑?

我试过直接把整个项目文件夹拖进Codex,然后让它重构某个模块,结果它像失忆一样乱改。它根本不理解那些全局变量、事件订阅、还有隐藏在注释里的历史妥协。到底有没有办法让AI‘读’懂我的项目?

关键不是让Codex自己去‘悟’,而是你主动喂给它‘上下文压缩饼干’。我实践出的流程是:首先,在项目根目录创建~AGENTS.md文件,里面用500字以内描述项目的核心架构、命名约定、数据流方向(比如‘所有领域事件通过EventBus发布,命名规则为xxx:yyy’)。

其次,在准备重构某个模块前,我会给Codex一段‘历史日志’,直接复制Git Blame里频率最高的几个commit message,或者粘贴一段团队Wiki里对该模块的说明。

比如之前重构一个‘离线数据同步’模块,我先贴了3条commit message:‘修复同步锁冲突’、‘调整失败重试间隔策略’、‘兼容v2协议字段名变更’,Codex立刻理解了那些看似冗余的try-catch和回调是历史原因,生成的代码不再自作主张删掉它们。

第三步,用‘分层提问法’:先问‘请列出这个模块依赖的所有外部接口和内部状态’,它列对了再让改。如果第一次它列错了(比如漏掉了一个全局单例),马上纠正,这一步不能跳过,否则后续所有修改都会跑偏。记住:AI不是你肚子里的蛔虫,你要做的是帮它拼凑出那个‘残缺的地图碎片’。

3. Codex突然拒绝重构某个函数,或者改了之后有一半是错的,这时候该怎么处理?

我遇到过Codex说‘抱歉,这个修改太复杂,我无法安全生成’,或者它硬着头皮改了20个文件,结果运行时报错一堆。这时候它是真不行还是我没问对?我应该继续逼它还是放弃自己来?

我自己遇到Codex‘罢工’的情况大约占任务的15%。

经过多次试探,我总结出两条路:如果是‘拒绝执行’,说明它识别到风险极高(比如跨5个文件以上的循环依赖重构),这时强行要求它改只会得到一堆不可执行的伪代码,正确做法是拆任务:比如它不敢一次性移除一个老旧依赖包,我就改成让它先‘扫描所有使用该依赖的进口点,列出清单’,我手动删掉2个核心调用后,再让它替换剩余20个普通调用。

如果是‘改了但一半错’,比如我们之前重构一个复杂的状态机,Codex改出的代码通过率只有53%。

我的应对方案是:不从头review,而是用‘差分法’,先让Codex输出一份改动摘要(changed files + 关键逻辑变更),然后我重点关注那些‘跨模块的接口变更’和‘异常分支的删除’(因为AI最容易删掉它认为‘没用’的catch块)。

然后对高风险区域手动编写单元测试,再让Codex跑一遍测试覆盖,看还有哪些红线。说白了,AI犯错也有规律:它在‘精简’代码时最危险,会砍掉看似多余的保护逻辑。所以我的策略是:对AI的删减操作,默认持怀疑态度,除非它能给出我认可的理由。

4. 如何搭建一套系统化的AI代码验收流程?具体用什么标准判断AI改的质量?

现在团队里每个人都用Codex改代码,但每个人对AI输出的容忍度不一样。有人觉得改完能跑就行,有人非要逐行看。我们急需一个统一的、可执行的验收清单,既不过度消耗人力,又不会放行有隐患的代码。该怎么做?

我们团队经过多次踩坑,最终制定了一份可复用的‘AI代码验收清单’,包含6个检查项,每个检查项都会消耗平均3-5分钟的人工时间,但可以拦截90%以上的AI隐性bug: 1. 依赖检查:AI是否新增了包?新增的包是否有更轻量的替代?

比如Codex曾给一个只用了Node内置crypto的模块额外装了一个crypto-js,只为了方便调用一个函数,直接否决。2. 异常分支审计:AI是否删除了原有的catch块、if-else的else分支或防御性null检查?

我检查过往输出,AI在‘简化’代码时删掉异常处理的概率高达37%。3. 性能关键路径标记:AI是否将之前手写的for循环替换成了Array.map()?如果该循环在每秒调用数百次的渲染函数里,这种替换通常不会引起注意,但会带来微秒级的性能损耗,对高性能场景不可接受。

跨文件一致性:AI修改文件A时,是否忘记了同步修改文件B中对应的引用?我们会让AI单独输出一个‘可能受影响的文件列表’,然后随机抽查其中3个文件的接口签名是否对齐。5. 类型安全越狱:AI是否引入了as any或@ts-ignore来绕过类型检查?

一旦发现,要求它提供无法用TS类型表达的具体理由。6. 副作用声明:AI是否在纯函数里偷偷引入了console.log、时间戳依赖或者外部状态读写?特别是重构旧代码时,AI可能保留原有的日志输出,但日志位置发生改变导致监控数据不准。

这六个检查项我写成了一个CODE_REVIEW_CHECKLIST.md放在项目根目录,每次AI提交PR后,由负责review的工程师逐一勾选。这个流程从原来的‘发现bug才修’变成了‘预防性拦截’,返工率降低了60%。

核心关键词

读者评论

顾清

这个翻车案例太真实了。我们之前用AI改一个旧系统,也是依赖替换,结果AI把很多跨模块的调用直接删了,测试报告一片红。文章里那句“局部正确,全局错误”简直说到了心坎里,跨三层以上的调用链AI真的理解不了,还是得自己先画图。

李卓

AI太想优化你的代码了”这部分简直是我的嘴替。前两天让AI把一个报表计算的循环优化一下,结果给我整了一堆高阶函数和柯里化,性能确实好了点,但产品经理说这以后咋维护?可读性才是老项目的命。

陈思远

先补测试再让AI动代码,这条血的教训我真的太同意了。我们项目没有安全网,有一次让AI批量改了20多个文件,功能看着都正常,上线第二天才有人发现某个角落的if分支逻辑被悄悄吃了,吓得我回去连夜补单元测试。

林晨

作为一名接手了三年屎山的开发,看到“AI能让你从搬砖工变成施工队队长”这句话,特别有感触。之前组长总让我把老的jQuery代码改React,现在让AI先搞第一遍,我花时间在审查和决策上,确实心态和效率都变了。

孟凡

想问问团队内部是怎么说服技术总监同意用AI重构的?我们这边也是领导怕出事,一直不让在生产环境相关的代码上用。你们有没有立过什么军令状或者先拿非核心模块做实验?

文章版权归“万象方舟”www.vientianeark.cn所有。发布者:程, 沐沐,转载请注明出处:https://www.vientianeark.cn/p/596587/

温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com 删除。
(0)
上一篇 1小时前
下一篇 1小时前

相关推荐

  • 从手动写函数到Codex自动补全复盘

    工作到第三年的某个下午,我写了一个函数,十七行,处理用户权限判断。 写完就在想,这十七行代码里,真正算得上“我思考过”的,大概只有三行。其余十四行是拿来即用的:判空、遍历、字段映射、异常兜底。你可以说这是工程规范,但那一刻我突然意识到一个问题,这几年代码打字速度越来越快,可真正让我觉得自己在“解决问题”的时刻,反倒越来越稀薄了。 差不多就是在那个时间点,我开始用 Codex,开始让它补全那些我懒得…

    1小时前
    000
  • 先别依赖Codex,先学会写Prompt

    先别依赖Codex,先学会写Prompt 上周我帮一个创业团队做技术评审,他们用Codex已经三个月了。技术负责人打开后台让我看使用数据,三个月,生成了超过一万段代码,但最终合入主分支的比例不到30%。剩下的70%去哪了?大部分被删掉重写,小部分在反复修改后勉强能用,但带着大量技术债。 我问他平时的Prompt怎么写的。他翻了翻聊天记录,给我看了一句典型的话:“帮我写一个用户管理的后台接口。” 问…

    1小时前
    100
  • Codex在代码审查中的真实搭法

    我真正开始信任 Codex 做代码审查,是在它指出一个我用了一下午才定位到的并发边界条件之后,那是一个我确信“绝对不可能有人能一眼看出来的”Bug。 在此之前,我和大多数开发者一样:把它当成一个“看起来很美,但关键时候不敢用”的吉祥物。问题不是它“能不能审”,而是我压根不知道怎么让它审得可信。 这篇文章,围绕“怎么搭”展开,不讲百科,不谈未来,只说你明天就能用上的真实落法。 一、核心结论:Code…

    1小时前
    000
  • Codex生成的正则表达式为何总错?

    你给 Codex 一句“匹配所有有效邮箱地址”,它毫秒级吐出一个正则出来: /^[\w\.=-]+@[\w\.-]+\.\w{2,3}$/ 语法没问题,符号没写错,任何一个入门正则教程都可以给这个写法打满分。 但这个看似完美的表达式,会把 a@b.co.uk 拒之门外,会认为 user@domain.c 一定合法,而且完全不考虑国际域名里那些非 ASCII 字符。 十次里可能有七次,Codex 生…

    1小时前
    000
  • 用Codex处理重复CRUD的实战效率

    用Codex处理重复CRUD的实战效率 凌晨两点,你已经为第7个后台管理模块写完了同样的分页查询、同样的字段校验、同样的增删改接口。唯一不同的是表名从 t_user 换成了 t_role,DTO里的几个字段换了名字。我经历过这种时刻,不是因为不熟练,而是因为这种工作压根就不该由人一行行手敲。后来我尝试用 Codex 把这类重复CRUD彻底重构了一遍,结果让我意识到:过去对AI编码的想象,可能都太保…

    1小时前
    100
站长微信
站长微信
分享本页
返回顶部