06月09, 2026

规约编程实践指南 — 让 AI 按规矩写代码

在日常开发中,直接让 AI 写代码常常会遇到一些问题,比如不了解项目规范、代码质量不可控,上下文容易丢失、需求理解偏差等,解决办法就是使用规约编程。规约编程的核心思路是:先规划,再编码。通过两层约束机制,让 AI 在明确的规则和计划下工作。

一、为什么需要规约编程

1.1 AI 编码的常见痛点

在日常开发中,直接让 AI 写代码常常会遇到以下问题:

不了解项目规范:AI 生成的代码风格与项目现有代码不一致,比如命名风格混乱、import 顺序不统一、组件写法不符合团队约定。

代码质量不可控:没有明确约束时,AI 可能会引入不推荐的库、使用已废弃的 API、忽略类型定义,导致代码质量参差不齐。

上下文容易丢失:对于复杂功能,一次对话难以覆盖所有细节,AI 容易”忘记”之前的约定,导致前后代码不一致。

需求理解偏差:口头描述的需求容易产生歧义,AI 的理解可能与你的预期不同,返工成本高。

1.2 规约编程解决了什么问题

规约编程的核心思路是:先规划,再编码。通过两层约束机制,让 AI 在明确的规则和计划下工作:

约束层级 作用 类比
Rules(项目规则) 定义项目的技术架构、编码规范、组件使用标准 类似团队的开发规范文档
Specs(需求规约) 将具体需求拆解为需求文档、设计文档和任务清单 类似需求评审 + 技术方案 + 排期

有了这两层约束,AI 输出的代码就像是一个熟悉项目规范的开发者,按照评审通过的技术方案,逐步交付代码。


二、核心概念

2.1 Rules(规则)—— 项目的”开发军规”

Rules 是长期不变的项目级规范,存放在.{agentName}/rules/目录下。AI 在每次执行任务时都会自动读取并遵循这些规则。

Rules 的特点:

始终生效:设置alwaysApply: true后,无论是规约规划还是代码编写,AI 都会自动遵循

一次配置,长期受益:只需要维护一次,后续所有 AI 编码都会遵守

团队共享:随代码仓库一起管理,团队成员使用同一套规则

典型的 Rules 文件包括:

1
2
3
4
5
6
7
8
9
10
11
12
.{agentName}/rules/
├── architecture.md # 技术架构:技术栈、目录结构、开发约束
├── code-style.md # 代码风格:命名规范、缩进、引号、分号等
├── component.md # 组件规范:开发规范、使用优先级、拆分原则
├── page.md # 页面规范:页面结构模板、路由配置、状态管理
├── api.md # API 规范:请求封装、类型定义、Mock 数据
├── state-management.md # 状态管理:Model 结构、使用方式
├── responsive.md # 响应式设计:布局系统、媒体查询
├── testing.md # 测试规范:Jest 单元测试执行方式和代码示例
├── commands.md # 命令工作流:开发命令、Git 工作流、部署流程
├── protected-files.md # 受保护的文件或目录,指定某些文件AI只读不改
└── glossary.md # 名词解释:组件库说明、模块联邦名称

2.2 Specs(规约)—— 需求的”施工图纸”

Specs 是针对具体需求生成的一次性规划文档,存放在.{agentName}/specs/{项目名}/目录下。每套 Specs 包含三个文件:

文件 内容 作用
requirements.md 需求文档 定义用户故事和验收标准,明确”做什么”
design.md 设计文档 技术方案、组件设计、数据模型,明确”怎么做”
tasks.md 任务清单 将设计拆解为可独立执行的开发任务,明确”分几步做”

2.3 两者的关系

1
2
3
4
5
6
7
Rules(项目规则)          Specs(需求规约)
━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━
长期不变的约束 一次性的需求规划
适用于所有需求 仅针对特定需求
团队统一维护 每次需求单独生成

AI 编码时同时遵循两者

简单类比:Rules 是”公司制度手册”,Specs 是”项目施工图纸”。施工时既要遵守公司制度,也要按图纸施工。


三、前置准备 —— 配置项目规则(Rules)

3.1 .{agentName}/rules/目录的作用

这个目录是 AI 的”知识库”,告诉 AI 你的项目是怎样的、代码应该怎么写。AI 在每次执行任务前都会自动加载这些规则文件。

