Vibe Coding快满一年了,踩过无数坑,也从坑里爬出过无数回,本着经济高效的理念,我现在使用的IDE收缩至俩,分别是Antigravity和VS Code,VS Code里接入DeepSeek和Codex,基本满足了我当下的需求。
但蜜月期很快就结束了。
当项目脱离了 “Hello World” 阶段,进入核心逻辑的快速迭代期时,我发现了一个极其致命的问题:AI 总是过度表现出一种“企业级”的求生欲。它对于“向后兼容”有着近乎偏执的狂热。
明明是一个还在开发阶段(Phase 0 到 1)、连内测用户都没有的项目,我仅仅是想在数据库表里删掉一个不再需要的字段,CodeX 竟然给我洋洋洒洒写了一个长达百行的 Migration(数据迁移)脚本,甚至还在 API 层加了一个 Fallback(降级)兼容层!
这简直是在给还在襁褓中的项目直接注入“十年历史遗留问题”的屎山基因。
如果你也在用 AI 辅助构建新项目,并且不想在项目上线前就被毫无意义的复杂度压垮,请务必在你的 System Prompt 或 Cursor Rules 里,死死钉住以下 8 条架构决策铁律。
1. 绝不保留向后兼容:过时的代码只有死路一条
场景痛点: 假设你在写一个基于 Rust 的后端服务,中途发现早期设计的 DeviceConfig 结构体完全错了。你让 AI 去修改结构。AI 的第一反应往往是保留旧的 DeviceConfigV1,创建一个 DeviceConfigV2,然后写一堆 From trait 来做互相转换。
我的规矩: 在项目未正式发布(或无外部依赖)前,过时的直接删,别加兼容层、别写 Migration、别留 Fallback。 我们不需要像维护一个有上万并发的在线支付系统那样去维护一个开发环境的数据库。如果表结构变了,直接 DROP TABLE 重新建;如果 API 路由变了,直接改名字。
把时间浪费在为不存在的旧版本用户写兼容代码,是对开发生命力的极大消耗。
给 AI 的 Prompt 约束: “本项目正处于 MVP 开发阶段,没有历史包袱。遇到废弃的字段、路由或数据结构,请直接进行破坏性删除(Destructive Deletion),严禁编写任何形式的兼容层、Migration 脚本或 Fallback 逻辑。”
2. 拒绝预防性抽象:只要能跑的最简实现
场景痛点: 你想加一个从本地读取 JSON 配置文件的功能。如果任由 AI 发挥,它能给你整出一个 ConfigProvider 接口,然后实现一个 LocalJsonConfigProvider,最后再来一个依赖注入工厂。
我的规矩: 选能满足当前需求的最简单实现。不要预防性抽象,不要多此一举的配置层。 AI 极其喜欢炫技,它阅读了 GitHub 上成千上万的企业级开源项目,导致它认为“高内聚低耦合 = 疯狂加接口”。但在项目的探索期,过早的抽象是万恶之源。如果只需要读取一个文件,直接用标准的 fs::read_to_string 一把梭。等真的有一天你需要从 AWS S3 读取配置时,再去重构提取接口也不迟。
代码越少,Bug 越少,AI 再次阅读上下文时消耗的 Token 也越少。
3. 端到端优先:系统是切出来的,不是叠出来的
场景痛点: 很多新手带着 AI 写代码,喜欢“分层堆叠”:先让 AI 把所有数据库表建好,然后写所有的 ORM 模型,接着写所有的 Service 逻辑,最后再碰前端。结果往往是底层写了 80% 的无用代码,一旦前端需求变了,整个底层都要推倒重来。
我的规矩: 先跑通一个最小的端到端版本(Vertical Slice),再往上加东西。绝不为了未完成的复杂度,拆掉能跑的东西。 比如做那个网络自动化巡检系统,第一天我就只要求 AI 做一件事:前端点一个按钮 -> 后端接收请求 -> 通过 SSH 连上一台测试机拉取 uptime -> 回传前端显示。 就这一个极简的端到端切片。中间不搞复杂的任务队列,不搞状态机。
一旦这条线跑通,系统就“活”了。之后你可以往这根线上挂载“定时任务”、“并发控制”、“复杂解析”,但始终要保证系统处于“可运行”状态。
4. 强制模块化与关注点分离 (Separation of Concerns)
场景痛点: AI 在生成长代码时,极其容易把业务逻辑、UI 渲染、甚至环境配置揉在同一个文件里。如果你在开发 WASM 前端,它可能会把组件的样式计算和网络请求死死绑定在一起。
我的规矩: 虽然我们抵制“预防性抽象”,但这不代表我们可以写“面条代码”。组件必须保持模块化,关注点绝对分离。 把数据获取(Fetch)、状态管理(Store/State)和视图渲染(View)分开。当你告诉 CodeX “帮我修改卡片右上角的编辑图标样式”时,它只应该去改 View 层的代码,而不是重新生成一遍包含数据获取逻辑的整个大组件。
5. 敬畏开源:优先用成熟的、有人维护的库
场景痛点: 遇到一个稍微复杂的日期时间格式化,或者特定的字符串正则提取,AI 很多时候会“为了展现聪明才智”当场给你手写一个几百行的解析器。
我的规矩: 没有明确理由,别自己重写。 遇到常见需求,第一时间去搜轮子。处理时间?去用成熟的包;做反向代理?直接挂 Nginx,别让 AI 在代码里手撸一个 HTTP 代理分发;做进程监控?系统级服务直接上 Systemd,容器级挂 Docker 重启策略,甚至直接用 fail2ban 搞定安全拦截,别在业务代码里写一堆轮询脚本。
相信世界上最聪明的那拨开源维护者,不要相信 AI 临时在一秒钟内生成的正则。
6. 榨干现有依赖:别动不动就引入新包
场景痛点: AI 经常有“依赖饥渴症”。项目里明明已经有了 reqwest,它非要为了发一个简单的 HTTP 请求再让你装一个轻量级的包;明明 tokio 已经提供了定时器,它非要让你引入一个专门的 Cron 包。
我的规矩: 先翻项目里已有的依赖能做什么,再考虑加新包或自己写。别上来就假设库里没有。 每次引入一个新的包,不仅增加了编译时间(比如在做 Rust 到 WASM 的编译时,LTO 优化的时间极其宝贵),还会增加安全漏洞的攻击面。在给 AI 发出指令前,我通常会附上一句:“检查 Cargo.toml / package.json,仅使用现有依赖完成此功能。”
7. 架构决策往长了做:拒绝“临时凑合”
场景痛点: “老板催得紧,这里的数据我们先写死在一个 JSON 文件里吧,以后有空再上数据库。” AI 也很乐意配合你这种短视行为,甚至会为你写一套非常精密的 JSON 文件读写互斥锁。
我的规矩: 不接受”先这样以后再换”的临时方案。 经验告诉我们,IT 运维系统里的“临时方案”,往往最后都会变成运行了 5 年的“核心基础设施”。如果你知道这个功能最终需要落库查询(比如需要复杂的关系联表、资产树状层级),哪怕现在只有 10 条测试数据,也必须立刻上 SQLite 甚至 PostgreSQL,并搭建好基础的连接池。
如果一开始的架构方向妥协了,后期迁移数据的痛苦,会让你想要把当初敲下这段代码的键盘砸碎。
8. 别从零发明:抄成熟产品的作业
场景痛点: 你需要设计一套 IP 地址管理系统(IPAM)或者设备机柜视图。AI 顺着你的思路,天马行空地设计了一套前所未有的、极其复杂的坐标系数据结构。
我的规矩: 先看成熟产品怎么解决同一个问题,用已验证的模式。 在这个行业,几乎没有什么是没被人做过的。如果你在做网络自动化系统,不要让 AI 瞎编数据结构,直接告诉它:“去参考 NetBox 的核心数据架构,模仿它对 Site, Rack, Device 的层级抽象定义。” 如果你在做 ITSS 运维管理系统,就直接参考 iTop 的 CMDB 理念。
站在巨人的肩膀上,然后让 AI 帮你把巨人的思想转化为代码,这才是驾驭 AI 的正确姿势。
以上要点,汇总到你的AGENTS.md就是:
注意!
- 以下提示词仅适用于开发阶段的项目,切勿用于生产环境!
- 如果你仍在迭代的项目需要频繁的进行数据库开发,第一条中的“别写migration”可以删除。
1、不保留向后兼容。过时的直接删,别加兼容层、别写migration、别留fallback。
2、选能满足当前需求的最简单实现。不要预防性抽象,不要多此一举的配置层。
3、系统分层长。先跑通一个最小的端到端版本,再往上加东西。绝不为了未完成的复杂度拆掉能跑的东西。
4、组件保持模块化,关注点分离。
5、优先用成熟的、有人维护的库。没有明确理由别自己重写。
6、先翻项目里已有的依赖能做什么,再考虑加新包或自己写。别上来就假设库里没有。
7、架构决策往长了做。不接受"先这样以后再换"的临时方案。
8、先看成熟产品怎么解决同一个问题,用已验证的模式,别从零发明。总结
AI 是一个阅读过万卷代码,但没有任何真实项目挨骂经验的“超级初级程序员”。它极其勤奋,懂得所有的设计模式,但完全不懂业务的妥协与演进节奏。
在 AI 编码时代,程序员的核心竞争力不再是写出无 Bug 的循环语句,而是“品味”与“决断力”。我们必须像一个严厉的 Tech Lead,拿着戒尺,随时敲打试图制造屎山的 AI,逼迫它写出克制、精准、能打硬仗的代码。
你对 AI 编码工具的态度是怎样的?欢迎在评论区分享你被 AI “坑”过的实战经历。
如果觉得文章对您有帮助,欢迎打赏支持作者:




发表回复