“氛围编码”这个词现在提起来我都有点PTSD。过去两年我几乎把所有能交给AI的代码都交给了AI——丢给它一个需求描述让它“照着氛围写”写完直接跑跑通就算完事。当时确实爽一天能交好几个功能老板满意我也以为自己效率翻倍了。直到最近这个“2年攒下的烂摊子”开始反噬——我发现自己面对一个自己亲手“催生”出来的项目完全不敢改代码因为改一行可能炸掉三个模块而这三个模块的代码我看不懂也不再理解了。终于在一连串线上问题之后我被逼着做了职业生涯里最痛苦也最清醒的决定把手底的系统拆开重新手写核心代码。这篇文章就想跟你聊聊氛围编码是怎么帮我挖出一个深坑的以及我为什么最终还是选择回到“手写代码”这条路上——不是否定AI而是重新夺回对代码的主导权顺便给同样在这条路上挣扎的人一些可执行的参考方案。1. 氛围编码的甜头与陷阱它为什么“好用”又留下了什么1.1 氛围编码到底是怎么回事先说概念。“氛围编码”vibe coding这个词简单说就是让AI尽可能多地参与编写代码人类只需要提供一段自然语言的需求描述比如“写一个用户登录接口带token刷新”然后照着AI生成的结果用起来就行碰到报错就继续把报错往对话框里丢让AI修到跑通为止。我一开始并不是全盘氛围编码只是用它写一些工具的脚本、临时报表的SQL后来慢慢演变成核心业务模块也让它写。那个流程是固定的我打开一个空的文件夹作者在脑子里想好大概要什么功能然后对着AI编辑器说“帮我搭一个什么什么系统”然后就是一连串的“这个功能再加一下”“这个地方老是报错修复一下”。代码长得什么样没看过。逻辑是怎么串起来的不清楚。测试怎么写AI说“不用写我给你补”它真的补了但我从来没跑过那些测试。站在当时的视角氛围编码的吸引力是真实存在的。它把“从零到能跑的Demo”的时间压缩到了极致对于验证创意、做内部原型、临时数据清洗这些场景效率提升明显。我刚接触时也真心觉得这可能是未来写代码的方式——毕竟能力再强的工程师一天手写也就几百行高质量代码而AI在几分钟内就能产出上千行。1.2 它的核心缺陷你在“生产代码”但你没在“理解代码”但要命的是氛围编码有一个根本性的错位它让开发者处于一种“生产者的位置”而非“作者的位置”。你可以指挥AI按照你的意向产出一堆代码但你完全没有——或者说放弃了——对每一行代码为何存在的理解。刚开始你可能觉得无所谓能跑就行嘛。但这种“能跑就行”的心态会在代码量膨胀之后变成一场灾难。我大概在用到第8个月的时候开始感觉到不对劲某次改一个很小的配置项我让AI帮忙找是哪里读的它找了三遍没找到最后我自己去全项目搜关键词才在一个我不记得怎么生成的工具类里发现了硬编码的配置。那一刻我突然意识到这个项目的认知负担已经超出了我的掌控——问题不是AI写得不好而是我的头脑里没有这张代码地图。用个生活化的类比氛围编码就像是叫了一位极其高效的外包团队来帮你装修房子。他们很擅长按照你口头描述的样子把墙刷好、柜子装好但你从未看过图纸也从没自己摸过管线。有一天水管堵了你连总阀在哪里、墙里管线怎么走的都不知道。嵌入式的水管尚且可以砸墙但代码里的“管线”要是砸错地方那就不是漏水是整栋楼塌掉。1.3 氛围编码真正适合的边界在哪我并不想一棒子打死氛围编码。经过这两年踩坑我总结出它的适用边界大概是这样几条一次性脚本或原型验证用完即弃没有后续维护需求跑完拿到数据或结论就删。文档注释、重复模板代码的批量生成比如给几十个DTO写注解人工写没价值AI出活快。测试数据的构造、临时mock服务、压测脚本生成产出物本身不重要重要的是快速拿到可用环境。帮你回忆语法或处理繁琐的配置细节比如某个框架的完整配置示例、某段不常用的API用法。技术探索期的辅助当作“高级搜索引擎”用快速生成一段能跑的代码来观察行为。反过来核心业务逻辑、涉及状态管理的模块、需要长期演进和多人协作的系统这些坚决不能完全交给氛围编码。我说“完全”而不是“不能”——是因为AI可以介入某些局部但你必须亲自做架构决策、理清模块边界、至少通读并理解每一条核心链路。否则你只是在写一份“发布说明”而不是在写代码。2. 烂摊子全景拆解氛围编码2年后代码库的真实面目2.1 “屎山”最典型的四大症状如果你也长期依赖AI生成代码你的项目很可能已经出现了下面这些症状。我用自己手头那个被逼重写的系统为例列出最常见的四类问题第一隐式依赖无处不在。我原来核心模块里有一个配置文件氛围编码时代AI为了让“某个功能快速跑通”直接在几个工具类里硬编码了文件路径和参数。当时我因为不懂细节没意识到这个硬编码的存在。结果后来要迁移环境这个路径藏在三个不同的类里一个没改到线上就是一连串的路径报错。这不是AI的锅是我没把“全局扫描一遍配置引用”当成必做项。第二重复代码堆积成山。AI在生成代码时有个特点——它永远不会主动“复用已有的东西”因为为了确保当前生成的片段能独立运行它倾向于把依赖的辅助函数、常量、工具逻辑完整复制一份嵌进去。我后来统计那个项目的重复代码率接近35%。这意味着整个代码库里躺着大量看似不同、实则一致的逻辑实现。改动一处其余还有七八处在“假装正常”地跑着旧逻辑。第三混沌的模块边界。氛围编码时代我从来没有认真定义过模块之间的接口。需求来了就说“让我在现有代码上再加一个类”AI生成的新类如果跟旧类有重名它有时会“聪明地”再生成一个新的文件然后靠类型推断或者动态调用硬接进去。时间一长整个项目变成了一张巨型互相调用的“蛛网”。我从没画过它的架构图因为完全画不出来。第四测试形同虚设。这里要说的不是没测试。恰恰相反AI很“配合”你说要测试它就给你生成测试但全是那种“为了通过而通过”的用例写死输入和期望输出覆盖率看着还行实际对业务逻辑的保护价值很低。真正碰到边界条件、异常路径、数据不一致的情况测试根本帮不上任何忙。更糟的是如果运行环境稍有不同这些测试甚至跑不过——它们更像是“为了证明代码存在”而不是“为了证明代码正确”。2.2 一个具体的翻车案例我差点把生产数据全抹了说个具体的例子。某天产品提了个需求要求给用户列表增加一个筛选功能按注册来源筛选。听起来很简单对不对氛围编码模式下我把需求贴在对话框里AI很快生成了一段改动。我没有细看只简单测了“筛选之后列表正常显示”就合进主分支准备发布。结果上线之后运营那边在后台用筛选功能时突然发现数据少了——不是显示问题是数据库里的记录被删掉了一批。我当时吓得手心冒汗赶紧回滚并查日志发现AI在生成筛选逻辑时“顺手”在某个公共数据访问方法里加了一个条件如果来源参数为空就执行delete操作。它为什么这么加我不知道可能是在某次“修复”时被AI自动脑补出来的逻辑。它自以为聪明地“清理无效数据”但那个方法的调用方不止有筛选功能还有其他业务模块。这件事给了我巨大的冲击。问题的根子不在AI写错了而在于我不了解这个模块的完整逻辑——我不知道那个公共方法被哪些地方调用也不知道AI在实现新需求时偷偷动了旧的逻辑。如果当时我对代码有足够认识看到AI生成的结果时我会立刻发现那个莫名的delete语句并意识到它施加了不可接受的副作用。可事实恰恰相反我根本没有形成“审查”的习惯。这种“AI帮你删了一行你全然不知”的时刻比任何技术债描述都更让人后怕。2.3 氛围编码债务的累积曲线如果你还处在“大力出奇迹”的阶段我建议你用下面这条曲线来评估自己项目面临的债务风险第1到6个月代码量爆发期需求交付速度飞快心态极度膨胀感觉“再也不用手写了”。第6到12个月开始出现“某个模块不敢动”的现象因为一改就有人际联动的报错需要频繁问AI“之前那段代码是干嘛的”。第12到18个月新需求交付速度明显下降因为AI生成代码的时间不长但“把新代码嵌进旧系统再调通”的时间越来越长。改动一处测试一片回归一遍心累到极点。第18个月以后你发现自己完全不想碰这个项目的核心区域要么改需求就推倒重来要么对外宣称“这块已经冻结了”实际上是你自己也不知道它还有多少秘密。我就是走到了第20个月才被现实强按着头承认继续用氛围编码缝补这个项目只会把烂摊子越铺越大唯一的选择就是把核心抽出来亲手重写。3. 重新手写代码不是返工这是一次代价更低的止损3.1 什么情况下该动手重写什么情况下还能救说到“重写”很多人的第一反应是“成本太高了吧公司不会批的”。我自己也曾经被这个念头吓退过但实际经历过之后我觉得真正的判断标准不是“成本高不高”而是“继续修补的成本是否已经超过了重写”。对于氛围编码攒下的项目来说有两条硬指标可以参考指标一你修改任何一个基础模块平均需要研读超过三个以上无关文件才能定位改动范围。指标二你无法在一小时之内画出当前核心链路的调用关系图起码要找出“请求从入口到落库”中间经过的每一个方法。只要这两条里有任何一条不满足就说明代码库的认知负载已经失控重写的必要性就成立了。但如果项目本身很小、依赖方很少、马上要废弃那就不要重写了直接让它“体面退休”即可。从我个人的经验看重写不是“把代码用AI再生成一遍”而是你开始亲手创建项目骨架、亲自动手定义每个模块的边界和接口、亲手写出第一条核心链路。它不是在抄作业而是逼着自己把之前缺失的功课全部补上。这个过程要把“AI能帮你搞定一切”的心态扔掉用“我要真正掌握这个系统”的心态去重新组织代码。它当然比让AI生成慢但慢的是过程快的是之后的维护响应速度这两笔账不能只算眼前。3.2 重新手写前的准备摸清现存系统的真实行为在动手重写之前我花了两周时间做一件看起来“很没用”的事逆向梳理旧系统的行为。先让AI帮我从系统日志、数据库操作记录和线上监控里把核心请求的时序拉出来然后我手动画出调用关系图和状态流转图。这一步的本质是把旧系统当作黑盒去“考古”而非靠读代码去理解——因为代码本身可能就是错的但线上行为是真实发生过且被验证过的。我用表格整理了每个核心接口的行为特征包括输入参数、依赖数据、副作用、异常分支和性能特点。这个过程非常痛苦但也让那些以前藏在AI生成代码里的隐藏逻辑浮出水面——比如之前那个delete操作它到底在什么条件下被触发哪个调用方会受影响。然后我开始为关键路径写“行为规格说明”说白了就是不管这条代码是怎么实现的先写下它应该做什么。这份规格说明在后续手写代码时就是我们的“施工图纸”。避免重写过程中“边写边改约定”造成新的混乱。强烈建议你也这样做——它帮你把“AI生成代码”时代的黑盒行为清晰转化为可以指导人工开发的契约。3.3 动手重写的优先级先把最痛的那块骨头啃下来重写的顺序也是有讲究的。我见过有人一上来就想把整个项目全部推翻结果写了三个月连一个可运行版本都没出来心态直接崩掉。我的建议是“窄口切入”——先选一个影响面最核心、让你最痛苦的模块来重写。我的选择是数据访问层和状态管理模块。这两个模块是所有业务逻辑的底层前提也是之前AI代码里隐式依赖和重复逻辑最密集的地方。先在这个层面亲手写出干净的模型和基于明确接口的数据访问方式再往上重建业务逻辑时就会轻松很多。重写第一版时不要追求功能100%覆盖旧系统。你要优先保证“核心主链路跑通”比如一个用户从注册、登录、提交主业务到数据落库、读取展示的完整闭环。把这条链路用自己手写的代码跑通了就相当于给新系统打下了“定海神针”。剩下的边角功能再一个个从老系统里“搬”过来——每搬一个都要对照之前整理的行为规格说明确保没有遗漏或偏离。3.4 如何划定重写范围避免“范围爆炸”重写最容易失控的点是你还想把旧系统的每一个“怪癖”都保留下来。比如某个接口需要返回一个很别扭的结构仅仅是因为前端早期那样消费了或者某段业务逻辑有个if分支但你根本不知道那个分支是否还有人走。我以前的心态是“既然旧系统这样我就照搬吧”。但这次不一样——我会把每个要保留的怪癖都当成一个“需求决策”来审视。凡是我搞不清楚用途的分支、参数、特判直接列表标注“待删除试验”等新的核心链路稳定运行一段时间后在确保没有业务依赖的情况下坚决移除。重写期间的团队协同和个人精力管理也很重要。毕竟你已经花了两年代价才走到这一步不能因为这个过程太累而中途放弃。我当时给自己定的规则是每天先花至少45分钟纯粹手写核心代码不打开AI自动生成窗口只有在写测试、生成迁移脚本或查某个框架语法时才允许“请AI帮忙”。这个节奏保持了大约两个月之后新系统已经具备平稳替换旧模块的能力。4. 技术栈与工程化选择换掉哪些“氛围编码”留下的隐患4.1 工具链咋调整AI辅助写作代码的正确打开方式重新手写代码不代表你要彻底告别AI。我的态度是可以走AI辅助但角色彻底调转了——人类做架构师AI做打字员。具体来说我会用AI完成四类固定工作帮我快速生成DTO、常量类、配置项的初始模板。帮我写重复性很高的单元测试用例的外壳比如测试数据的builder。帮我翻译旧系统的SQL逻辑到新系统数据访问层的方法注释。帮我做代码风格的统一和基础重构的批量修改。但是核心业务逻辑、状态机转换、锁与并发控制、事务边界这些“系统灵魂”部分我一定自己写而且写完一行一行再看一遍。请记住一句话AI生成代码最好用的时刻是你已经明确知道要什么的时候而不是你希望它帮你探索要什么的时候。4.2 架构设计的取舍避开隐式依赖拥抱显式契约重写过程中我给新系统立了几条纪律每一条都是对着旧系统痛点量身定的第一所有模块之间的交互必须通过明确的接口定义。不管是内部方法还是跨服务调用先定义好输入输出和异常语义再写实现。严禁模块之间偷偷访问对方的内部工具类。第二配置必须集中化管理。旧系统那种“硬编码散落多个工具类”的灾难绝不允许再次发生。所有环境相关的参数统一进入配置中心或至少一个显式配置类并通过代码扫描工具保证没有漏网之鱼。第三禁止“复用型复制”。如果某个逻辑需要被多个模块使用那它必须是独立模块并引入依赖如果因为解耦问题暂时无法下沉那就把重复代码的“提取重组”作为技术债显式记录下来排进迭代计划而不是假装看不到。第四写代码时同步画图。哪怕是简单的模块依赖草图其实就是在逼自己把系统的结构在脑子里显式化。氛围编码时代系统在自己脑子里就是一堆“生成物”的集合手写时代你要让系统结构变成可讲述、可画出来的图景。4.3 数据迁移和兼容策略不让重写成为第二场灾难重写系统时数据格式、存储位置甚至表结构都可能调整。这里的核心风险是如果新系统和旧系统的读写不能平滑切换重写就变成了“数据割裂”。我当时是这么处理数据迁移的新系统上线前先做一次“影子运行”把新系统部署在与旧系统并行的环境里开启灰度开关流量先打到旧系统但新系统同步读取真实数据持续对比两者输出结果。等到行为对比连续两周没有差异再把读写切到新系统旧系统保留只读模式方便随时回退。切换完成后继续观察至少一个完整业务周期比如月底对账、批量任务执行确认无数据异常后再把旧系统彻底下掉。这套流程的核心就是“诚实的灰度”。氛围编码时代我往往跳过这个环节直接全量上线AI生成的代码等线上出问题再紧急修复实际上是在用生产环境当测试环境。重写之后我宁愿慢一点也要让每一步切换都有据可依。4.4 重写期间的度量怎么知道自己真的在变好重写总会伴随焦虑花了一两个月功能还少一大截到底值不值得我自己的经验是盯着几项关键指标看而不是用“功能数量”这种氛围编码时代特别容易膨胀的指标。用一张表来记录项目健康度指标旧系统状态重写后目标单模块平均依赖的外部类型数量大量交叉引用超过20每个模块控制在10以内核心链路平均方法调用深度深且不透明常有隐藏调用尽量浅显调用关系一目了然重复代码率约35%目标低于8%单元测试对核心业务的覆盖有效性形同虚设关键路径和异常分支全部覆盖从改一行配置到完成全链路回归需要半天甚至更长一小时内完成度量不是为了写汇报而是为了让自己随时知道手写代码是否在朝着“可维护、可掌控”的方向前进。如果某项指标在重写过程中迟迟没有改善就要警惕是不是犯下新的架构错误——提前修正比全部写完再回头排雷要省力得多。5. 手写代码之后我到底拿回了什么5.1 认知状态的变化从“代码观游”到“代码掌舵”如果你问重新手写核心代码之后最大的感觉是什么我会说是认知状态的改变。以前看到AI生成的项目代码内心飘着的是一种“不可知”的迷惘哪怕它什么bug都没有我心里也是悬的因为我不知道它为什么会这样。但手写核心代码的过程本质上是让我重新完成了一次“作者责任”的确认。我记得新系统核心链路第一次完整跑通时我看着日志里的每一步流转那种感觉跟以前“AI写代码跑通了”完全不同。它不是一种“几乎”我知道这条链路一共经过几个模块、每个模块各自处理了什么、哪里可能出问题、在什么条件下会出问题。我可以拍着胸脯跟团队讲清楚这个系统在干什么而不是含糊其辞地说“它应该可以”。这份踏实感是氛围编码再快也给不了的。5.2 对团队协作的影响代码变成了一门可沟通的语言另一个显著的变化发生在协作层面。氛围编码时代我很难跟同事讨论代码——因为大部分代码都不是我“想”出来的我也没有足够理由解释它为何长这样。同事接替我review时也极其痛苦因为他们面对的是“遗物考古”。手写重写之后代码的每一处设计决策都有据可循。模块之间靠接口沟通核心逻辑有注释说明自己为何这么做复杂分支有测试锁住行为预期。团队里的新同学接手时不再需要靠AI“翻译”这坨代码而是可以直接读、可以改、可以提出更优方案。这才是工程协作该有的样子。5.3 现在还整天用氛围编码吗我的答案是用但完全变了用法。我依然会让AI帮我写日志聚合脚本、生成压测数据、补全注释和简单的测试骨架也会用AI快速排查某个第三方库的报错原因甚至会让它帮忙把一段冗长的旧代码重构得更紧凑但我亲自通读改动结果确认它没有改变任何行为。对应到日常开发流程里我会设定“AI辅助红线清单”涉及事务控制、锁、权限、数据迁移、外部接口契约的代码一律不交给AI生成涉及性能和安全性的实现细节必须人工评审后再合入。氛围编码不再是默认选项而是众多“效率工具”之一——它服务于一个我完全理解的系统而我不再服务于它生成的未知代码。6. 避坑心得与执行清单给也想戒掉氛围编码的你6.1 五个“绝对别做”与五个“一定去做”如果你看完前面的分析也决定要给自己的代码库来一次“清创”下面这份执行清单是我踩了无数坑之后浓缩出来的绝对别做绝对不要在重写之前迷信“照抄旧系统逻辑就行”——旧系统逻辑本身就是屎山的一部分盲抄等于把债务换个壳带进新系统。绝对不要一次性“大爆炸式”重写——那会让你在几周内没有可交付物心态先崩项目也可能被叫停。绝对不要忽视数据迁移的灰度验证——新旧切换不经过影子运行和对比就是在拿生产环境赌博。绝对不要只重写代码不重写文档和架构图——手写过程中画下的图就是未来几天、几月、几年里你和其他维护者的指路明灯。绝对不要让AI直接生成你的核心业务逻辑——哪怕你靠它查语法、生成模板最后一行一行审查并修改的是你作者责任在你这头。一定去做一定先做旧系统行为梳理写一份“旧行为规格说明书”无视代码、只管行为。一定先用一根完整主链路跑通新系统哪怕是手写得很土也要让它作为一个闭环存在。一定给每个模块定义干净的接口和异常协议不允许跨模块引内部类。一定在重写期间定期做代码评审让第二双眼睛帮你发现“氛围编码后遗症”可能复发的地方。一定给自己设置“无AI手写时段”哪怕每天只有45分钟坚持下来那份代码会让你骄傲地摸到它的每一寸。6.2 关于心态的几句大实话最后想说点心态层面的东西。重新手写代码不是“退步”或者“否认AI的价值”而是一种主动的权利回归。你用两年时间体验到AI生成代码的高效也踩遍它带来的雷这些经历都是财富——它们让你真正懂得哪些环节可以放手给工具哪些责任必须留在自己手里。这跟开车很像自动驾驶辅助很好用但如果你在自动驾驶路段开了两年却再也不会自己判断车距、自己打方向盘那这辆车早晚会把你带到沟里。手写核心代码就是在重新训练你的路感和方向盘手感。也不要因为“重写太慢”而焦虑。氛围编码把代码量堆起来的速度快垃圾也堆得飞快手写代码的速度看起来慢但写的是承重墙和地基。我现在的体会是项目里的核心代码就该是“手写”的。AI可以当脚手架、当助手、当生成器但它不该替代你的判断。毕竟一个你能完全看懂的、能勇敢改动的、能在凌晨三点出故障时快速定位的系统——那种安心感是任何一个高速生成的代码库都给不了你的。如果你也正对着一个氛围编码攒下的烂摊子发愁别犹豫了从梳理旧行为开始亲手重写第一步。相信我这个决定虽然痛苦却是我这两年做过最值得的一件事。
阅读完成 · 觉得有帮助?