AI Coding 写得快,代码却越来越难维护,怎么办?

93 阅读10分钟

《AI Coding 工程化:从个人提效到组织升级》第 17 期
这个系列聊 AI Coding 怎样进入真实研发流程。上一期讲接入企业内网,这一期接着看:项目长期交给 AI 修改,怎样让它越改越顺。

用了 AI Coding,写代码越来越快,一个需求接着一个需求,代码也越写越多。可几个迭代下来,功能是加上去了,项目却逐渐堆成了一座庞大的“屎山”:改个小地方,牵出一堆问题,人看着头疼,让 AI 接着改,也经常改了这里、坏了那里。

代码生成快了,项目却越来越难维护,省下的时间又花在了排查和返工上。

你们有没有遇到过这种情况?这篇就聊聊老A会怎么处理:已经写乱的代码怎么整理,后面的需求又怎么让 AI 做出合理的设计,少留一些难维护的代码。

我们先看一个退款的例子。

一条退款规则,改了这里漏了那里

假设一个订单系统,最初只有详情页能申请退款,后端根据支付、发货状态和退款时限判断资格。

后来列表页也要显示退款按钮,AI 参考已有代码,又写了一份判断。运营后台增加退款功能时,也有了自己的实现。几个需求单独验收都能通过,但同一条退款规则已经分散在几个地方。

现在加一个限制:订单已有进行中的退款申请,就不能再次发起。

AI 给详情页和提交接口补了条件,列表页却漏了。用户看到列表上的退款按钮,点进去操作,提交时又被拦住。功能没崩,用户却不知道到底能不能退。

退款规则有几份独立实现,后面每加一个条件,都得找到所有相关入口一起改。

退款规则复制到多个入口以后,新条件可能漏改,合理例外也可能被误删

运营后台还有一条特殊规则:普通用户超过退款时限就不能申请,但经过人工审批,运营仍然可以处理。这是业务明确允许的例外,不能把运营后台也按普通用户的规则处理。

不过,审批只允许超出普通退款时限,并没有允许重复退款。如果订单已经有进行中的申请,运营也必须被拦住。

到了这里,修复就不能只找“哪几个条件写得不一样”。还得搞清楚,哪些差异是漏改,哪些是业务本来就需要的。

反正以后也是 AI 改,还用管这些吗?

顺着这个例子,很容易产生一个想法:人找几份代码很麻烦,AI 可以自己搜、自己改、自己测,那就让它每次多改几个地方好了,为什么还要花时间整理?

如果几处重复逻辑很简单,关系明确,测试也能覆盖,暂时保留确实没什么问题。没必要看到两段相似代码,就立刻要求重构。

麻烦的是,代码越乱,AI 也越难判断该信哪一份;让它多找几个文件,并不能自动补上业务判断。

比如运营后台没有普通时限限制,AI 可能认为这里漏了校验,把限制补回去,正常的审批退款反而不能用了。也可能为了让审批退款通过,把其他限制一起放开。两种改法在局部都能讲出理由,但业务结果完全不同。

这时即使 AI 很快改完,人仍要核对它有没有理解错,重新检查影响范围,再做回归。AI 如果根据自己的实现生成测试,还可能把错误行为当成正确答案,代码和测试一起通过。

继续由 AI 维护,照样要付出这些理解、验证和返工成本。我们希望它接到下一个需求时有清楚的依据,而不是又从几份互相矛盾的实现里猜一遍。

先把眼前这次问题改好

回到退款需求,我会先让 AI 列出各入口的判断和调用关系,再对照业务规则看差异。

人工确认共同规则和审批例外,AI 再按确认后的方案修改、迁移调用、补测试。

这个例子里,支付状态、已有退款申请等共同资格判断,可以放回负责退款的模块,由详情、列表和运营的相关接口复用。运营审批保留为明确的特殊处理,由后端核验审批是否有效,只豁免普通退款时限。

页面根据后端结果显示按钮和原因;真正提交时,后端仍要按最新状态校验,并保证并发下不会重复受理。用户打开页面之后,订单状态可能变化,不能只相信刚才那个可点击的按钮。

AI 把新实现写出来以后,还要把旧调用迁过去,清掉各入口多余的判断。否则项目里只是多了一套推荐用法,下一次它还是可能参考旧代码。

多个入口复用退款模块,保留经过核验的审批例外,提交时再次校验最新状态

改完能不能验收,要按事先确认的业务预期来测。假设其他退款条件都满足:

场景应有结果
时限内,没有进行中的申请允许申请
已有进行中的申请所有入口都不能重复发起
超过时限,未获审批不允许直接申请
超过时限,已获审批运营入口核验审批后允许处理
已获审批,但已有进行中的申请仍然不能重复发起

这些场景既要验证公共规则,也要验证各入口是否接对。用例和结果需要人工审核,不能只看 AI 报告“测试通过”。

