程序员们的难言之隐--AI 写的代码,三次迭代后谁敢改?

来源:西风白马啸 链接:查看
0 评论 47 浏览 0 收藏

想象一个很常见的需求:给会员增加一个“满 300 减 50”的优惠。

想象一个很常见的需求:给会员增加一个“满 300 减 50”的优惠。

你把这句话丢给 AI。十分钟后,接口、页面、数据库字段、单元测试全有了,Demo 也跑通了。

两个月后,业务要支持优惠券叠加;再过一个月,又要处理部分退款。新同事打开代码,发现折扣是在税前算还是税后算、退货时 50 元如何分摊、并发提交会不会重复核销,全藏在 AI 当时顺手做出的选择里。

最麻烦的是:没有人记得这些选择为什么存在。

于是,那句熟悉的质疑又来了:代码都不是你写的,后期怎么维护?

听起来很像技术史上反复出现的保守派台词。机器码时代,人们担心程序员用了汇编,就不会直接写机器码;高级语言出现后,人们又担心程序员依赖编译器,不懂底层汇编。现在轮到 AI,人们开始担心程序员只会说需求,不会读代码。

乍一看,这不过是又一次“新工具恐惧”。

但这一次,质疑者确实碰到了一个过去没有的问题。

历史确实相似,但没有短视频里那么整齐

先纠正一个流传很广的说法。

目前能找到的可靠史料里,早期高级语言遭遇的典型质疑,主要不是“以后谁来维护编译器生成的汇编”,而是“编译器生成的代码,能有熟练程序员手写的代码快吗?”

20 世纪 50 年代,John Backus 团队开发 FORTRAN 时,必须花大量精力优化编译器,原因很现实:如果生成程序的效率明显不如手写机器码或汇编,程序员根本不会用它。后来 FORTRAN 证明自己能生成足够高效的代码,这种怀疑才逐渐消退。IBM 的 FORTRAN 历史资料和计算机历史博物馆的编程语言时间线都记录了这段转变。

汇编语言做的事情也很清楚:它用助记符、符号和标签代替难读的数字指令与绝对地址,再由汇编器转换成机器代码。IBM 对汇编语言的说明至今仍把它定义为最接近机器语言的符号化编程语言。

这里有一个经常被忽略的事实:

无论从汇编到机器码,还是从高级语言到机器码,开发者都会保留上游源码。下面生成出来的东西,大多只是构建产物。

  • 机器码坏了,可以重新汇编。
  • 编译结果丢了,可以重新编译。
  • 换了处理器,可以针对新平台重新构建。

维护者不需要逐行读懂生成的机器码,因为真正承载设计意图的是上游源码。只要工具链、依赖和构建参数被控制住,这个转换就受明确规则约束,可以反复执行和验证。

AI 编程不是这条链路的自然延长。

编译器负责翻译,AI 经常在替你补需求

高级语言当然也不完美。不同编译器有实现差异,某些语言存在未定义行为,优化参数也会改变产物。说“高级语言到机器码绝对唯一、毫无歧义”,并不严谨。

但编译器不会在背后替你决定“满 300”包不包含运费。

程序员一旦在代码里写明先算商品金额、再减优惠、最后计算运费,编译器的任务就是按照语言和工具链的规则去翻译。它不会因为见过另一家电商平台,就自作主张换一种优惠顺序。

AI 面对自然语言时却不得不做推断。

“满 300 减 50”至少缺了这些信息:

  • 300 元按商品原价、活动价,还是实付价计算?
  • 运费、税费算不算进门槛?
  • 能否和优惠券、积分、会员折扣叠加?
  • 多件商品部分退款时,50 元怎么分摊?
  • 用户连续点击两次,优惠名额能否重复占用?
  • 跨币种订单按下单汇率还是结算汇率计算?

这些不是“代码写得优不优雅”的问题,而是需求里根本没有答案。