3.2 应该配置哪些规则

建议按以下维度配置规则文件:

(1)技术架构(architecture.md)

告诉 AI 项目的技术栈和目录结构,例如:

1
2
3
4
---
globs: *
alwaysApply: true
---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 架构模式和最佳实践

## 项目概述
- **项目类型**: React TypeScript 前端应用
- **基础框架**: 基于 ola-cli@3.x 的 ola-template-4a 模板

## 核心技术栈
| 技术 | 版本/说明 |
|-----|----------|
| React | 16.13.1 |
| TypeScript | - |
| 状态管理 | @olajs/modx@3.1.0 |
| UI组件库 | antd |

## 目录结构规范
(列出项目的标准目录结构)

(2)代码风格(code-style.md)

定义团队的编码规范,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## 代码风格
| 规则项 | 规范 |
|-------|------|
| 缩进 | 2 个空格 |
| 引号 | 单引号 |
| 分号 | 必须使用 |
| 逗号 | 尾随逗号 |

## 命名规范
| 类型 | 命名风格 | 示例 |
|-----|---------|------|
| 组件 | PascalCase | CouponManager |
| 变量/函数 | camelCase | getCouponList |
| 常量 | UPPER_SNAKE_CASE | COUPON_TYPE |

(3)组件规范(component.md)

告诉 AI 如何选择和使用组件:

1
2
3
4
5
6
## 组件查找顺序
| 优先级 | 来源 |
|-------|------|
| 1 | 项目公共组件(src/components) |
| 2 | common 组件库 |
| 3 | antd 组件库 |

(4)其他规则

根据项目需要,还可以配置 API 规范、状态管理规范、页面开发规范等。

3.3 如何编写一份好的规则文件

格式要求:

  • 文件头部必须包含 YAML frontmatter,声明作用范围
  • globs: * 表示对所有文件生效
  • alwaysApply: true 表示始终加载

内容原则:

  • 具体而非模糊:写”使用 2 个空格缩进”,而不是”合理缩进”
  • 有示例代码:用代码片段展示期望的写法
  • 保持更新:技术栈升级或规范变化时同步更新规则文件
  • 避免冗长:只写 AI 需要知道的关键信息,不必面面俱到

四、规约编程工作流

4.1 整体流程

规约编程分为两个阶段:规约规划规约执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
需求描述


┌─────────────────────────────┐
│ 阶段一:规约规划 │
│ │
│ ① 生成需求文档 ──→ 审查确认 │
│ ② 生成设计文档 ──→ 审查确认 │
│ ③ 生成任务清单 ──→ 审查确认 │
└─────────────────────────────┘


┌─────────────────────────────┐
│ 阶段二:规约执行 │
│ │
│ 按任务清单逐个执行开发任务 │
│ 任务1 → 任务2 → 任务3 → ... │
└─────────────────────────────┘


功能交付

4.2 阶段一:规约规划(交互式)

只需要用自然语言描述你的需求,AI 会自动生成三份规约文档。关键在于:每一步都有审查环节,你可以随时要求调整。

Step 1:生成需求文档

  • AI 将你的需求描述转化为结构化的需求文档,包含用户故事和验收标准
  • 完成后会询问:"调整需求内容"还是"继续生成设计文档"
  • 如果有遗漏,选择”调整”并补充说明

Step 2:生成设计文档

  • 基于需求文档,AI 生成技术方案,包含组件设计、数据模型、API 设计等
  • 完成后会询问:"调整设计内容"还是"继续生成任务清单"
  • 如果技术方案不合理,选择”调整”并说明你的想法

Step 3:生成任务清单

  • 将设计方案拆解为可独立执行的开发任务
  • 完成后会询问:"调整任务内容"还是"确认完成,准备执行"
  • 确认无误后进入执行阶段

4.3 阶段二:规约执行

确认规约文档后,AI 会提供三个操作入口:

  • 查看任务清单:查看所有待执行的任务
  • 执行所有任务:按顺序自动执行全部任务
  • 执行下一个任务:逐个执行,每完成一个任务后暂停

每个任务执行时,AI 会:

  • 读取规约文档,理解任务上下文
  • 严格按照任务范围编码,不越界
  • 完成后汇报产出物和修改的文件

4.4 什么时候该用规约编程

