
1. 为什么不是给人类写代码规范而是给AI写先讲个真实场景。团队人不多业务排期很紧大家默认把一部分重复性、模板化、甚至一些带业务状态的页面逻辑交给AI来写。刚开始挺爽一个星期后问题来了代码确实能跑但每个人的机器上跑的是”看起来差不多但风格完全分裂”的版本。有人变量命名用data有人用resData组件的props七零八落接口错误处理有一半是throw new Error另一半是console.error完事。代码评审变成了语文猜谜改起老代码来更是整个人都不太好。于是我们决定在项目里新增一份给AI制定的代码规范。注意不是给人类看的那份规范是专门给AI读的规范。这个区别非常关键。人类的代码规范讲究原则、推荐、反例比如“命名要清晰”“尽量不写重复代码”“注意性能”这类表述。人看到能发挥主观能动性理解了就照做。但AI不一样它的本质是分词、上下文联想生成代码时依赖的是规则文件里的字面约定和边界条件。“尽量”“通常”“合理”这种词对它来说几乎没有约束力它每次都在概率上猜测一个看起来最正常的选择。所以给它写规范本质上是把人类的审美和工程要求翻译成一套它“能够消化”的显式约束。这份规范不需要多宏大也不需要覆盖所有编程领域但一定要做到三件事可判定。每条规则都要能说清楚什么情况算违反。可执行。规则要能配合静态检查、lint 工具或代码评审来验证而不是停留在文档里。可引用。AI工具在生成代码时必须能找到并引用这份规范围绕上下文否则规范就是摆设。这篇文章就把我们实际沉淀下来的AI代码规范拆给你看包括规范的结构设计、每个核心章节的写法、怎么把规范喂给Cursor/ Copilot 这类工具以及后续怎么验证AI到底有没有遵守规则。文章里的代码示例大多以我们最常用的 TypeScript / Vue 前端项目为背景但方法完全适用于后端、Flutter、小程序等各种技术栈。2. 先拆清楚AI读代码规范和人类读的差异在哪2.1 精确阈值替代模糊建议给AI定规范之前你得知道自己面对的是什么样的“读者”。人类资深工程师看到“函数体不要过长”会自然产生分寸感知道50行一般没事、200行面试肯定是大问题。AI没有这种分寸感。我做过一次实验同一段业务代码我们在规范里写“函数应保持简短、便于阅读”AI生成的结果是随机抽签有些函数30多行有些直接一个组件塞进300多行业务逻辑。后来把规范改成“单函数逻辑行数不超过80行超过时必须拆分子函数并在原处写明拆分原因”生成质量立刻稳定下来。所以第一条原则是能给数值就给数值能给黑白判定就别写灰色表述。举个例子规范原文不要使用装饰器模式来包装重复逻辑优先抽成公共工具函数。AI大概率不会在意这句话它甚至可能以为你在给它讲装饰器的概念。更好的写法是项目中禁止使用 class 作为装饰器容器重复逻辑必须抽离到 src/utils 目录下的纯函数中函数名以 use 或 handle 开头。再配合工程上的 eslint rule 或目录结构约定AI生成的东西就能自动贴着你的模块边界走。2.2 语境感知提出了更高要求人类看规范会结合场景判断AI则极度依赖你提供的上下文。比如你说“不要重复代码”人类看一个弹窗组件知道整块的样式配置可以抽成常量AI如果看不到全量代码它根本不知道哪些叫重复只能根据最高频的写法生成一个自认为合理的副本。所以给AI的规范必须带“执行路径”不能只提目标。最有效的半结构就是把约束和文件、模块、命名空间直接绑定。告诉它某个目录下的文件必须怎么做而不是笼统地说“所有代码都要这样做”。详细一点推荐在规范文件里给每个目录单独建一个小节src/components/ 下 - 每个组件必须有 props 类型定义禁止使用 any - 组件名必须使用 PascalCase - 样式必须走 scoped禁止全局生效 - 组件内部超过100行时必须拆分子组件这种写作方式AI在读取仓库结构时就能把规则自动匹配到对应文件上比单一一堆全局规范好用得多。2.3 规则优先级得排清楚给AI写规范还有一个容易被忽略的点规则之间会有冲突。比如“不要写长函数”和“尽量不引入新依赖”如果AI遇到一个既要长函数又要引入新依赖才能拆开的逻辑它该选哪个人类会判断AI只会卡住或者随机选一个然后生成出稀奇古怪的代码。所以每一条规范都应该有一个明确的优先级标记。我们项目的做法是给规则分三个等级等级含义示例P0硬性约束违反视为代码评审不通过禁止引入非 package.json 声明的第三方包禁止 any 类型P1强烈建议违反需在注释里说明理由函数长度超过80行必须拆分并注明原因P2偏好与风格组件名语义化按钮统一用UButton而不直接用button把 P0 放在规范文件的头部并加粗P1 放在中部P2 作为附则。AI在读取时对优先级高的内容会保持更强的注意力生成结果也更稳定。优先级设计不仅是给人看的层次结构也是给AI做决策冲突裁决的依据。3. 给AI的代码规范应该包含哪些核心内容3.1 命令与文件结构约束AI读规范时最基础也最重要的是“项目骨架认知”。它必须知道代码落在哪里、入口在哪、公共模块在哪、测试写在哪。很多团队用AI翻车恰恰是AI把文件路径猜错了生成了各种utils/helper.ts、lib/xxx.ts、甚至直接丢在App.vue旁边。我建议规范里明确写清楚整个目录树和每个目录的职责项目目录结构如下 src/api/ —— 所有接口请求定义禁止混入业务逻辑 src/components/ —— 公共组件组件内禁止写业务请求 src/stores/ —— 状态管理禁止直接调用接口 src/utils/ —— 纯函数工具禁止引入副作用模块 src/views/ —— 页面组件只做页面编排复杂逻辑委托给 composables给AI的目录规则开头可以标明“本目录结构是唯一合法的代码布局遇到不确定文件放哪时优先问用户而不是自己新建目录。”这个小小的前缀我发现特别有用AI不会自动提问但它在约束不明确时会倾向于遵循描述更细的位置。如果不写它自己新建一个src/common/目录的可能性非常高。3.2 命名和命名规范里的隐藏约束命名规范人类也有但给AI的命名规范必须细到前缀、后缀、动词甚至可以给出一份“命名黑名单”。因为它真的会把变量叫temp、data、result而且非常频繁改起来还特别难全局替换。我们的规范文件里专门有一节变量命名 - 禁止使用 data, res, temp, obj, arr 这类无意义名称 - 列表变量必须使用复数名词如 userList, itemOptions - 布尔变量必须使用 is/has/can 前缀如 isVisible, hasPermission - 方法命名必须以动词开头如 get, set, create, update, remove - API 文件命名与后端接口名保持一致如 getUserInfo.ts这套规则AI基本上能消化但要注意一点命名规则最好配合代码评审强制执行一个迭代周期。前一个礼拜AI生成的代码依然有大量res原因是很多开源项目、教程代码都是这么命名的它的权重很高。所以我们加了惩罚性语句“在现有代码中发现命名违规时先找AI出现过的同名同义变量做全文件重命名再继续开发别的功能。”创造了AI对命名规则的“强记忆”下一轮生成的代码明显就守规矩了。3.3 代码结构、拆分与分层拆分逻辑对AI来说非常抽象。你让它“拆细一点”它反而会更碎你让它“不要拆太碎”它可能把一个500行的组件原封不动拿给你。最好把组件拆分的标准写成可以直接量化的判据。以下是我们规范里的一个标准片段组件拆分判据满足任意一条就必须拆分子组件 1. 组件 render 模板部分超过120行 2. 单个组件包含两个及以上表格或表单 3. 组件内部状态超过10个 4. 存在对同一个第三方组件库的 8 次以上引用这里我特别想强调第4条。当AI大量写某种表格、弹窗或表单时很容易把重复的el-formel-form-item写上一百多遍。只要拆分子组件代码的可读性立刻提升一个档次。组件拆分的规则也必须和目录树配合否则AI拆出来一个components/TableWrapper.vue没有进一步约束它过两天它又会在utils/里新建一个.tsx文件目录结构就乱了。规范要明确写着“所有子组件必须放在当前页面目录下的components/子目录中”。3.4 类型、错误处理与边界行为的显式约定AI在类型处理上有一个很典型的问题为了省事、快速通过编译大量使用any和类型断言。这类代码编译没毛病重构时全是坑。规范里我们列了硬规则- 禁止使用 any通过 unknown 代替并在使用前做类型守卫 - 禁止使用 ts-ignore如确实需要必须提供 issue 链接 - 接口返回数据必须经过运行时校验推荐使用 zod 或 valibot 定义 schema - 所有 catch 分支不得为空至少记录 error message这段规范用下来效果最好的一点是AI不仅不再写any还会主动在关键函数入口写zodschema 校验。因为规范里已经写了“必须经过运行时校验”AI会据此联想出最合理的实现方案。错误处理方面AI最容易写的离谱代码是把错误直接吞掉比如catch (e) {}或者catch (e) { console.log(e) }。规范里改成错误处理规则 - 所有异步请求必须包含 try/catch/finallycatch 中至少必须调用 message.error 提示用户 - 不允许在 catch 中只写 console.error - 非恢复性错误必须重新抛出或向上层返回失败状态这些规则AI读完很容易落地因为它的“充当参考案例”里到处是这种经典写法。关键是你要把它列成强制项否则AI默认选择最省字符的写法。3.5 禁止事项与反面清单除了正面告诉AI该怎么做反面清单更重要。我强烈建议每个给AI的规范里都有“禁止事项”章节而且放在醒目位置。经验之谈反面清单比满篇正面描述好用得多因为AI更容易记忆和遵守“不能做”的规则像黑名单一样。我们项目的禁止事项节选禁止事项 - 禁止在 src/api 之外直接调用 axios 或其他 HTTP 库 - 禁止在组件内直接修改 stores 中的状态必须通过 actions 修改 - 禁止在代码中硬编码后端接口地址必须读取 .env 中的环境变量 - 禁止复制现有代码块来扩展样式必须抽象为公共 class 或组件 - 禁止使用内联样式完成布局必须使用 tailwind 或 scoped style - 禁止在 package.json 中新增依赖除非在规范文件的第 X 节登记并说明理由有一条特别有效禁止在没有用户明确要求时自己新增依赖。因为AI每次都倾向于用第三方库来解决现有问题尤其是一些很小的需求比如随机数、日期格式化它都想下一个dayjs、uuid结果 package.json 越来越胖。这条禁令写出来之后项目的依赖增长立刻温和了。4. 实操落地把规范文件变成AI真正会遵守的规则4.1 规范文件的物理结构与工程路径写规范不是写作文落盘位置和文件结构非常重要。我们最终将文件放在了项目根目录名称为AI_CODING_RULES.md原因非常简单根目录下最容易让AI在读取仓库上下文时命中。理论上是这样但实际工程里有多个子包所以文件结构被进一步拆成了三个文件文件作用AI_CODING_RULES.md总纲目录结构、优先级、命名、禁止事项docs/frontend-architecture.md具体技术栈实现细节如组件通信、状态管理、请求层约定docs/ai_code_review.md面向AI的代码评审规范告诉它审查别人的代码时重点看什么之所以拆成三份是因为AI的上下文窗口是有限的。如果灌一整本《前端开发手册》给它它很可能在生成长代码的中间阶段把关键规则忘掉。拆成单点文件配合工具的规则机制能精准命中。4.2 在Cursor / Copilot 中把规范真正挂载上接下来是操作层面。不同AI编程工具对规范文件的引用方式不一样但核心思路一致把规则文件放到AI能够自动感知的位置。在 Cursor 中我用的是项目级 Rules 机制。通过.cursor/rules/目录可以针对不同目录、不同文件类型配置规则.cursor/rules/ ├── global.mdc # 对所有文件生效的总规则 ├── typescript.mdc # 对 .ts / .tsx 文件生效 ├── vue.mdc # 对 .vue 文件生效 └── api.mdc # 对 src/api 目录生效每个.mdc文件开头是 YAML front matter说明匹配范围--- description: TypeScript coding rules globs: [*.ts, *.tsx] ---然后在正文里写入对应的规则摘要并在末尾用一句话提示AI去查看根目录的AI_CODING_RULES.md获取完整细节。这样做的价值是AI在生成代码时能自动携带相关规则而不是等用户手动粘贴。如果是 GitHub Copilot则指向.github/copilot-instructions.md同样在顶部写全局指令按需引用其他文件。重点经验是不要让规则文件本身太长否则指向根的提示会被淹没。核心规则控制在60~100行左右其余细节在需要时让AI主动查询。4.3 通过Prompt二次约束把规范和具体任务绑定光靠工具挂载还有局限因为有些任务是嵌套的、跨目录的比如“在这个接口基础上增加一个导出按钮”。这时候需要写更细的Prompt让AI在生成某个具体功能前先“走一遍规范检查”。我自己常用的Prompt模板我当前在 src/views/order 目录下开发订单列表的导出功能。开始实现之前 1. 阅读根目录 AI_CODING_RULES.md 中的命名规范、目录规范和禁止事项 2. 检查 src/api/order.ts 是否已存在导出相关接口不要重复定义 3. 页面编辑组件需满足组件拆分判据如超出请先给出拆分方案 4. 完成后用规范中的禁止事项自检一遍并列出你违反复审过哪些条款表面看这样写Prompt很啰嗦但实测下来能大大降低AI自以为是的概率。尤其是第4条“自检并列出违反复审过的条款”AI为了不列出负面结果会在生成时就更加谨慎。这个技巧在白热化、快速开发阶段特别有效。4.4 让AI在生成后自检把规范内置到工作流里最后要在流程上形成闭环。代码生成只是第一步生成后必须让AI跑一遍“自检”。我们用的方式不是只靠人看而是借助了编辑器插件 命令行工具的组合eslintprettier做语法与格式检查eslint-plugin-boundaries做目录范围检查grep手工捞一些违反重点条款的例子比如搜索catch (e) {}或: any。AI自检的Prompt可以写成请对刚才生成的代码做一次规范自查 1. 用 eslint 规则跑一遍把报错列表贴出来 2. 手工检查是否存在违反 AI_CODING_RULES.md 禁止事项的地方 3. 如果发现违规直接给出修正后的完整代码有了这个自检步骤AI生成代码的质量基本会从“能运行”提升到“可评审”。我自己感受很明显加入自检前后代码评审时的修改量至少减少了一半。5. 验证AI是否真正遵守了规范的四种手段5.1 静态检查接入先让机器把关规范的第一层验证一定是静态检查。哪怕你不懂编译原理也需要在项目中把 lint 跑起来。前端项目我们用的是 ESLint Stylelint后端项目类似地使用 SonarQube 或专门的 lint 工具。特别建议在 CI 里加一个步骤专门用严格的规则集跑一遍 AI 生成代码所在的目录。这样做的好处是一旦 AI 犯错失败信息会通知到人而不是等到代码评审才爆发。我们的 CI 里曾经发现 AI 生成的代码有以下常见违规console.log没去掉、导出组件的默认路由未注册、类型定义写在函数内部、新增依赖没有同步 lock 文件。遇到这些情况lint 能第一时间报警。5.2 用代码评审兜底AI生成的代码也要走审核AI 生成代码再丝滑也必须有代码评审环节这个底线绝对不能丢。团队可以约定所有AI生成代码必须走一遍正常评审尤其是检查三层是否满足业务需求而不是单纯“编译通过”是否满足规范里的 P0 硬性约束是否存在由AI幻觉引入的边界遗漏比如空数组再map、接口字段拼写错误等。我们的评审清单里专门有一项“这段代码如果由人来写会不会这么写”很多时候 AI 会生成看起来精妙但过度设计的代码比如在简单查询上垫一层抽象工厂这是评审时应该挑出来砍掉的。5.3 建立“违规登记簿”从错误中迭代规范实践一段时间后你一定会发现新的违规模式。比如我们最初没有任何规则能阻止AI在src/views里直接写CRUD整页逻辑后来实际遇到三四次才总结出新判据并根据目录规范和“禁止在页面中写业务接口”的规则新增了 P1 条款。建议在规范文件旁边维护一份AI_RULE_CHANGE_LOG.md记录每个学期出现的新违规、修订规则、验证结果日期发现的问题新增/修改规则验证结果2025-03-12AI在api目录外调用了axios在禁止事项中增加序号5通过 lint 自主修复2025-03-19新写组件时直接复制了其他组件的样式块组件拆分判据扩大到样式部分人工评审时未见复发2025-04-02Promise.all使用场景没兜底异常新增异步错误处理规范生成代码时自动带 catch这份变更日志既是团队的公共资产也是让AI规则不断进化的驱动力。别人接手项目时只要读一遍日志就能知道当前规范为什么这么定哪些坑是真实踩过的。5.4 抽检AI代码里最容易“违法”的三个地方根据我们跑了一整个迭代周期的数据AI 生成代码最容易出现违规的位置高度集中我直接列出来方便你提前布防。第一个是接口请求层。AI 喜欢复用已有函数结果经常出现一个文件里同时导出getOrderList和getOrderListNew两个名称可以一字之差但内部调用的却是两个完全不同的接口。第二个是样式部分。内联样式、!important、乱用flex布局几乎每轮都会出现。这类问题靠规则文本很难完全避免最好的方式是让 lint 直接禁止内联样式。第三个是状态更新。AI 经常直接修改仓库里对象属性的方式完成状态更新而不是走 action 或 store 的 mutation。后端起中这一条危害特别大因为你很难从页面报错定位到是哪个状态被偷偷改了。建议在规范中直接写上“所有 store 更新必须通过代码搜索确认是否存在对应 action不存在时必须新增 action”而不是直接改 state 属性。6. 踩坑记录与经验法则几个月迭代下来的心里话6.1 规范宁可“少而硬”不要“多而软”写了几轮之后我真实的体会是给AI看的规范必须短、硬、少。与其写50条弹性建议不如写10条禁止事项 5条强约束 3条目录树约定。AI对规则的记忆和能力是有限的当规则超过一定数量后它就开始出现“选择困难”反而更容易遗漏某些P0规则。所以我的建议是第一版规范压缩到一页A4纸以内。先把最高频的违规和最有价值的硬约束沉淀下来其余等出了问题再补。6.2 规范要放进工作流而不是挂墙上和在网上看到的很多“规则文档”不同真正能落地的规范一定和工作流深度绑定。要么在 lint 里体现要么在 AI 工具的规则文件里体现要么在代码评审清单里体现。没有工具和工作流兜底的规范就像贴在墙上的安全标语AI根本感知不到。我们做了一次“AI编写规范能力验证”故意把一部分老代码在不看规则的前提下让AI重构结果它完全无视了命名黑名单。再把规则文件用 prompt 显式传给同一个模型结果命名准确率立即提升到 90% 以上。这个对照实验直接说服了团队规范不是给人看的而是喂给AI的上下文。6.3 规则要有“逃跑通道”最后一条经验可能和直觉相反再严格的规范也要设有“例外通道”不然AI会为了满足规则绕过你的意图。比如我们规定“组件必须拆分子组件”但有某些场景下适当冗余更容易维护不拆也行。所以在规范文件末尾我们固定写了一句如果认为某条规则在你的特定场景下不适用请先输出违反规则的说明和原因再生成代码。禁止静默违反规则。这个设置非常妙它把是否违反规则的决策权交回给用户避免AI在规则冲突时自行脑补。实际用下来AI在大多数情况下会因为多了一步说明而主动尝试先按规则做如果实在不行它也会在注释里写明原因后续评审人处理起来高效得多。6.4 最后的最后说一点个人心得这份AI代码规范不是写完之后一劳永逸的。它更像一份活在项目里的“对话记录”每次遇到新问题就往里加一条约束每过两周就删掉那些AI已经自然遵守的冗余条目。只有保持这个增删循环规范文件才不会演变成一本没人看也没有约束力的“法典”。如果你所在的项目也已经让AI大量参与编码我强烈建议你把这项工作提前安排上。别等代码腐烂到没法维护才动手也别一开始就搞几十页大而全的规范。从一页A4纸开始从“禁止事项 目录导航 命名黑名单”三件事起步只要坚持让AI在生成前读到这些内容代码质量会肉眼可见地稳定下来。真到那时候你大概率不会再想退回没有规范的时代了。