# 高质量 Spec 编写指南 **核心原则**:人定义 WHAT,AI 实现 HOW;Spec 是唯一的真实来源。 --- ## 1. 核心概念 ### 1.1 高质量 Spec 的标准 - **可测试**:每个需求都有明确验收标准,可被自动化测试验证。 - **有边界**:明确做什么、不做什么、在什么约束下做。 - **独立于实现**:描述 WHAT,不限制 HOW(外部约束除外)。 ### 1.2 六要素模型 完整 Spec 须包含以下六个要素: | 要素 | 回答的问题 | |------|------------| | **Problem Statement** | 为什么要做?背景和痛点是什么? | | **Success Metrics** | 做到什么程度算成功?可量化的指标。 | | **User Stories** | 谁、在什么场景下、获得什么价值? | | **Acceptance Criteria** | 具体怎么验证?什么行为算通过? | | **Non-Goals** | 明确本期不做什么。 | | **Constraints** | 必须遵守的技术、法律、业务约束。 | ### 1.3 验收标准与原子性原则 **验收标准(AC)** 定义「怎么做才算对」。模糊 AC(如「用户可以登录系统」)会导致实现不一致。 **原子性 AC** 要求每条 AC 只验证一个独立业务行为: - **单一职责**:一个场景只测试一个动作的结果。 - **无依赖**:可单独执行,不依赖其他 AC 的执行顺序。 - **可独立验证**:一条失败时能立刻定位到具体问题。 六要素提供全景结构,原子性 AC 提供可执行粒度,二者融合形成可被 AI 直接消费的精确指令。 --- ## 2. 六要素编写规范 ### 2.1 Problem Statement(问题陈述) 用简洁语言描述当前系统或业务存在的痛点、机会或待解决问题。 **对比**: - ❌ 「用户需要搜索功能。」 - ✅ 「用户在 10,000+ 文档的知识库中查找目标文档平均需 3 分钟,效率低下;需提供搜索功能,将查找时间缩短至 10 秒以内。」 **要点**: - 用数据或事实描述现状。 - 说明不解决的后果。 - 不在问题陈述中直接给出解决方案。 --- ### 2.2 Success Metrics(成功指标) 可量化、可测量的成功标准,用于判断功能是否真正解决问题。 **对比**: - ❌ 「搜索应该很快。」 - ✅ 「搜索 API 响应时间 P95 < 200ms;搜索结果 Top-5 相关性准确率 > 85%(基于人工标注测试集)。」 **要点**: - 必须包含数字(时间、百分比、数量等)。 - 避免主观词汇(「好用」「快速」「美观」)。 - 每个指标须能在 AC 或后续测试中直接验证。 --- ### 2.3 User Stories(用户故事) 从用户视角描述谁想做什么、为了什么价值。格式:「作为…,我希望…,以便…」 **示例**: - 作为系统管理员,我可以创建自定义角色并分配权限组合,以便为不同部门提供差异化的系统访问能力。 - 作为普通用户,我的权限变更后无需重新登录即可生效,以便工作时不被中断。 **要点**: - 每条故事体现独立的用户价值。 - 用户角色要具体,避免笼统使用「用户」。 - 故事不包含实现细节或技术术语。 --- ### 2.4 Acceptance Criteria(验收标准) 对每条用户故事的具体验收规则,定义什么行为算完成。须采用 Given/When/Then 格式(或等效结构化场景),覆盖正常路径、异常路径和关键边界,且全部可自动化测试。 **示例结构**: ```gherkin Scenario: 用正确密码登录 Given 用户 alice@example.com 已注册且密码为 "P@ssw0rd1" When 她用该邮箱和正确密码登录 Then 返回 200,包含有效 JWT ``` --- ### 2.5 Non-Goals(非目标) 明确本期**不**实现的范围,防止范围蔓延和过度设计。 **示例**: - 本期不实现跨组织的权限委托。 - 不实现基于时间段的临时权限。 - 不涉及 UI 层的权限管理界面(由前端团队单独出 Spec)。 **要点**: - 与成功指标互补:成功指标说「要什么」,非目标说「不要什么」。 - 将容易产生歧义或易被「顺手」加上的功能提前排除。 - 阻止 AI 自动添加不必要的复杂功能。 --- ### 2.6 Constraints(约束条件) 技术、法规、业务等方面必须遵守的外部限制,是不可违反的边界。 **示例**: - 必须兼容现有 OAuth2.0 认证流程。 - 权限数据存储使用现有 PostgreSQL 实例,不引入新的存储组件。 - 权限模型设计需参考 AWS IAM Policy 语法规范。 - 所有数据库查询必须使用参数化查询,禁止字符串拼接。 **要点**: - 约束不是实现方案,而是「必须在这个框里做事」。 - 若某约束严重影响目标,须先修正约束(升级 Spec),而非绕过。 - 项目级约束放在项目级规范文档中,模块级约束放在当前 Spec 中。 --- ## 3. 原子性验收标准(Atomic AC)设计 ### 3.1 定义 一条原子性 AC 只描述**一个独立、完整、可单独验证的业务行为**: - 不依赖其他 AC 的执行顺序。 - 一条失败时原因清晰,不会「一条挂、多条误伤」。 - 能一对一转化为一个自动化测试用例。 ### 3.2 标准格式 推荐使用 **Gherkin** Scenario 格式: - **Given**:前置条件,系统当前状态。 - **When**:触发动作,用户或系统操作。 - **Then**:预期结果,可观察的输出或状态变化。 ### 3.3 编写原则 **① 单一职责** 一个 Scenario 只测试一个业务动作的结果。 ❌ 「Given 未登录用户,When 他登录,Then 跳转首页,And 显示待办数量」 ✅ 拆成两条:一条测登录成功,一条测首页数据展示。 **② 前置状态自给自足** Given 通过数据夹具直接设定所需状态,不依赖「先执行 AC-1 再执行 AC-2」。 ❌ 「Given 已通过上一个测试创建了用户」 ✅ 「Given 数据库中已存在用户 alice@example.com,密码为…,登录失败次数为 3」 **③ Then 允许多个相关断言,但须属于同一结果** ✅ 「Then 返回 200,And body 中包含 access_token 字段,And token 有效期 3600 秒」 ❌ 「Then 跳转首页,And 弹出欢迎提示,And 导航栏显示头像」(可能来自不同接口) **④ 环境可恢复、隔离** 每条 AC 执行后不留影响其他 AC 的副作用;转化为测试时通过 `beforeEach/afterEach` 保证数据隔离。 ### 3.4 常见反模式与修正 | 反模式 | 问题 | 修正方法 | |--------|------|----------| | 「用户完成整个订单流程」 | 包含浏览、加购、下单、支付多个动作 | 拆为浏览商品、加入购物车、提交订单、支付成功等多个独立 AC | | Given 描述模糊:「系统正常运行」 | 无具体状态 | 明确系统状态,如「数据库已清空」「缓存已预热」 | | Then 使用主观词:「页面美观」 | 不可测试 | 改为可观察行为,如「页面包含 CSS 类 primary-button」或视觉回归对比 | | 异常场景与正常场景混在一起 | 定位困难 | 异常须单独成 AC,如「密码错误」「账户锁定」「参数缺失」 | --- ## 4. 编写流程:从六要素到可执行 Spec ### 步骤一:起草五要素 先完成除 Acceptance Criteria 外的五个要素,不急于写 AC,确保方向正确。 **输出示例(权限管理模块)**: - Problem Statement:当前系统缺乏细粒度权限控制,无法满足不同部门差异化需求。 - Success Metrics:支持 5 种以上自定义角色;权限校验 P95 < 50ms;变更后 5 秒内生效。 - User Stories: 1. 管理员创建角色并分配权限 2. 用户权限变更后无需重新登录 - Non-Goals:不做跨组织委托;不实现临时权限。 - Constraints:必须兼容现有 OAuth2.0;使用现有 PostgreSQL。 Acceptance Criteria 暂时留空。 ### 步骤二:为每条 User Story 生成原子性 AC 逐个故事展开,写出覆盖正常、异常、边界的原子性 AC。可用 AI 辅助生成草稿,但须逐条审查和修正。 以「管理员创建角色并分配权限」为例: ```gherkin ### Acceptance Criteria for User Story 1: 管理员创建角色 Scenario: 成功创建角色并分配指定权限 Given 管理员已通过 OAuth2.0 认证,且拥有「角色管理」权限 When 调用 POST /api/v1/roles,传入角色名「财务审核员」和权限列表 ["read:order", "write:order"] Then 返回 201,角色创建成功 And 查询该角色权限,包含 "read:order" 和 "write:order" Scenario: 创建已存在的角色名应被拒绝 Given 数据库中已存在角色「财务审核员」 When 管理员尝试创建同名角色 Then 返回 409,错误消息「角色名已存在」 Scenario: 无权限管理员无法创建角色 Given 管理员没有「角色管理」权限 When 调用创建角色接口 Then 返回 403,不产生任何数据 Scenario: 权限列表包含不存在的权限码应被拒绝 Given 系统合法权限码集合中不包含 "delete:everything" When 创建角色时传入权限列表 ["read:order", "delete:everything"] Then 返回 400,错误消息指明非法权限码 Scenario: 角色名为空应被拒绝 Given 管理员拥有创建权限 When 请求的角色名为空字符串 Then 返回 400,错误消息「角色名不能为空」 ``` ### 步骤三:反向验证覆盖度 检查所有 AC 是否覆盖 Success Metrics 和 Constraints。例如 Success Metrics 要求「权限变更后 5 秒内生效」,须有一条 AC 直接验证: ```gherkin Scenario: 新增权限在5秒内生效 Given 用户 Alice 当前权限为 ["read:order"] When 管理员为 Alice 新增 "write:order" 权限 And 等待不超过 5 秒 Then Alice 调用权限校验接口,返回的权限包含 "write:order" Scenario: 移除权限在5秒内不再可用 Given Alice 拥有 "write:order" When 管理员移除该权限,等待不超过 5 秒 Then Alice 调用权限校验,不包含 "write:order" ``` 同时检查 Constraints:所有 AC 是否满足硬性约束(如上例中 OAuth2.0 认证)。 ### 步骤四:迭代打磨(3–5 轮) 基于第一版 AC,生成简要实现计划或测试大纲,检查模糊、遗漏、矛盾之处,反复修订直至六要素与 AC 自洽。一般需 3–5 轮迭代。 ### 步骤五:分配测试锚点(可选) 为每条 AC 分配唯一锚点(如 `[AUTH-ROLE-AC-01]`),便于在开发任务和测试代码中追溯。AC 可进一步拆解为实现任务,但与 Spec 本身解耦,属于实现计划范畴。 --- ## 5. 完整示例:用户权限管理模块 Spec ```markdown # Feature Spec: 用户权限管理模块 ## Problem Statement 当前系统仅区分管理员(全部权限)和普通用户(只读),无法满足业务部门对细粒度权限的需求。需要支持至少 5 种自定义角色,每个角色可配置 20 种以上独立权限。 ## Success Metrics - 支持创建、编辑、删除自定义角色,每个角色可配置 ≥ 20 种独立权限。 - 权限校验 API 响应 P95 < 50ms。 - 权限变更后,无需用户重新登录,5 秒内生效。 - 向后兼容:现有管理员/普通用户的行为不变。 ## User Stories 1. 作为系统管理员,我可以创建自定义角色并分配权限组合,以便为不同部门提供差异化访问能力。 2. 作为普通用户,我的权限变更后无需重新登录即可生效,以便工作不被中断。 ## Non-Goals - 本期不实现跨组织的权限委托。 - 不支持基于时间段的临时权限。 - 不涉及 UI 层的权限管理界面(前端团队单独出 Spec)。 ## Constraints - 必须兼容现有 OAuth2.0 认证流程。 - 权限数据使用现有 PostgreSQL 存储,不引入新组件。 - 权限模型设计参考 AWS IAM Policy 语法风格。 - 所有查询必须参数化,敏感数据不出现在日志中。 ## Acceptance Criteria ### Story 1: 管理员创建角色并分配权限 Scenario: 成功创建角色并分配权限 Given 管理员已通过 OAuth2.0 认证,拥有 "role:manage" 权限 When 调用 POST /api/v1/roles,body 为 { "name": "财务审核员", "permissions": ["order:read", "order:write"] } Then HTTP 201,响应体包含角色 ID And 查询该角色权限列表,包含 "order:read" 和 "order:write" Scenario: 角色名重复时创建失败 Given 数据库中已存在角色名 "财务审核员" When 管理员尝试创建同名角色 Then HTTP 409,错误消息 "ROLE_ALREADY_EXISTS" Scenario: 缺少必填字段 Given 管理员拥有创建权限 When 请求 body 中 name 为空 Then HTTP 400,错误消息 "NAME_REQUIRED" Scenario: 包含非法权限码 Given 系统合法权限集合中无 "super:destroy" When 创建角色时 permissions 包含 "super:destroy" Then HTTP 400,错误消息 "INVALID_PERMISSION_CODE" Scenario: 无权限管理员无法创建 Given 管理员不具备 "role:manage" 权限 When 调用创建角色接口 Then HTTP 403,无数据变更 ### Story 2: 权限变更实时生效 Scenario: 新增权限在5秒内生效 Given 用户 Alice 当前权限为 ["order:read"] When 管理员为 Alice 添加 "order:write" 权限 And 等待 ≤ 5 秒 Then Alice 调用 GET /api/v1/users/{userId}/permissions,结果包含 "order:write" Scenario: 移除权限在5秒内生效 Given Alice 权限为 ["order:read", "order:write"] When 管理员移除 "order:write" And 等待 ≤ 5 秒 Then Alice 查询权限,结果不包含 "order:write" ``` --- ## 6. 质量自检清单 交付前逐项确认: - [ ] **Problem Statement** 是否量化了痛点或机会? - [ ] **Success Metrics** 是否包含具体数字,且每个指标可测试? - [ ] **User Stories** 是否覆盖了所有核心用户角色和场景? - [ ] **每条 AC 是否原子化**?能否单独运行? - [ ] **AC 是否覆盖正常、异常、边界**?(空值、重复、权限不足、超时等) - [ ] **Non-Goals** 是否明确了本期不做的范围? - [ ] **Constraints** 是否列出了所有硬性技术/业务约束? - [ ] 能否用另一种技术栈实现,而 Spec 依然有效?(说明没有泄露 HOW) - [ ] 所有 AC 与 Success Metrics、Constraints 之间是否可追溯? --- ## 7. 常见陷阱与应对 | 陷阱 | 表现 | 应对 | |------|------|------| | 过度规格化 | AC 变成分步操作手册,描述实现细节 | 用「换技术栈检验法」:若 Spec 绑定特定框架或算法,删去实现细节 | | AC 非原子化 | 一条 AC 包含多个动作,或 Given 依赖其他 AC | 坚持「一个动作,一个结果」,用数据夹具直接创建初始状态 | | 遗漏边界条件 | 只写 Happy Path,没有异常场景 | 每个 Story 至少包含:1 条正常、1 条权限/认证异常、1 条数据边界 | | 指标不可测 | 「系统应该快速响应」 | 改为「P95 < 200ms」或「3 秒内返回结果」 | | Spec 腐烂 | 代码迭代了,Spec 未更新 | 将 Spec 纳入版本控制,与代码同步提交;采用增量 Spec | | 约束与方案混淆 | 把「使用 Redis 缓存」当成约束 | 若是强制要求(如公司中间件标准)则为约束;否则归入实现计划决策 |