场景 推荐方式
新增一个完整的业务模块 规约编程
涉及多个文件的大功能迭代 规约编程
修改一个 Bug 直接编码模式
调整样式或文案 直接编码模式
重构某个组件 视复杂度而定

五、实战演示

下面通过一个完整的案例,展示规约编程的全过程。

5.1 需求描述

假设我们要为项目新增一个”优惠券管理”模块,包含优惠券列表页和创建优惠券页面。

在 AI Coding 工具中切换到规约编程模式,输入:

我需要新增一个优惠券管理模块,包含以下功能:

  1. 优惠券列表页:支持按状态筛选、分页查看、启用/停用操作
  2. 创建优惠券页:支持填写优惠券名称、类型、面额、有效期等信息并提交

5.2 AI 生成需求文档

AI 会自动生成.{agentName}/specs/coupon-management/requirements.md,内容类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 需求文档

## 需求 1 - 优惠券列表

**用户故事:** 作为运营人员,需要查看和管理优惠券列表,以便掌握优惠券使用情况

### 验收标准
1. 当进入优惠券列表页时,默认展示全部状态的优惠券,按创建时间倒序排列
2. 当选择状态筛选条件时,列表仅展示对应状态的优惠券
3. 当点击"启用"按钮时,优惠券状态变为启用,列表刷新
4. ...

## 需求 2 - 创建优惠券

**用户故事:** 作为运营人员,需要创建新的优惠券,以便投放促销活动

### 验收标准
1. 当打开创建页面时,展示优惠券创建表单
2. 当必填字段未填写时,提交按钮置灰或给出提示
3. ...

此时 AI 会问你:需求文档是否需要调整?确认后继续。

5.3 AI 生成设计文档

接着生成.{agentName}/specs/coupon-management/design.md,包含技术方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 设计文档

## 1. 技术架构
- 前端技术栈:React + TypeScript
- 状态管理:@olajs/modx(页面级 useShareModel)
- UI 组件:antd
- API 请求:common/utils/ajax

## 2. 详细设计

### 2.1 前端设计
- 页面组件:CouponList(列表页)、CouponCreate(创建页)
- 状态管理:每个页面独立 model.ts
- 路由:/coupon/list、/coupon/create

### 2.2 目录结构
src/pages/coupon/
├── routes.ts
├── CouponList/
│ ├── index.tsx
│ ├── index.scss
│ ├── model.ts
│ ├── api.ts
│ └── type.ts
└── CouponCreate/
├── index.tsx
├── index.scss
├── model.ts
├── api.ts
└── type.ts

5.4 AI 生成任务清单

最后生成.{agentName}/specs/coupon-management/tasks.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 实现任务

## 任务概览
- 总任务数:5
- 任务类别:开发、集成

## 开发任务
- [ ] 1. 创建优惠券模块目录结构和路由配置
- 创建 pages/coupon/ 目录及 routes.ts
- 在主路由中引入模块路由
- _需求: 1 2_
- [ ] 2. 实现优惠券列表页 API 和状态管理
- 编写 api.ts(列表查询、启用/停用接口)
- 编写 model.ts(列表状态、分页、筛选)
- _需求: 1_
- [ ] 3. 实现优惠券列表页 UI
- 筛选栏、数据表格、分页组件
- 启用/停用操作按钮
- _需求: 1_
- [ ] 4. 实现创建优惠券页
- 表单组件、字段校验、提交逻辑
- _需求: 2_
- [ ] 5. 添加 Mock 数据
- 为所有 API 接口添加 Mock 数据
- _需求: 1 2_

确认后,点击”执行所有任务”或”执行下一个任务”即可开始编码。

5.5 AI 逐步执行任务

AI 会按照任务清单逐个执行,每个任务完成后汇报:

  • 创建/修改了哪些文件
  • 完成了哪些交付物
  • 是否严格遵守了任务边界

直到所有任务完成,整个功能模块开发结束。


六、最佳实践

6.1 需求描述要清晰

好的需求描述:

新增优惠券列表页,支持按状态(全部/启用/停用/已过期)筛选,表格展示字段:优惠券名称、类型、面额、有效期、状态、操作,操作列支持启用/停用,分页每页 10 条。

不好的需求描述:

做一个优惠券页面

需求越清晰,AI 生成的规约文档质量越高,后续返工越少。