AI 仍然可以交出一份能运行的代码,因为它会从上下文、训练数据和常见做法中选一个看起来合理的解释。Demo 通过,只能证明这套解释在演示路径上自洽,不能证明它就是业务真正想要的规则。

所以,模型是否随机并不是最核心的问题。即使把生成参数调到最稳定,只要输入缺信息,它也只能稳定地猜。

2026 年一项关于需求歧义的预印本研究构建了 1304 个函数级任务,覆盖词义、句法、语义和模糊表达四类歧义。研究者发现,歧义会持续拉低所有受测模型的代码生成表现;面对同一条含糊需求,模型还会生成行为不同的实现,并且不能可靠地主动识别和消除歧义。论文与 Orchid 数据集说明

这才是 AI 与编译器最重要的差别:

编译器转换的是已经写进程序的决定;AI 经常把没有做出的决定,悄悄固化进程序。

最大的风险,不是没人看懂代码,而是系统失去了“上游源码”

很多人会说,以后让 AI 维护 AI 写的代码就好了,人不需要再看。

这句话不是完全错,但它漏掉了一个前提:AI 下一次维护时,依据什么判断旧行为是特性还是 Bug?

传统编译链里,高级语言源码是上游,机器码是可丢弃、可重建的下游产物。可在很多 AI 项目里,情况变成了这样:

  • 原始提示词只留在某个聊天窗口里;
  • 提示词本身没有写清边界条件;
  • 当时的模型、上下文和外部资料已经变化;
  • 生成的高级代码被提交进仓库,成了唯一完整的实现;
  • 团队却又默认“这是 AI 写的,不必细看”。

结果是,代码既没有被当成需要理解的源码,也不能从上游规格中可靠重建。它成了一份没有设计依据的“孤儿源码”。

三次迭代以后,AI 只能继续从现有代码反推意图。废弃逻辑、临时兼容和历史 Bug 也会一起进入上下文。模型看到某段奇怪判断,不知道它是财务规则、线上补丁,还是上一次生成留下的垃圾,于是通常会选择最像已有模式的改法。

这会形成一种比代码重复更麻烦的债:语义债。

技术债通常还能从结构、复杂度和依赖关系里看出来;语义债的表现却是,系统明明在稳定运行,团队已经没人能说清“为什么必须这样运行”。

Google 的 2025 年 DORA 研究把 AI 称为组织能力的“放大器”:流程清晰、协作顺畅的团队会被放大,原本割裂、混乱的团队也会被放大。DORA 报告的这个判断,用在代码维护上尤其准确。AI 不会自动治好混乱的工程,它只会让混乱更快地长出代码。

真正可维护的 AI 代码,要留下三样东西

维护一段代码,不要求每个人都能背出每一行。人写的代码也做不到。

但团队至少要能回答三个问题:

  1. 这段行为为什么存在?
  2. 哪些条件无论如何都不能被改坏?
  3. 改坏以后,什么机制能在上线前发现?

对应到工程里,就是意图、不变量和验证证据。

缺少任何一个,所谓“AI 会自己维护”都只是把问题递延到下一次对话。

1. 别直接让 AI 写代码,先让它把歧义暴露出来

大多数人给 AI 的第一句话是:“帮我实现这个需求。”

更稳妥的第一句话应该是:

先不要修改代码。请列出需求中所有缺失条件、可能产生两种以上解释的表述、会受影响的模块和数据;再把需求改写成可验收场景,等我确认后再实现。

对于重要业务,可以进一步要求它按下面的结构输出:

  • 触发条件:什么事件发生时执行?
  • 前置状态:系统和数据必须处于什么状态?
  • 可观察结果:用户、接口、数据库分别发生什么变化?
  • 不变量:无论如何都不能被破坏的规则是什么?
  • 异常路径:超时、重试、并发、部分失败如何处理?
  • 非功能约束:性能、安全、兼容、审计和回滚要求是什么?

