AI写80%代码背后:辅助编程工作流与工程踩坑

AI写80%代码背后:辅助编程工作流与工程踩坑 1. 现象拆解80%这个数字到底意味着什么前段时间刷到一条行业消息说某家做大模型的AI公司对外披露他们内部代码仓库里大约80%的代码是AI自己写出来的几乎同一时间这家公司的负责人又公开呼吁行业给AI开发踩一脚刹车。这两个信息摆在一起荒诞感和真实感是同时涌上来的——工具已经被用到这个程度用工具的人反而开始担心工具跑得太快。作为一个常年泡在代码里的开发者我第一反应不是震惊而是好奇这80%到底是怎么算出来的又是哪一类活被交了出去。AI开发这件事这两年被聊得太多真正落到日常编码的细节反而少有人讲透所以这篇就把我看到的、试过的、踩过的东西摊开说不管你是刚接触AI编程提示词的新手还是已经带着AI Agent做项目的工程师都能从里面拿到能直接抄作业的东西。1.1 从自动补全到自主生成AI写代码走了三级台阶要理解80%这个数字得先把AI参与编码的方式分个层。最早的一层是行内补全你在编辑器里敲几个字符它猜你接下来要写什么本质上是加强版的自动补全比如补一个for循环的骨架、填一个早就忘了参数顺序的库函数这种帮助是被动的你不动它就不动。第二层是对话式生成你把需求描述清楚丢给它它吐出整段甚至整个文件的代码像“写一个读取CSV、按城市分组求平均值的函数”它一口气连空值处理和异常捕获都给你带上。第三层是Agent也就是常说的ai agent开发你丢一个大任务过去它自己读文件、改代码、跑测试、看报错、再改循环到你点头为止中间几乎不需要你插手。这三层对应的是三种完全不同的信任程度。第一层你基本不用怀疑因为最终敲进去的每一个字符都在你眼皮底下过了一遍第二层你需要审逻辑对不对、边界处理全不全得自己读一遍第三层的信任成本最高因为它会动你的仓库、装依赖、执行命令一旦方向跑偏你回滚的成本可能比从头写还高。所以当一家公司说“80%的代码是AI写的”如果没有说明白是这三层里的哪一层占主导这个数字的含金量其实差别巨大。1.2 别被80%唬住先搞清楚它统计的是什么“代码由AI生成”这句话最大的陷阱就在统计口径。我见过几个团队做过类似的内部统计得出的数字能从15%跳到75%区别只在于统计方式不同。下面这张表是我自己梳理的几种常见口径你可以对照着看自己团队大概落在哪个位置。统计口径具体含义常见的虚高原因行数占比仓库里由AI生成的代码行数占比把样板代码、注释、空行都算进去采纳率AI建议中被开发者接受的比例只统计“接受”动作不看后续被改了多少Token占比AI输出token占全部改动token忽略了开发者反复重写的部分有效逻辑行去掉模板、注释、测试数据后的核心逻辑行这个数字通常最低但最能说明问题提交归属Commit里标注AI协作的占比依赖开发者自觉标注样本有偏差真正有意义的指标其实是“有效逻辑行”加上“返工率”这两个组合起来看。我做过一个小实验让AI独立生成一个中等复杂度的数据处理模块代码行数上它写了差不多95%看起来非常漂亮但如果只算核心业务逻辑比例掉到大概60%因为大量行数是日志、参数校验、类型声明这些周边内容。更关键的是返工那个模块我前后改了四轮第一轮的问题是拿了一个根本不存在的方法名第二轮是分页边界处理错了第三轮是并发场景下没加锁第四轮才是性能问题。把返工的时间折算进去最终“净节省”的工时并没有行数看起来那么夸张。这不是说AI写代码不行恰恰相反它的价值是真实的只是别被一个孤立的百分比带着走。看到任何“AI写了X%的代码”的说法先问三个问题算的是什么口径返工率多少出问题谁兜底。想清楚这三个你对这个数字的免疫力就建立起来了。1.3 呼吁暂停的悖论为什么踩刹车的往往是踩油门的人比80%更有意思的是后面那半句——呼吁暂停。乍看之下很矛盾一家把AI用到了极致的公司反过来劝大家慢一点。但如果你真的在工程一线待过这个动作其实一点都不难理解。工具跑得越快留给人的评估窗口就越短而软件的复杂度是随规模非线性增长的。AI可以在一周内给你堆出一个能跑的系统但这个系统里埋了多少没被验证过的假设只有出事的时候才暴露。我自己的体会是AI开发带来的不是“写不出来”的问题而是“写得太快、来不及想清楚”的问题。以前写一个模块要三天那三天里你会不自觉地反复琢磨设计很多坑是在敲代码的过程中被顺手填掉的。现在AI十分钟给你一版你看着能跑就往下走了那些原本会在慢速编码中被消化的思考被跳过去了。所以所谓的“暂停”很多时候不是反对工具本身而是反对那种“因为能快速生成所以就不加评估”的节奏。这个提醒对个人开发者也成立你手上有了一把快刀更需要的是刀法而不是挥得更快。接下来的几节我就把自己在AI辅助编程里总结出来的完整流程拆开讲从工作流到落地细节再到踩坑清单尽量给到能直接复现的东西。2. AI辅助编程的真实工作流长什么样很多人用AI写代码用得很累然后得出结论说“AI不靠谱”。我观察下来问题通常不出在模型而出在工作流。把AI当搜索引擎用的人得到的是一堆零散代码片段把AI当新人带的人得到的是一个能进仓库的模块。这两种用法之间的差别就是下面这几个环节有没有做扎实。2.1 上下文准备把AI当新人带而不是当搜索引擎用我吃过最大的亏就是不给上下文直接发一句话需求。比如我说“写个用户登录接口”它给我的东西五花八门有的用Flask有的用Express有的用FastAPI密码加密方式每次都不一样。后来我改了个习惯每次开口之前先做三件事。第一把相关的目录结构和已有代码贴给它让它知道项目在用哪套技术栈、命名风格是什么样。第二把数据模型说清楚字段名、类型、约束一个不落。第三明确告诉它我要的输出形式是完整文件、是补丁、还是只要核心函数。这个习惯看起来费时间实际上省的是后面反复返工的时间。你可以把这理解成带新人你不会跟一个刚入职的同事说“你把登录做了”然后指望他一次做对你会给他看现有的代码、告诉他规范、指出参考实现。AI和新人唯一的区别是它不会累、不会不好意思问但前提是你得把该给的背景给全。实测下来同样一个模块做足上下文的版本一次通过率能到七成以上不做上下文的版本大概只有两成。2.2 生成、审阅、验证的三段式闭环我现在用AI写代码基本是固定套路分成生成、审阅、验证三段每段有明确的产出。生成阶段只管让它把东西造出来这时候不纠结细节因为早期版本注定要被改。审阅阶段是我花时间最多的地方重点看四件事依赖的库和方法是否真实存在、边界条件有没有处理、异常路径是否完整、有没有明显的性能陷阱。验证阶段就是把它扔进测试里跑跑不过就带着报错回到生成阶段。这个闭环的关键是不要让三个阶段混在一起。我见过有人一边让AI改、一边自己手动改、一边又跑测试最后出了问题根本不知道是哪一步引入的。分开之后每次出问题你都能定位到具体环节返工效率高很多。顺带提一句审阅阶段我完全不看它的注释只看代码本身因为AI写的注释有时候和代码逻辑是对不上的信注释会把你带沟里。2.3 代码评审与责任归属代码是谁写的这件事在工程里有明确的后果——谁提交谁负责。AI生成的代码也一样。我的原则很简单任何合进主干的代码都必须有人能对它的逻辑负责这个人就是提交者不能因为它是AI生成的就把责任摘出去。所以在团队里我会要求AI参与生成的改动提交信息里要标注清楚哪些部分是生成的方便事后追溯。这不是形式主义。真出线上问题时你回看提交记录能快速知道这段代码是怎么来的是有人精心设计过还是随手让AI补的排查方向完全不同。有些团队还会在PR里加一条检查项要求作者说明“这段代码我验证过哪些场景”这个动作成本很低但能挡住大量没想清楚就提交的改动。2.4 工具选型的几个务实判断工具这块我不做具体品牌推荐列几个我判断时用的维度你自己套。第一看它和你编辑器的集成度能否直接读到项目上下文这决定了它给的建议准不准。第二看它的输出可控性能不能约束代码风格、能不能指定不要用某些库。第三看它对多文件改动的支持单文件补全和跨文件重构是完全不同的能力层级。第四看隐私和数据策略是否满足你所在团队的要求。第五看它在出错时的表现是干脆编一个不存在的API糊弄你还是会承认不确定。我的经验是不要迷信某个工具的“全能”大部分工具在补全类任务上表现都差不多真正拉开差距的是跨文件理解和Agent执行能力。选型时不妨拿你自己项目里一个真实的、有点复杂的重构任务去试比看任何宣传材料都管用。3. 把AI生成的代码落到工程里的关键环节工作流搭起来之后真正决定成败的是落地细节。这一节讲几个我反复打磨过的操作要点包括提示词怎么写、测试怎么安排、静态检查怎么接、版本怎么管以及Agent用到什么程度就该收手。3.1 提示词不是玄学是约束条件AI编程提示词这件事被讲得神乎其神其实核心就一句把你脑子里的约束条件写出来。大部分人写提示词只写“要什么”不写“不要什么”和“必须满足什么”。我现在的模板大概是四段式目标是什么、输入输出长什么样、有哪些硬约束、出问题时的降级方案。硬约束这块最容易被忽略但对结果影响最大比如“不要引入新的第三方依赖”“异常必须抛出自定义错误类型”“所有外部调用必须加超时”。举个具体例子。我要一个分页查询会这样写# 需求实现按用户ID分页查询订单 # 约束 # 1. 使用已有的 db 连接对象不新建连接 # 2. page 从 1 开始page_size 默认 20上限 100 # 3. 返回结构 {items: [...], total: int, page: int} # 4. 查询为空时返回空列表不抛异常 # 5. 不允许用 SELECT *显式列出字段 def list_orders(db, user_id, page1, page_size20): ...把约束写在前面的代码块里比用自然语言劝它“注意边界”有效得多。原因很直接结构化的约束对模型来说歧义更小它不需要猜。你可以把这段当成模板换成自己的业务需求实测识别率明显提升。3.2 测试先行让AI先写测试再写实现这是我个人最喜欢的一招也强烈建议你试试不要让AI直接写实现先让它写测试。听起来绕但收益很大。因为测试描述的是“行为”是明确的输入输出AI写测试时不容易跑偏而实现是“手段”它可能用一堆你没想到的方式去实现同一个行为。先有测试再让AI去填实现就相当于给它画好了靶子。具体怎么操作我先用自然语言把业务规则列清楚让AI生成一组测试用例覆盖正常路径、边界值、异常输入。生成完之后我自己过一遍这些测试确认它们符合我对业务的理解然后才让AI去写实现目标是把这些测试跑绿。这个顺序的好处是即使实现写得再花哨只要测试能过至少行为是对的。而且测试本身是资产AI重写实现的时候它还在相当于给你加了一层保险。注意AI生成的测试同样需要审。我遇到过它把错误行为写进测试然后实现照着这个错误行为去写两头都对上了测试全绿但业务逻辑本身是错的。测试断言的那部分必须由人来把关。3.3 静态检查与代码诊断AI写的代码有个特点看起来很整齐但不一定符合你的项目规范。所以静态检查工具这块不能省一般编辑器里的代码诊断插件就能挡住一部分问题比如未使用的变量、类型不匹配、循环里的重复计算。更严格的做法是接上Linter和类型检查器把它作为提交前的门禁。# 提交前的典型检查顺序按成本从低到高 ruff check . # 快速风格与常见错误检查 mypy src/ # 类型检查挡住类型相关的隐患 pytest -q # 单元测试这套东西的价值不在于它多聪明而在于它稳定。AI每次输出的风格可能都不一样但检查规则是固定的它能保证不管谁写的代码过门槛的标准是一致的。我习惯把这几步接进git的pre-commit钩子这样AI生成的代码在提交那一刻就会被筛一遍比事后review发现问题要高效得多。3.4 版本管理与可追溯性AI参与开发之后提交粒度这件事变得更重要。以前一个功能可能一大坨提交现在我会刻意把AI生成的部分和人工修改的部分拆开提交。原因是当出问题需要回滚时你能精确地回滚AI生成的那部分而不必连带把人工写的逻辑一起撤掉。具体做法很简单AI生成一版先提交标注清楚这是生成版本然后我审阅修改后再提交一版标注修改内容如果后续发现问题直接看这两版之间的diff就能定位。这比把所有改动混成一个提交要好太多。另外我会给关键模块加一个简短的头注释记录这个模块的设计意图和验证过的场景AI很难自己写出准确的意图说明这部分必须人补但它的价值在半年后会体现得非常明显。3.5 Agent化开发的甜区与边界Agent用在什么地方最划算我的经验是任务边界清晰、验证方式客观、失败成本可控的场景最适合。比如批量重命名、补充类型标注、把一类写法统一替换成另一类、修一批已知模式的告警这些活的共同点是“做错了很容易看出来改动可以快速回滚”。反过来涉及核心业务逻辑设计、并发安全、数据一致性、权限校验这类任务我基本不让Agent自己拍板只让它做辅助最终逻辑由人来定。原因是Agent的强项是执行和迭代弱项是判断“这个设计是不是合理”。它能把一个错误的设计执行得很完美。所以我会给Agent明确划定操作范围比如只允许改特定目录、只允许跑只读命令、改动必须通过测试才能继续。这些边界设定看起来限制了它的能力但实际是在保护你的仓库不被一次跑偏的自动执行搅乱。4. 踩坑实录AI生成代码的高频问题与排查这一节基本是我这两年被AI坑出来的经验集合。说出来可能不好听但每个坑我都真实踩过写出来是为了让你少走一遍。下面按问题类型分开讲最后附一张速查表排查的时候可以直接对着找。4.1 幻觉API和根本不存在的库这是最高频也最隐蔽的问题。AI会非常自信地调用一个不存在的方法或者给你一个听起来很合理但实际没有的库名。它不会说“我不确定”语气上完全看不出破绽。我第一次遇到是在orm层它给了一个看起来很标准的链式调用我直接用了跑起来才发现那个方法在这个版本根本没有。对付这个问题我的做法是所有AI引入的API第一次使用前必须查官方文档确认存在且版本匹配。听起来很笨但这是唯一可靠的办法。更省事的版本是让AI在生成时附带一个“用到的API清单”然后我逐个核对。或者干脆在提示词里写清楚“只允许使用以下已存在的接口”把它锁死在已知范围内。4.2 边界条件与异常处理AI写代码有一种“乐观倾向”它假设一切顺利空值、超长输入、并发冲突这些它经常漏掉。我统计过自己review过的一批AI生成函数正常路径基本都对但边界处理的缺失率相当高。最典型的是循环里的越界分页的最后一条还有外部调用的超时和失败重试。解决办法有两个层次。浅层的做法是提示词里明确要求“必须处理空输入、必须处理超时、必须处理部分失败”这能挡掉一部分。深层的做法还是回到测试用专门的边界测试用例去逼它比如传空列表、传极大值、传非法参数跑不过就修。这一层更可靠因为它是用结果验证行为不依赖它的自觉。4.3 性能与安全盲区性能问题AI很少主动考虑它能写出功能正确但效率很差的代码比如在循环里反复查数据库或者在内存里攒一个巨大的列表。这类问题在小数据量下完全不显形上线以后才爆。安全上更麻烦一些比如字符串拼接SQL、日志里打印敏感字段、对外部输入不做校验这些AI都可能在“能实现功能”的前提下写出来。我的应对是给关键路径加上性能和安全两条检查线。性能上对涉及批量操作的代码做一次小规模压测看看有没有明显的时间复杂度问题。安全上所有外部输入必须经过校验所有数据库操作必须参数化日志必须过滤敏感字段这几条我会当成硬规则写进提示词里并且在review时逐个确认。4.4 依赖与许可证风险AI有时候会推荐一个“方便”的第三方库你不知道它的来源、维护状态、许可证类型。个人项目可能无所谓但在团队项目里随手引入一个没人维护的依赖后患很大。我的原则是默认不让AI引入新依赖需要什么先在项目已有依赖里找找不到再说。如果确实需要新库那也必须经过选型评估看它的活跃度、许可证、有没有已知问题这个流程不能因为“AI推荐的”就走捷径。4.5 常见问题排查速查表现象最可能的原因排查方向运行时报方法不存在幻觉API或版本不匹配核对官方文档与当前依赖版本测试在边界输入时崩缺少边界条件处理补空值、极大值、非法参数测试数据量小时正常大时卡循环内查询或复杂度问题检查循环中的IO调用做压测偶发死锁或数据错乱并发场景未加保护检查共享资源访问是否加锁提交后CI报类型错误类型标注不一致跑类型检查补齐标注线上出现敏感信息泄露日志未过滤或输入未校验排查日志输出与外部输入校验依赖库突然报漏洞引入了不合规依赖审查依赖许可证与维护状态这张表我基本是贴在显示器旁边用的新问题出现时先对一下命中率挺高。需要说明的是表格里的“最可能原因”是概率判断不是结论真正的定位还是要看堆栈和复现步骤别偷懒直接照表下药。5. 对开发者意味着什么前面讲了这么多技术细节最后想聊聊这件事对人本身的影响。AI写了80%的代码那剩下20%是什么我的观察是剩下的份额越来越集中在判断上而不是产出上。这个变化对每个开发者都是真实的早点想清楚自己的位置比焦虑有用。5.1 从写代码的人变成审代码的人以前衡量一个开发者的水平很多时候看他写得多快、多熟。现在这个指标在弱化因为“写”这件事的边际成本在快速下降。真正被拉开的是审的能力你能不能一眼看出这段代码的问题能不能判断这个设计是否合理能不能预判它在什么场景下会崩。这种能力没法靠刷题获得它来自大量真实的踩坑和对系统的理解。我现在带新人会刻意训练他们读代码和挑毛病的能力而不是让他们练手速。给他们一段AI生成的代码让他们找出所有可能出问题的地方这个练习的强度比写一百个函数都高。对个人来说也是一样的与其纠结“AI会不会取代我”不如问“我审代码的水平配不配得上我拥有的生成速度”。5.2 学习路线该怎么调基础的语法和常见数据结构当然还得会这是你判断的前提看不懂代码的人谈不上审。但学习的重心可以往两个方向偏。第一个方向是系统设计理解模块之间怎么配合、数据怎么流转、故障怎么隔离这些是AI不太能替你做判断的地方。第二个方向是调试和排查出了问题能不能快速定位这是日常工作中高频且高价值的技能而且是AI最不擅长的环节之一。反过来那些纯粹靠记忆的东西优先级可以降一降。比如某个库的函数签名、某种语言的语法糖写法这些让AI来给就行你只要会判断对不对。把省下来的精力放到理解系统是怎么运转的上这个投入回报比更高。5.3 团队协作方式的变化AI参与开发之后团队的协作方式也在变。以前code review是一个人从头读到尾现在很多团队改成“先让AI粗筛一遍人只看AI标记出的可疑点”效率提升明显。但这里有个前提就是团队要建立统一的标注规范哪些改动是AI生成的、哪些是人工修改的、验证过哪些场景这些信息必须透明。我参与过的一个项目就是这么做的提交信息里固定几个字段写清楚生成来源和验证情况reviewer一眼就能知道该重点看哪里。这套规范刚推的时候有人嫌麻烦用了两个月之后大家都回不去了因为排查问题的速度快了不止一倍。协作方式的变化本质上是把“信任”这件事从口头承诺变成了可追溯的记录这在人机混合协作里尤其重要。回到开头那家公司的呼吁我不觉得那是在否定工具更像是在提醒节奏。工具越强越需要配套的评估和边界否则生成出来的东西越多欠下的债也越多。我自己这两年的体会是AI让写代码变快了但让“想清楚”这件事变得更贵了而那部分恰恰是省不掉的。你要是问我下一步最该练什么我会说练怎么在十分钟内看出一段代码的毛病这个能力在接下来几年只会越来越值钱。