6.2 善用审查环节

每一步生成后都有审查机会,不要急于跳过:

  • 需求文档:检查是否覆盖了所有功能点、验收标准是否合理
  • 设计文档:检查技术方案是否符合项目规范、组件拆分是否合理
  • 任务清单:检查任务粒度是否合适、执行顺序是否正确

6.3 Rules 要持续维护

当项目发生以下变化时,记得同步更新 Rules:

  • 升级了技术栈版本
  • 引入了新的组件库或工具
  • 调整了目录结构规范
  • 新增了编码约定

6.4 大功能用规约,小改动用编码

不是所有任务都需要走规约流程:

  • 规约编程:新增模块、大功能开发、涉及多文件的复杂迭代
  • 直接编码:Bug 修复、样式调整、文案修改、小范围改动

在 AI Coding 工具中可以随时切换模式,灵活选择最高效的方式。

6.5 团队协作建议

  • .{agentName}/rules/目录纳入 Git 版本管理,团队共享同一套规则
  • 新成员入职时,可以通过阅读 Rules 快速了解项目规范
  • 定期 Code Review 时,检查 Rules 是否需要更新

七、常见问题 FAQ

Q1: 已有功能要迭代怎么办?

每次迭代会创建新的规约文档(使用不同的项目名,如coupon-management-v2),不会覆盖旧的。AI 在创建新规约时会分析现有代码,确保在现有基础上扩展而非重写。

Q2: 规约文档可以复用吗?

规约文档是一次性的,每次需求单独生成。但 Rules(项目规则)是长期复用的,所有需求都会自动遵循。

Q3: 生成的代码不满意怎么调整?

有两个时机可以调整:

  • 规约阶段:在审查环节选择”调整”,修改规约文档后重新生成代码
  • 执行阶段:任务执行后如果代码不满意,可以直接告诉 AI 修改意见,AI 会在当前任务范围内调整

Q4: 规约编程 vs 直接让 AI 写代码,区别在哪?

对比维度 直接编码 规约编程
适用场景 小改动、Bug 修复 新功能、大迭代
代码规范性 依赖 AI 自由发挥 受 Rules 严格约束
需求覆盖度 容易遗漏 需求文档明确覆盖
技术方案 无显式方案 有设计文档记录
可追溯性 有完整的规约文档
执行一致性 不确定 按任务清单逐步执行

Q5: Rules 规则文件怎么快速生成?

你不需要从零编写 Rules。可以参考本项目.{agentName}/rules/目录下的已有规则文件作为模板,根据自己项目的实际情况修改即可。核心是把项目的技术栈、目录结构、编码规范、组件使用约定等信息整理清楚。

Q6: 一个需求应该拆成多个规约还是放在一个里?

建议一个业务需求对应一套规约。如果需求过大(比如涉及 10+ 个页面),可以按模块拆分为多套规约,每套独立规划和执行。


八、一些 AI 常犯的错误

8.1 组件选择问题

设计文档的「前端设计」部分在描述页面结构时,只写了”使用 antd Form 组件”,没有要求先走一遍组件查找流程。如果设计文档中增加一条约束:

页面中使用的组件必须按照项目组件规范的查找顺序确认后再写入设计方案(src/components → common 组件库 → antd 组件库)

那么在设计阶段就会先查 common 组件库文档,发现 JsonForm 更适合表单场景。

8.2 字段语义合并问题

设计文档中将 startTime 和 endTime 定义为两个独立字段,到任务执行时我就一对一翻译了。如果设计文档中增加一条约束:

表单字段设计应以用户交互视角分组,语义上属于同一概念的字段(如日期范围、地址组合)应设计为单个表单控件

那么在设计阶段就会将有效期设计为一个 RangePicker 字段。


总结

规约编程的核心价值在于:用规则约束 AI 的行为,用规约指导 AI 的工作

Rules 让 AI 了解你的项目 —— “应该怎么写代码”

Specs 让 AI 琢磨你的需求 —— “应该写什么代码”

两者结合,AI 就能在你的项目中输出高质量、符合规范、可预期的代码。

开始使用:在 AI Coding 工具中切换到规约编程模式,描述你的需求,体验从规划到交付的完整流程。

本文链接:https://www.chenliqiang.cn/post/spec-coding-guide.html

-- EOF --