乐于分享
好东西不私藏

用AI写代码,需求补不完,代码总有偏差

用AI写代码,需求补不完,代码总有偏差

用AI做开发确实提效了——以前半天的活现在一小时能出,代码生成、调试、重构,速度肉眼可见地快了。但有一件事没变好,反而变糟了:焦虑。

焦虑不是因为AI不靠谱。大部分时候它确实好用,代码写得快、查bug也快,这些提效是实打实的。但在两个环节上,它会反复出同一种问题:拿到模糊的输入时不追问,直接用自己的推理补位,补出一个看着自洽但方向偏了的方案。问题出在它”太自信”的时候——推理越流畅,偏差越不容易被发现。

这种事集中在两个环节:需求分析和代码实现。两个场景看似不同,拆开看又发现它们其实是一件事。

两个焦虑,其实是同一个问题

产品设计给过来一份需求,技术名词用缩略短语,流程说明只写了主干交互,一些他觉得”开发肯定知道的”部分干脆没写,整个文档点到为止。这些上下文在他脑子里是完整的,但文档一旦离开他的脑子,信息就塌缩了。

你把这份需求交给AI分析,AI生成一版设计文档,复核的时候发现理解偏了。比如需求里提到”数据A”,AI推测是B,实际是C——因为原文用了个缩略名词A指代C,没说清楚。AI没问,直接猜了一个最合理的解释填上去,然后基于这个猜测生成一整份设计文档。

你纠正完,再让AI实现,跑出来发现边界条件又没覆盖,回头再补。与此同时,代码库里明明有个现成的工具函数,AI视而不见,自己新建了一个。

两个场景反复出现,一开始你会把它们当两件独立的事处理——需求不完整,去补需求;AI跑偏了,去纠正实现。但补完需求再实现,还是跑偏;纠正完这次,下次又偏。每个问题的解法都没有触及根因。

根因是什么?你写需求规格时,期待的是”把意图描述清楚,机器忠实执行”;但AI实际在做的是”根据上下文预测最合理的续写”。你用的是规格驱动的心智,操作的是生成驱动的工具,这两个范式之间的鸿沟,不是靠写更好的需求就能填平的。

而且这里有个容易忽略的结构:需求不是你写的,是产品设计给的,但补全的责任落在你身上。你不是需求的创造者,你是翻译者——把不完整的上游意图翻译成AI能执行的规格。翻译环节天然有损耗,但你一直把这个损耗当成”自己没做好”,这才是焦虑加剧的原因。

AI最危险的时刻,不是它不知道,是它以为自己知道。给它一个模糊的输入,它不会停下来问”你确定吗”,直接推一个自洽的解释上去——推理能力越强,补位越自信,偏差越隐蔽。一个笨的AI给出的答案明显不合理,你一眼就能拦住;一个聪明的AI给出一个完全合理但方向错误的答案,你要走到半路才能发现走错了。

既然根因是心智模型错配,第一反应自然是:把需求规格写得更完整不就行了?

“完整需求”是个伪目标

所以你建了检查清单,做了需求结构化工具,每次拿到产品设计的需求就系统性地补全——技术名词展开、隐形交互显性化、默认常识写出来。

但焦虑并没有减轻。

为什么?因为你真正想要的不是”需求更完整”,而是”需求完整到不用返工”。这两件事的解法不一样——前者是开工前多想一步,后者是开工后降低纠错成本。你拿着清单逐项检查,补全的是规格的完整性,但一个缩略名词背后藏着多少业务上下文,只有写需求的人自己知道,你只能猜。清单补不了”业务理解的深度”,指望通过结构化工具弥补上游的认知缺口,本身就是天花板。

试想另一种情况:如果补全需求的成本是每次2小时,但实现后发现问题再改的成本只有15分钟,你还会坚持先把需求写到完美吗?策略取决于哪种返工更贵。在你的场景里,需求的根因在上游,你补到80%可能已经花了一个小时,要补到95%还得再花两个小时——而AI实现一遍只要十分钟。那更好的策略就不是”开工前想透”,而是”快速试一轮,用实现结果暴露需求遗漏”。

需求不完整不是成本,反复补全才是成本。

降低纠错成本,具体是纠正什么?是AI实现的偏差。那AI除了需求推理跑偏,实现阶段也会偏差——比如忽略已有代码自己新建。

代码库里明明有A,AI自己建了B

代码库里有个现成的`formatDate`,AI视而不见,自己新建了一个`formatDateNew`。

第一反应是”它又搞错了”。但换个角度想:AI选B而不选A,说明从它看到的上下文里,B比A更”自然”。问题不在AI选错了,而在A根本没出现在AI的视野里。

AI只看到上下文窗口里的内容。`formatDate`的代码不在里面,对AI来说它就不存在。需求偏差是”信息模糊导致推理补位方向错误”,实现偏差是”信息缺失导致推理从零建一座新的”。一个是AI脑补了错误的C,一个是AI没看到已有的A就自己造了个B。本质上都是上下文不充分时的推理补位

而且这个问题会随代码库增长恶化。你写了一万行代码的时候,AI大概还能”看到”大部分;等你写了十万行,需要被”看见”的东西翻了十倍,但上下文窗口没变,被忽略的概率反而更大。

对人类开发者来说,代码越多可复用的越多;对AI来说,代码越多”看不见”的越多。方向完全相反。