这样处理以后,共同规则有了明确位置,合理的例外也留了下来。但这仍然只是解决了当前退款模块的问题。如果下个需求里 AI 又复制一套判断,过几轮还是会乱。

怎样让 AI 从一开始就做出合理设计?

老A觉得,治理做到这里还不够。要解决的是 AI 在后续需求里反复写出难维护代码的现象,得把设计依据和质量检查放进日常开发流程。

退款规则重复只是其中一种表现。逻辑放错模块、上下游互相依赖、一个函数包办查询和审批、为小需求设计一堆暂时用不上的框架,也都会让项目越来越难改。

所以给 AI 一句“遵循最佳实践”远远不够。它得知道这个项目怎么划分、哪些能力已经存在,以及团队为什么这样设计。

可以按下面这张图安排人机协作:AI 根据项目资料提出方案、完成实现,人参与澄清、评审和验收。评审中发现的问题交给 AI 修改,确认后的结论也要留给后续需求使用。

AI提出问题和方案、执行编码与测试;人工参与需求澄清、设计评审、关键代码审查及用例和结果审核,纠正结论写回项目资料

**先把项目的架构依据给到 AI。**项目知识库里要有模块职责、调用关系、已有公共能力和特殊约定,并能找到具体文档与代码。退款例子里,要写清资格判断由退款模块负责,页面负责展示,运营审批只处理获准的例外。

还可以放一段经过团队确认的参考实现,说明新入口应该怎样接入。旧代码里确实有问题的地方也要标出来,避免 AI 把历史欠账当成项目规范。业务规则、审批边界则放在对应的业务文档里,让它设计时能查到。

这些信息要随着需求按需读取。Claude Code、Codex 或 Cursor 的项目入口里说明去哪找,Spec(开发流程规范)要求设计阶段读取相关模块资料,无须把整个知识库一次性塞进上下文。

AI 读完资料、给出方案后,就进入设计评审。人要重点看模块职责是否清楚、依赖关系是否合理,已有能力有没有复用,扩展设计是否符合业务接下来的需要。

可以让 AI 在方案里回答几项具体问题,再由人确认:

设计要确认什么在退款需求里怎么判断
逻辑放在哪里,谁调用谁?入口调用退款模块,退款模块不反过来依赖某个页面
现有能力能否复用?新增退款入口先接已有资格判断,确有差异再说明原因
哪些地方要一起变?列出详情、列表、运营和提交接口,确认各自影响
扩展要留到什么程度?保留已知的审批差异;没有其他明确需求,先不搭通用规则引擎

这里需要人的判断,尤其是扩展设计。业务已经明确下一步要支持什么,可以在这次设计里留好位置;只是“以后可能用到”,就要考虑是否值得增加复杂度。团队规模、业务增长和后续计划都会影响取舍,这些信息也应该在澄清和设计时告诉 AI。

方案确认后,编码流程还要检查实现有没有照着走。比如设计要求复用退款模块,AI 最后却在列表接口里重新写了一份条件,即使这次结果正确,也应该在 Code Review(代码审查)时纠正。

可以让 AI 先对照设计自查模块依赖、重复规则、错误处理和旧调用,再把关键改动交给人审阅。能明确判断的规范,尽量交给工具检查;业务含义和设计取舍,仍要在评审里确认。

格式、类型、静态检查,以及项目能够自动检测的依赖约束,都适合放进本地检查和 CI(持续集成)。功能测试则根据已评审的需求和设计生成,覆盖正常路径和例外。它们各有作用:测试通过说明被覆盖的场景符合预期,不能据此认定架构也合理。

这样,知识库提供项目依据,设计评审决定实现方式,代码审查和自动检查负责发现偏离。AI 写代码时有参考,写完以后也有具体标准可以核对。

这些标准,也要跟着需求一起完善

不必指望一开始就把所有架构规则写全。每做一个需求,发现一次重复实现或错误依赖,就看看缺的是业务说明、参考代码,还是流程中的检查。

退款案例处理完,就补上资格判断的归属、审批例外和对应测试。下次增加“冻结订单不能退款”时,再看 AI 是否主动找到退款模块,设计是否覆盖各入口,实现有没有重新复制规则。

如果它还是做错,就继续查:文档没写清,流程没有要求读,还是评审时没有发现?这些原因对应的改法不同,只反复提醒“下次注意”很难有效。

**所谓从根上解决,是让每次发现的问题都能改进后续开发的依据和检查,逐步减少同类问题。**这不能保证 AI 第一次就写出完美代码,但能让人的纠正留下来,用到之后的需求里。

当前的坏代码要整理,后续怎么设计、怎么写、怎么检查,也要一起改。项目长期交给 AI,才能少一些反复修同一种问题的工作。

你持续用 AI 修改项目时,遇到过哪些越补越乱的逻辑?欢迎在评论区聊聊。


我会继续更新 AI Coding 和企业 Agent 的真实实践。更多系列内容,欢迎关注公众号「真老A计划」,微信搜索名称即可找到,头像和这里一样。