上个月帮一个朋友做内部项目的 code review,他特别兴奋地跟我说:“现在我们 80% 的代码都是 AI 写的,效率翻了三倍。”我花了半小时把改动看完,问题在评论区列了一长串:数据库层有七八处 N+1 查询没处理,事务边界一会儿放在 service 层、一会儿放在 controller 层,异常被 catch 之后直接吞掉,日志里什么都没留下。他说这些都是 AI 生成的,反正测试能过。
我盯着那句话看了很久,忽然意识到一件事:AI 编程正在以一种特别真实的方式,重蹈人类编程过去六十年的覆辙——我们当年在工程化道路上踩过的坑,现在换了个形态,被 AI 加速放大了一遍。
1. 人类编程其实一直在“重蹈覆辙”
要说 AI 编程哪里在“重蹈覆辙”,得先搞清楚人类编程本身是怎么一步步走到今天的。回头看这几十年的软件工程演进史,你会发现一个极具讽刺意味的规律:每一代新技术在刚出现时,都声称能彻底解决上一代的所有问题,结果没过几年,它自己就成了新的问题源。
1.1 每一层抽象都在解决问题,又制造新问题
最早的程序员直接用机器码写程序,后来觉得太难记,发明了汇编语言。汇编比机器码好懂,但写复杂程序依然痛苦,于是诞生了高级语言,比如 C 和 Fortran。高级语言不够用,就出现了面向对象、设计模式、各种框架;框架还不够,就搞出了云原生、微服务、容器化。
这套演进逻辑听起来很合理:每上一层抽象,开发效率就提升一次,门槛就降低一次。但代价是,下层能力在绝大多数开发者的知识体系里逐渐消失。现在你随机问一个写 Java 的工程师,volatile底层到底怎么实现,或者一个 Go 程序从函数调用到系统调用之间具体发生了什么,很多人是说不清楚的。这不是他们不努力,而是抽象层把他们保护得太好了,已经不再需要在那个层面思考。
到了今天,AI 编程做的事情本质上是给这个抽象链条再叠一层:把“人类写代码”抽象成“人类描述需求,模型生成代码”。表面上看效率大幅提升,但这一层抽象和前几层一样,也带来了全新的复杂度,只是这些复杂度从看代码的阶段,转移到了看行为、看维护、看排障的阶段。
1.2 每次工具革命都会伴随一次“技能大洗牌”
另一个被忽略的事实是,编程工具每次升级,都会带来一波技能淘汰和岗位震荡。当年可视化开发工具流行时,很多人说“拖拽式开发会取代程序员”,结果没有;代码自动补全流行时,又有人说“程序员只需要会拼 API”,结果也没有。真实发生的变化其实是岗位结构的重塑:低端重复编码需求减少,理解和设计系统的能力变得更加值钱。
AI 编程对岗位结构的影响,比历史上任何一个工具革命都来得更快更猛。过去从“拖拽式开发”到彻底改变工作内容,用了将近十年;而现在,从 Copilot 到 AI Agent,再到能独立处理多步骤任务的智能体,只用了两三年。很多团队第一时间感受到的不是“效率翻倍”,而是 Junior 工程师该学什么、Senior 工程师该干什么,全都变得模糊了。
这就埋下了一个隐患:如果新入行的程序员把 AI 当成“不用理解也能写代码”的自动生成器,那他们很可能在职业生涯最关键的几年里,绕过所有基本功训练,直接跳到“用自然语言指挥机器”的层面。结果就是:代码能跑,但没人真正知道它为什么能跑;出了问题,也没人知道该从哪里下手排查。
1.3 人类当年的“覆辙”到底是什么
我想把“覆辙”这个词说得更具体一点。过去几十年软件工程领域反复踩的坑,大致可以归结成四类:
- 复杂度转移而不是消灭:抽象层减少了某个层面的复杂度,但总复杂度守恒,只是换了个地方寄存。
- 工具链膨胀超过实际收益:引入大量工具来解决之前工具的问题,最终维护工具本身变成一项繁重工作。
- 技能断层:底层技术细节被封装之后,从业者的底层能力逐渐退化,一旦抽象层出现 bug,没有人能修。
- 效率假象:局部效率大幅提升,但整体系统稳定性和可维护性在悄悄下降,技术债越滚越大。
这套框架几乎可以套用到每一代编程范式上,从框架到中间件到一个微服务治理平台,全是同一个剧本。而现在,AI 编程成为这套剧本的最新一集,只是这次连“写代码的人”都开始被抽象掉了。
2. 拆解 AI 编程今天到底做到了什么程度
先不谈宏大的未来预测,回到当下的技术现实。AI 编程今天能做的事,以及它的能力边界,是理解“重蹈覆辙”的前提。
2.1 从补全到代写,再到自主执行
目前市面上主流的 AI 编程能力可以分成三个梯度。
第一梯度是代码补全,代表工具是 GitHub Copilot、通义灵码这类 IDE 插件。它的核心逻辑是“根据上下文预测下一段代码”,在你写函数名、写注释、写少量代码时,帮你续写相关实现。这一层能力现在非常成熟,对日常开发效率的提升是实打实的。
第二梯度是代码生成,给定一个需求描述,直接返回完整函数甚至完整模块。比如你告诉它“写一个处理 CSV 文件并做数据清洗的 Python 类”,它能直接生成可用代码。这个梯度的价值在于将“搜索引擎查写法 + 复制粘贴 + 改改跑跑”的流程压缩成一步。
第三梯度是 AI Agent,它能拆解多步骤任务、调用外部工具、读写文件、执行命令,甚至自己跑测试并修 bug。OpenAI 的 Codex、Devin、以及各种开源 Agent 框架(比如 LangChain 生态、AutoGPT 等)都在朝这个方向努力。这个梯度更接近“一个虚拟程序员”,而不是一个“代码生成器”。
三个梯度之间不是线性的替代关系,而是叠加关系。实际开发中,最理想的状态是:补全处理零碎的重复代码,生成器负责标准模块,Agent 负责跨文件的复杂需求。但这种理想状态有个前提——人类必须能够审查、理解、修正它们产出的东西。一旦这个前提被忽略,问题就来了。
2.2 实际场景里的真实表现
从我自己团队和几个朋友团队的使用情况来看,AI 编程在如下几类任务中确实表现突出:
- 样板代码和胶水代码:像 DTO 转换、数据访问层基础封装、CRUD 接口、配置文件解析这类重复性高、逻辑简单的代码,AI 生成几乎零失误,而且速度极快。
- 单元测试生成:告诉 AI“这个函数需要覆盖这些边界条件”,它能快速生成一组测试用例,测试覆盖率的起点立刻拔高。
- 代码解释和理解:面对一段生僻的老代码,让 AI 用通俗的语言解释它做了什么,比人肉去读要快得多,尤其是接手祖传项目时很好用。
- 跨语言迁移:把一段 Python 写的逻辑改成 Go 或 Java,AI 基本能直接输出可用的版本,虽然细节需要人工校准,但比从零写快太多。
但落到生产环境里,AI 生成代码的问题也同样明显。最先暴露的是局部正确、整体错误的问题:AI 对当前函数范围内需求的还原度很高,但一旦涉及全局约束——比如事务边界、分布式一致性、权限模型、历史兼容逻辑——它就很容易给出“看起来很合理、实际上会埋雷”的代码。恰恰是这些约束,决定了系统在真实流量下会不会出事故。
2.3 那些 AI 代码导致的“慢痛”
AI 生成的代码很少会让你“当场崩溃”,它造成的伤害更多是慢性的、累积的。
典型情况一:数据库查询的 N+1 问题。AI 根据面向对象直觉构建实体关系映射,生成一个获取订单列表的方法,内部循环中自动访问每个订单关联的用户信息。小数据量下毫无感觉,等线上数据量上来了,一次列表请求发出几百条 SQL,数据库直接被打爆。
典型情况二:异常处理策略混乱。AI 生成代码时倾向于“尽量让程序不报错”,所以它经常在你想让异常抛出去的地方默默吞掉异常,或者在错误的层级捕获。后果是线上报错被静默,问题积压到最后一次性爆发。
典型情况三:过度设计。AI 看到你给它上下文里有几处相似逻辑,它可能会自动抽象出一个通用的接口 + 多个实现类。对于一个小需求来说,这种抽象完全没必要,还让后来接手的人苦不堪言。
这些问题的共同点是:它们不会在 AI 生成代码的那一刻出现,也不会在测试阶段暴露,大多数是在上线几周、几个月后,以线上事故或技术债的形式反噬回来。这跟当年人类程序员在规模化工程里踩过的坑,本质上没有任何区别。
3. AI 编程正在重蹈的四个核心覆辙
把历史规律和 AI 编程的现状放到一起看,你会发现“重蹈覆辙”不是一个比喻,而是一个正在发生的工程现实。我把它拆成四个维度来讲,每个维度都有具体的表现和判断依据。
3.1 复杂度守恒:被转移的复杂度没有消失
我特别想强调一个概念:复杂度守恒。无论工具怎么升级,软件开发过程中要面对的复杂度总量大体是不变的,工具能做的是把它分配到不同的环节。人类写代码时,复杂度分散在编码、调试、维护、协作各个环节;AI 写代码时,编码环节的复杂度被大幅压缩了,但调试和维护环节的复杂度被急剧放大。
举个例子。一个后端接口,以前人类写可能要两个小时,但写完基本知道每行代码的意图。现在 AI 生成只要三分钟,但你要么花大量时间去审查它,要么就抱着“应该没问题”的心态直接合入。更可怕的是,当这段代码出问题时,你没有“我当时为什么这么写”的记忆锚点,只能依靠阅读 AI 生成的代码来反向理解它的逻辑——这种体验比读别人写的烂代码还要痛苦。
在信息论里有一个概念叫“不可压缩信息”,意思是有些复杂度无论怎么建模、怎么抽象,它都不会消失。软件系统正是这样一个包含了大量不可压缩复杂度的对象:业务规则之间的冲突、并发条件下的时序问题、不可预见的异常路径。AI 编程无法消灭这些复杂度,它只能把这些复杂度从“写代码的时候”迁移到“维护代码的时候”,从这个角度看,复辙已经在路上了。
Protocol 层面、数据一致性层面、分布式协商层面的复杂度,AI 帮不了你,它反而会在你不懂这些复杂度时,给你生成一套看似考虑了这些问题、实际完全没考虑的实现,把雷埋得更深。
3.2 工具链膨胀:IDE 插件从助手变成了“主子”
第二个覆辙是人类历史上反复出现的“工具吞噬工作流”。以前每个团队都有那么几个“配置管理大师”,负责维护 Jenkins 流水线、Kubernetes 部署脚本、各种监控告警规则。这些工具刚引入时都是为了解决自动化问题,结果维护工具本身变成了新的工作。
AI 编程正在复刻这个剧本,只是这次速度更快。你为了让 AI 更好用,开始学习 prompt 工程、学习不同模型的脾气、学习什么样的项目结构最利于 AI 理解上下文、学习怎么把大任务拆成 AI 能处理的小块。你可能还会引入向量数据库给 AI 做知识库,或者搞一套 Agent 编排框架来管理多个 AI 工具之间的协作。
听起来很熟悉对吧?这跟当年“为了管理微服务,引入了服务网格,为了管理服务网格,又引入了专门的运维团队”是完全一样的路径。工具解决了一部分问题,然后制造了更多需要被工具解决的问题。Jevons 悖论在这里同样成立:AI 让代码生产变得更便宜,于是我们对代码的需求量也增大了,最终代码总量不减反增,维护负担不仅没有下降,甚至可能上升。
3.3 技能断层:新入行的程序员正在失去“手写能力”
这是我觉得最值得警惕的一点。前几年我带过几个校招生,他们普遍能熟练使用各种框架,Spring Boot、MyBatis、Vue 都上过手,但让他们脱离框架写一个从请求到数据库访问再到响应的最小链路时,很多人会卡住。这不是他们笨,而是现代框架已经把他们保护得太好了,很多底层交互细节根本不用知道。
AI 编程会把这种“技能断层”推向极致。以前新人要理解一段代码,起码得逐行读过、调试过、改错过,才能形成“这段代码为什么会这样工作”的模型。现在,新人可以直接让 AI 生成代码,遇到问题直接让 AI 改,全程不需要知道内部机制。
短期看效率很高,但长期来看,这会导致整个行业出现一批“不会 debug 的开发者”。代码报错了,他们第一反应是把错误信息扔给 AI,而不是自己去追踪调用栈;线上出现问题,他们不是去看日志和指标,而是先去问 AI“这个报错可能是什么原因”。AI 当然能给出很多可能的原因,但没有能力和经验去判断哪个原因最符合当前系统的实际情况,这样的排查过程经常是缘木求鱼。
技能断层还体现在一个反向的维度上:资深开发者的判断力也在被弱化。当整个团队都以 AI 生成代码为默认生产方式时,资深开发者作为代码审查者,其实很难在有限时间内抓住所有问题。因为 AI 生成的代码风格统一、注释齐全、逻辑清晰,看起来太“优质”了,人类的注意力很难在每一行都能保持同样强度的警觉。
3.4 效率假象:局部效率提升,整体风险放大
最后这个覆辙,是最难被感知到的,因为它的代价是延迟的。
AI 编程带来的局部效率提升是肉眼可见的:同样的需求,以前写一天,现在写半天。但这种显性提升掩盖了一个隐性成本——它让错误的传播速度变快了。以前一个设计错误从产生到被修复,可能需要几天,因为编码、测试、评审之间有足够多的环节让人停下来思考。现在 AI 帮你把编码时间压缩到几乎为零,于是设计错误会以极快的速度被实现、被合入、被部署,直到线上反馈问题。
更棘手的是,当团队每个人都依赖 AI 写代码时,系统的集体心智模型会变得非常薄弱。以前一个核心模块是某个工程师手写的,他对这个模块的理解最深,任何修改他都能判断风险。现在代码是 AI 生成的,没有一个人对它有深度的理解,“代码所有权”的概念被稀释了。出了问题,往往出现所有人都在场、但没有一个人真正说得清现状的局面。
在这个意义上,AI 编程并不是单纯的“效率工具”,它更像是把一把双刃剑递给了整个行业:一边让产出提速,一边让理解减速。所以我说,AI 编程正在重蹈人类的覆辙——它没有拯救我们,它只是让注定要发生的坑,更快地出现。
4. 怎么避免这场覆辙:我的实操建议和排坑经验
讲了这么多问题,总得给出路。我不赞成“因噎废食式”地拒绝 AI 编程,也不赞成“全盘交给 AI”的躺平式应用。关键在于建立一套使用 AI 编程的工程纪律,把这个工具绑定在人类工程能力的轨道上。
4.1 给个人开发者:三条铁律
先讲个人层面的纪律。无论你是学生、自由开发者还是在职工程师,用 AI 编程时记住以下三条:
第一,AI 生成你能完全看懂的代码。如果 AI 生成的一段代码中,有任何一行你无法用自己的话解释它的作用,那这段代码就不应该进入你的项目。这不是教你放弃效率,而是确保你始终对代码库保有掌控力。你可以让 AI 生成代码,但生成之后必须逐行审查,哪怕慢一点,这个“审查”动作不能省。
第二,保留手写关键路径的肌肉记忆。像数据库连接管理、并发控制、事务处理、权限校验这些核心逻辑,我建议至少 30% 的工作量用“关掉 AI、亲手写”的方式完成。这不是矫情,而是这些逻辑一旦出错,代价极其沉重,你需要潜意识层面的熟悉度来排查问题,而这只能靠手写获得。
第三,把 prompt 当接口设计来写。大多数人给 AI 的指令都是“帮我写一个用户登录接口”,这是典型的需求描述,不是工程设计。好的 prompt 应该像一份需求规格说明书:它要包含输入输出定义、异常情况处理、性能要求、安全约束、边界条件。养成用工程思维写 prompt 的习惯,本质上是在锻炼你抽象需求的能力,这个能力与编程年限无关,但一定是未来最重要的人类技能。
4.2 给团队管理者:AI 代码审查的四道关卡
团队层面,建议每个引入 AI 编程的团队都要建立一套“AI 代码审查制度”,不是依赖平台已有的审查流程,而是针对 AI 生成代码的特点,设置专门的四道关卡:
- 第一关,架构对齐:AI 生成的代码是否能融入现有系统的架构风格?事务边界、模块边界、依赖方向是否符合团队约定?这关需要技术负责人或架构师来把关,适合用 checklist 的形式逐项比对。
- 第二关,性能与安全:检查数据库访问次数、循环复杂度、敏感数据是否被正确脱敏或鉴权、依赖是否引入了已知漏洞的版本。这个环节建议用自动化扫描工具辅助,因为人眼很难覆盖所有潜在攻击面。
- 第三关,可测试性:AI 生成的代码是否容易被测试?如果一段代码大量依赖全局状态、静态方法或者硬编码配置,说明它的可测试性很差,应该让 AI 重写,而不是将就着用。
- 第四关,可维护性:假设三个月后这段代码需要修改,一个不熟悉上下文的新人能快速上手吗?如果代码里充满了魔法数、深层嵌套、晦涩命名,建议直接打回重做,不要因为“能跑”就把标准降下来。
这四道关卡不是要增加团队的流程负担,而是把以前“人写代码时天然具备的隐式审查”显性化。当代码由 AI 生成时,这道“隐式审查”不存在了,你必须把它变成流程,否则就是在裸奔。
4.3 用“复杂度守恒”指导项目决策
最后,我强烈建议所有团队在决定“这个模块要不要用 AI 写”之前,先做一次复杂度分析。核心是一个简单的思考框架:
- 这个模块的复杂度是结构性的(业务流程本身复杂),还是生成性的(代码量庞大但逻辑简单)?
- 如果复杂度是生成性的,AI 可以放心用;如果复杂度是结构性的,AI 只能帮你完成落地,设计工作必须由人类完成。
- 还要问一句:这个模块出问题时的后果是什么?后果越严重,人为介入的程度就越高,AI 的作用就越应该被限制在“辅助生成草稿”的层面。
我刚带团队那会儿什么都要写“技术方案评审文档”,后来觉得是形式主义。但用了 AI 编程之后,我把它捡回来了。因为 AI 生成代码的速度太快了,如果前面没有一份清晰的方案让全团队对齐思考,AI 会干掉你一整个迭代周期的生产力,然后给你留下一堆“看似实现了需求、但整体架构已是一团乱麻”的代码。
4.4 我踩过的几个坑,希望你别再踩了
这三条是实操过程中亲测有效、但也付出过学费的教训,写出来供各位参考:
坑一:让 AI 直接改遗留系统代码。遗留系统里面充满了隐藏的业务规则、依赖顺序和隐式状态。AI 没有历史和上下文感知能力,它只会基于当前可见代码做局部推断。我曾经让 AI 优化过一个老模块的查询效率,它把 SQL 改成了一条“看起来更高效”的写法,直接把一个核心业务场景干出了数据不一致。后来这块代码整整回滚了两周。
坑二:没有给 AI 限定“能力边界”。一开始我们允许 AI 在项目中自由读取各类文件、自动修改代码。后来发现它会为了“完成任务”去修改一些与需求无关但“它觉得应该改”的东西。现在我们的方案里必须给 AI 一个白名单:哪些文件可以动、哪些模块不许碰、哪些依赖不能升级,这些全都是硬约束,写清楚之后 AI 的安全性会提升好几个等级。
坑三:忘记做回归测试。人工写代码时,代码合入前我们会做一轮回归测试。但 AI 生成代码时,很多人觉得“反正它自己会改”,跳过了回归。这是一个巨大的陷阱。AI 生成的代码在你测试覆盖不到的路径上埋雷的概率,比人类写代码高得多,因为它在生成时根本没有“我是否改动了其他模块”的全局意识。任何 AI 代码合入,都必须跑完整回归集,这个底线不要动。
5. 关于“重蹈覆辙”这件事,我的真实想法
说了这么多,可能有人觉得我是在唱衰 AI 编程。其实不是。
我用 AI 编程的频率很高,它帮我节省了大量写样板代码的时间,让我有精力去思考更有价值的系统设计问题。但我越来越强烈地感觉到:AI 编程不是把人从编程中解放出来,而是把人从“写代码”的环节里赶出来,推到“对代码负责”的环节里。
你可以不会写代码,但你必须能说清楚这段代码为什么这样写、它会带来什么后果、出问题后怎么排查——这三件事,恰恰是历史上无数优秀程序员一直在做的事。AI 编程没有改变这件事的本质,它只是把这个本质暴露得更明显了。
所以,“AI 编程在重蹈人类的覆辙”这句话,与其说是一个悲观的预言,不如说是一个清醒的提醒:技术在变,工具在变,复杂度守恒的规律不会变,对最终代码负责的人永远必须存在。AI 可以把我们从繁琐的语法和模板中解放出来,但它把更沉重的责任——理解系统、承担风险、维护秩序——交到了我们手上。
如果你现在刚开始学编程,别指望 AI 能让你跳过基本功直接成为高手。恰恰相反,在 AI 时代,基本功不仅没有被淘汰,反而变成了稀缺能力。谁能不看 AI 提示就写出清晰的代码,谁能不在 AI 辅助下独立排查一个复杂问题,谁就能在未来占据主动。
如果你已经在用 AI 编程,我建议你每隔几周做一次“无 AI 日”——关掉所有辅助工具,纯靠手工写一天代码。你会发现自己在哪方面已经钝化了,然后有针对性地补回来。这个习惯我坚持了半年,效果是我既享受 AI 带来的效率,也没丢掉作为工程师最重要的手艺。
说到底,覆辙之所以是覆辙,是因为人们总以为这一次会不一样。AI 编程确实改变了软件开发的许多细则,但只要“人类要对代码负责”这个大前提不变,那些根子里的教训就永远有效。别让 AI 替你思考,让 AI 帮你把思考变成代码。这是我在实操中最大的体会,也是我最后想分享给大家的一句话。