这不是靠”更好的prompt”能解决的,需要结构性的解法。具体来说有三条路:一是模块清单——在项目根目录维护一份清单文件,列出每个模块的职责、入口函数、关键依赖,AI开工前先读这份清单,知道代码库里有什么再动手。二是能力注册表——比模块清单更细一步,把所有工具函数按能力分类注册(比如”日期处理:formatDate、parseTimestamp”),AI需要某个能力时先查表再使用,而不是从零建一个。三是自动化的上下文注入——在AI开始实现之前,自动扫描它即将修改的文件的依赖链,把相关的现有代码拉进上下文窗口,而不是指望AI自己去找。前两条成本低、见效快,维护一份清单文件只需要十几分钟,但能大幅减少AI”视而不见自己新建”的情况。第三条需要更多工程投入,适合代码库超过十万行的项目。

既然AI在需求和实现两个阶段都会因为推理补位产生偏差,那给流程加防护层来兜底,总可以吧?

防护层越多越安全?恰恰相反

你给AI建了一条流水线:需求结构化→计划生成→TDD审查。每一层都在防止偏差,直觉上层越多越安全。

但算一笔账。每一层都不是完美的,假设每层可靠度90%,五步串联下来只剩59%。工程里叫”级联失效”——多级串联系统的整体可靠度等于每级可靠度的乘积。更关键的是,每一层防护本身也是一层新的故障点。需求结构化可能遗漏维度,计划生成可能误解意图,TDD审查可能漏掉边界。你给AI加的每一层防护,同时也是一层新的故障点。

如果不加这些防护层呢?AI直接从需求到实现,中间没有审查环节——你看到的偏差会更明显、更粗糙,但发现得也更快。加了防护层之后,每一层都在帮你”修正”一些问题,但同时也在引入新的问题,而且新引入的问题往往更隐蔽,因为它们经过了”流程背书”——你会觉得”这已经经过结构化审查了,应该没问题”,反而放松了警惕。

这不是说防护层没用。但需要承认一件事:你用的是确定性工程的方法——写规格、做审查、建流水线——操作的是一个概率性系统。同样输入,不同采样可能给出不同输出。防护层提高的是概率,不保证结果。你的焦虑程度说明,你心里期望的是保证。

既然防护层有天花板,那继续优化工具和流程,意义在哪?

你在建工具,还是在回避执行?

到这一步你可能会发现一个让自己不舒服的规律:每当执行层让你焦虑——AI又跑偏了、需求又漏了——你的反应不是直接解决那个具体问题,而是退到元层去优化流程、改进工具、完善体系。

元层花的时间越多,执行层交付越慢,焦虑加剧,更往元层退。说得更直白一点:你花了两天优化一个skill,让它能更准确地补全需求。但这两天里你原本可以直接用AI做两轮快速实现、发现问题、纠正——总耗时可能只要半天。你选择了两天而不是半天,因为优化工具比交付功能更有安全感。建工具可能已经不是手段,而成了应对执行焦虑的防御机制。

还有一个更隐蔽的维度:你的skill体系解决的是”单次对话”的问题,但焦虑来自”跨对话”。每次和AI对话都是全新的,纠正过的事、建立的约定、补过的上下文,全部归零。你把对齐经验编码成skill,让下次对话自动对齐,方向没错——但你只持久化了流程和规则,没有持久化决策和理由。为什么选了A方案不用B,为什么这个模块的边界定在这里。这些才是下次对话中最容易丢失、又最需要的信息。

所以偏差是不可避免的,防护层也有天花板,建工具可能是逃避——那偏差本身,有没有可能不是纯粹负面的东西?

偏差不是bug,是信号

AI新建B而不复用A——你一直把这当噪音:AI搞错了,去纠正就行。

但如果B在AI的上下文里比A更自然,这恰恰说明A在代码库中的可发现性有问题。命名、位置、调用方式,可能都不够直观。每一次偏差都在暴露代码库的”可发现性债务”——那些你觉得”明明有啊”的东西,在别人(或AI)的视角里根本找不到。把这些信号积累起来去改善架构,比每次手动纠正更有价值。

再深一层:你默认”我的设计意图正确,AI偏差是错误”。但你的设计意图本身也是近似的、在演化中的。有些偏差不是AI搞错了,而是它用不同的推理路径走到了一个你没想过的方案。举个例子:你设计了一个工具函数处理日期格式,AI实现时用了完全不同的思路——你第一反应是”不对”,但仔细看发现它的方案在时区处理上反而更健壮。你没想到不是因为你的方案不好,而是你在这个点上根本没想过还有别的路。

把所有偏差当缺陷修复,等于预设自己的方案永远更优。

缓解焦虑的方向不是消除更多偏差,而是改变你和偏差的关系。

有些偏差需要更快发现和纠正——比如需求推理方向性错误,越早拦住代价越小。有些偏差值得看一眼再决定——比如AI选了一个你没预期的技术方案,先看看它为什么这么选,说不定有道理。还有些偏差根本就是信息——比如AI忽略已有代码自己新建,说明你的代码库可发现性该优化了。

下次AI的实现和你预期不同时,先问一句”它为什么走了那条路”,再决定要不要改回来。如果它忽略了你写的某个函数,也许不是它看不见,而是你写的东西在该被看见的位置上不够显眼——毕竟,代码越多,AI”看不见”的越多,这个趋势只会加强,不会反转。

内容很长,如果你只能记住三件事,我希望是:

1. 你不是需求的创造者,你是翻译者——需求不完整的根因在上游,别把翻译损耗当成自己的问题。

2. 代码越多,AI”看不见”的越多,方向和人类完全相反——这是代码库增长带来的结构性风险,不是靠更好的prompt能解决的。

3. 策略取决于哪种返工更贵——算一笔账,如果补全需求的边际成本远高于AI实现一轮的成本,就别在开工前想透,改成快速试一轮暴露问题。

这篇文章把”为什么偏”拆清楚了,但没回答”怎么治”——模块清单具体怎么写、快速试错的workflow怎么搭、跨对话的上下文怎么持久化。这些操作层面的东西,下篇展开