这类做法并不是 AI 时代的新发明。2009 年提出的 EARS 方法,就是通过少量固定句式约束自然语言需求,减少歧义、复杂和模糊表达。EARS 原始论文的思路很朴素:自然语言无法变成形式语言,但可以先被“收紧”。

2. 测试代码可以交给 AI,正确答案不能一起外包

如果同一个 AI 根据含糊需求写实现、写测试,再自行宣布测试通过,这不是闭环,只是让同一种误解验证了自己。

AI 很适合补齐测试代码,人要守住的是测试预言,也就是“什么结果才算正确”。

仍以优惠为例,业务方至少要确认一组真实样例和不变量:

  • 同一个订单重复提交,不得重复核销优惠;
  • 任意退款顺序下,累计退回的优惠额不能超过原优惠额;
  • 订单实付金额不能小于零;
  • 老订单在新规则上线后,重新查询金额不能发生变化;
  • 数据迁移失败时,能够回滚到可继续交易的状态。

然后再让工具补单元测试、集成测试、属性测试和异常注入。测试的价值不在数量,而在它能不能拒绝一份“看起来没问题、其实理解错了”的实现。

3. 把 AI 的改动控制在可审查的尺寸里

一口气生成 5000 行代码,真正节省的是生成时间,增加的却是审查面积。

更可控的做法,是让每个变更只解决一个问题,并要求 AI 在提交时同时说明:

  • 改了哪些文件,为什么必须改;
  • 哪些调用方和数据会受影响;
  • 保留了哪些旧行为;
  • 新增了哪些验证证据;
  • 失败后如何回滚。

再按风险分级处理:样板代码、测试脚手架、内部小工具,可以让 AI 更自主;业务规则、缓存、并发逻辑,需要人工评审和集成测试;权限、支付、隐私、数据迁移等高风险改动,必须由人确认设计、演练失败路径并签字放行。

AI 时代不是所有代码都要逐行苦读,而是审查资源必须投到错误代价最高的地方。

4. 项目记忆要写进仓库,不要留在聊天记录里

模型会换,会话会结束,参与项目的人也会离开。

真正能跨越这些变化的,是和代码一起版本化的材料:接口契约、数据字典、架构决策记录、关键业务规则、迁移方案、回滚步骤,以及能执行的验收测试。

一个简单但很有效的验收办法是:在不提供原聊天记录的情况下,开一个新会话,让另一个 AI 只根据仓库里的代码、文档和测试完成一次小改动。

如果它必须依赖“上次聊天里说过”,说明项目还没有形成可维护的上游信息;如果它能解释约束、定位影响面,并用测试证明没有破坏旧行为,这套工程才算真正接住了 AI 的速度。

AI 可以成为新的抽象层,但现在还不是免费的

汇编语言把地址和操作码包装成符号,高级语言把寄存器分配、指令选择等工作交给编译器。每一次成功的抽象,都不是简单地让人“少懂一点”,而是在上一层建立了更清晰的表达,在下一层建立了更可靠的转换。

AI 也可能成为新的抽象层。

但自然语言提示词还不是高级语言,模型也不是传统意义上的编译器。前者没有完备语义,后者必须替输入补齐大量决定。工具越强,这些未经确认的决定反而越容易混进一份完成度很高的实现里,让人放松警惕。

所以,“AI 写的代码以后怎么维护”不是拒绝新工具的借口,而是一个必须正面回答的工程问题。

答案也不是重新要求所有人手敲每一行代码。

更现实的做法,是把开发者的注意力从“如何快速生成”移到“如何明确意图、约束变化、验证结果”。代码可以由 AI 写,决定不能无声地由 AI 代做;测试可以由 AI 补,正确答案不能没有负责人;实现可以重生成,业务规则必须能够被追溯。

如果做不到这些,AI 不是帮团队跨过了编程语言,而是把一部分需求猜成代码,再把猜错的代价留给未来。

而未来,通常就在第三次迭代。


收藏 0打赏 0评论 0
评论
  1. 暂时没有评论,来说点什么吧