ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI编程重蹈覆辙:复杂度守恒与技能断层,工程师如何应对?

AI编程重蹈覆辙:复杂度守恒与技能断层,工程师如何应对? 上个月帮一个朋友做内部项目的 code review他特别兴奋地跟我说“现在我们 80% 的代码都是 AI 写的效率翻了三倍。”我花了半小时把改动看完问题在评论区列了一长串数据库层有七八处 N1 查询没处理事务边界一会儿放在 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 或 JavaAI 基本能直接输出可用的版本虽然细节需要人工校准但比从零写快太多。但落到生产环境里AI 生成代码的问题也同样明显。最先暴露的是局部正确、整体错误的问题AI 对当前函数范围内需求的还原度很高但一旦涉及全局约束——比如事务边界、分布式一致性、权限模型、历史兼容逻辑——它就很容易给出“看起来很合理、实际上会埋雷”的代码。恰恰是这些约束决定了系统在真实流量下会不会出事故。2.3 那些 AI 代码导致的“慢痛”AI 生成的代码很少会让你“当场崩溃”它造成的伤害更多是慢性的、累积的。典型情况一数据库查询的 N1 问题。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 帮你把思考变成代码。这是我在实操中最大的体会也是我最后想分享给大家的一句话。
返回列表