【文档头信息】
|----------|---|---|---|------------|----------|------------|
| 字段 | 内容 || 编写要点 ||||
| 功能名称 | ++++填写++++ || 动词 + 名词,简洁明确。如"取消订单"/"执行开锁" ||||
| 功能编号 | ++++填写++++ || 唯一编码,便于追溯。如UC-ORD-2026-001 / FW-LOCK-002 ||||
| 所属模块 | ++++填写++++ || 功能所属的系统/子系统 ||||
| 需求来源 | ++++填写++++ || 可追溯的源文档ID,如PRD V3.2-第5.3节 ||||
| 功能描述 | ++++填写++++ || 一句话:谁、在什么场景下、做什么、达成什么目的 ||||
| 版本 || 修改日期 || 修改人 | 修改内容 | 审核人 |
| V1.0 || YYYY-MM-DD || ++++姓名++++ | 初稿创建 | ++++姓名++++ |
1. 触发源 (Trigger)
编写要点:
- 明确*"* 谁*/* 什么*"* 启动了本功能,外部实体 才能做Trigger,内部状态变化不算。
- 如果是*"* 用户主动操作*"* ,说明具体的UI动作。
- 如果是*"* 定时器*"*,说明触发频率和时间点。
- 如果是*"* 回调*"*,说明回调来源和触发条件。
常见错误 :把*"* 系统内部状态变化*"* 误写为触发源。内部状态机跳转是处理过程的一部分,不是触发源。
|-------------|----------|-----------------------------------------------------------------------------------|
| 触发类型 | 是否适用 | 说明 |
| ☐ 用户主动操作 | □ 适用 | ++++如:点击++++ ++++"++++ ++++取消订单++++ ++++"++++ ++++按钮++++ ++++/++++ ++++键盘输入密码++++ |
| ☐ 定时器/调度器触发 | □ 适用 | ++++如:每日凌晨++++ ++++2:00++++ ++++自动关单++++ |
| ☐ 外部系统回调 | □ 适用 | 如:支付成功回调 / 云端MQTT指令下发 |
| ☐ 传感器/硬件中断 | □ 适用 | ++++如:指纹匹配成功中断++++ ++++/++++ ++++霍尔传感器触发++++ |
| ☐ 其他 | □ 适用 | ++++请注明++++ |
2. 参与者 (Participants)
编写要点:
- 主要操作人:最终受益人或操作者(可以是人,也可以是代表人的前端系统)。
- 协作系统 :本功能主动调用的外部系统。
- 被动通知方 :本功能主动通知 的外部系统(发消息*/* 邮件*/*短信)。
关键区分 :Trigger 是*"* 谁启动了我*"* ;Participants 是*"* 我启动后要和谁打交道*"*。
|--------|-----------------------------------------|-------------------------------------|
| 类型 | 具体对象 | 交互目的 |
| 主要操作人 | ++++如:注册买家++++ | ++++发起操作并接收结果++++ |
| 协作系统1 | ++++如:支付网关++++ ++++/++++ ++++仓储系统++++ | ++++发起退款++++ ++++/++++ ++++拦截发货++++ |
| 协作系统2 | ++++如:云端管理平台++++ | ++++接收开锁指令上报++++ |
| 被动通知方 | ++++如:短信平台++++ ++++/++++ ++++本地日志存储++++ | 发送通知 / 写入Flash |
3. 前置条件 (Pre-conditions)
编写要点:
- 列出执行本功能前必须成立的所有条件。
- 包括:用户状态、资源状态、系统状态、环境状态。
- 条件必须是可验证的(测试可以检查)。
常见错误 :把*"* 输入参数合法性*"* 写在前置条件里。输入合法性应在处理过程 中校验,前置条件是执行前系统已经存在的状态。
好坏对比:
- ❌差:" 用户输入了正确的订单号。"(这是输入校验)
- ✅好:" 目标订单存在且属于当前用户。"(执行前必须成立)
- □ 如:用户已登录且具有操作权限
- □ 如:目标订单存在且属于当前用户
- □ 如:目标资源状态符合要求(如status='待发货')
- □ 如:电池电量 \> 10%(嵌入式)
- □ 其他前置条件:___________
4. 输入规约 (Input Specification)
编写要点:
- 列出调用方传递给本功能的所有数据。
- 类型引用《系统数据字典》,不在此处重复定义基础类型。
- 约束包括:必填性、取值范围、格式要求、业务关联约束。
- 来源说明:数据来自哪里(前端表单、URL参数、消息体、寄存器等)。
好坏对比:
- ❌差:" 订单信息*"*(太模糊,无结构)
- ✅好:下表逐字段定义
|--------------------|-------------------|--------|-----------------------------------|--------------|
| 参数名 | 类型(引用数据字典) | 必填 | 约束 / 边界 | 来源 |
| 如:orderId | 如:OrderId | 是 | ++++必须属于当前用户++++ | ++++前端表单++++ |
| 如:cancelReason | 如:String(200) | 否 | ++++最多++++ ++++200++++ ++++字符++++ | ++++前端表单++++ |
| 如:password | 如:String(32) | 是 | ++++6++++ ++++位数字,不可为弱密码++++ | ++++键盘输入++++ |
| ++++参数名++++ | ++++类型++++ | 是/否 | ++++约束描述++++ | ++++来源++++ |
5. 正常操作流程 (Normal Flow)
编写要点:
- 纯业务语言 ,不出现字段名、表名、API名。
- 步骤编号,按时间顺序排列。
- 每步是一个完整的业务动作 ,主语是*"* 用户*"* 或*"* 系统*"*。
- 步骤粒度:一个步骤对应一个可观测的业务节点 (测试能判断*"* 这一步完成了*"*)。
好坏对比:
- ❌差:" 系统处理取消请求。"(不可观测)
- ✅好:" 系统校验订单状态是否为*'* 待发货*'* 。"(可验证)
|--------|--------------------------------------------------------|
| 步骤 | 动作描述 |
| 1 | ++++用户提交取消申请++++ |
| 2 | ++++系统校验订单状态允许取消++++ |
| 3 | ++++系统调用支付网关发起退款(如已支付)++++ |
| 4 | ++++系统释放库存,更新订单状态为++++ ++++"++++ ++++已取消++++ ++++"++++ |
| 5 | ++++系统提示成功并发送通知++++ |
6. 扩展操作流程 (Extension Flow)
编写要点:
- 每个扩展对应主流程中某一步可能出现的偏离。
- 写明触发条件(什么情况下会走这个分支)。
- 写明处理动作(系统怎么应对)。
- 如果分支导致流程终止,明确说明*"* 终止*"*。
- 如果分支后回到主流程,说明*"* 回到第X 步*"*。
好坏对比:
- ❌差:" 接口调用失败时处理。"(太笼统,不知道失败后怎么办)
- ✅好:" 支付网关超时(>3s )→重试1 次,失败则回滚事务,提示稍后重试。"
|-----------------------|---------------------------------------------------------------------------|
| 触发条件 | 处理动作 |
| ++++如:订单已发货++++ | ++++提示++++ ++++"++++ ++++已发货无法取消++++ ++++"++++ ++++,流程终止,数据不变++++ |
| 如:外部接口超时(\>3s) | ++++重试++++ ++++1++++ ++++次,失败回滚事务,提示++++ ++++"++++ ++++系统繁忙++++ ++++"++++ |
| ++++如:重复提交++++ | ++++幂等处理,直接返回上次结果++++ |
| ++++如:凭证校验失败(嵌入式)++++ | ++++拒绝操作,记录失败日志,触发防暴力破解策略++++ |
| ++++触发条件++++ | ++++处理动作++++ |
7. 输出规约 (Output Specification)
编写要点:
- 同步返回 :API响应体结构,成功和失败都要写。
- 对外指令:调用了什么外部接口、发了什么消息,写明协议、地址、报文格式。
- 内部状态变更 :改了哪些表*/* 哪些字段*/* 变成什么值,缓存*/Flash*操作也要写。
- 超时*/*重试策略:非同步返回的输出必须写清楚。
|------------------|----------------------------------------------------|----------------|-----------------------|
| 输出类型 | 具体内容 | 目标方 | 超时 / 重试策略 |
| 同步返回(成功) | {"code":0, "msg":"成功", "data": {...}} / LED绿灯+蜂鸣一声 | 前端/调用方 | N/A |
| 同步返回(失败) | {"code":"EXXXX", "msg":"..."} / LED红灯闪烁 | 前端/调用方 | N/A |
| 对外指令 1 | 如:HTTP POST到仓储 /api/intercept,Body:{orderId} | ++++仓储系统++++ | 3s超时,重试1次 |
| 对外指令 2 | 如:发送MQ消息到Topic order-exchange | ++++数据分析系统++++ | ++++异步,失败记录日志补偿++++ |
| 对外指令 3 | 如:MQTT上报开锁事件到云端 | ++++云端平台++++ | ++++异步,失败本地缓存++++ |
| 内部状态变更 1 | 如:订单表 status='CANCELLED' | 内部数据库 | ++++事务内执行++++ |
| 内部状态变更 2 | 如:库存表 available_qty + 1 | 内部数据库 | ++++事务内执行++++ |
| 内部状态变更 3 | 如:删除Redis缓存 order:detail:{id} / 写入Flash日志 | 内部缓存/存储 | ++++事务提交后执行++++ |
8. 后置条件 (Post-conditions)
编写要点:
- A. 数据状态变更:强制性,执行成功后必须变。
- B. 对外通知:非强制性,但必须尝试触发(允许失败异步补偿)。
- C. 不变量:执行前后必须始终成立的全局规则。这是最容易遗漏的。
- D. 失败回滚策略:哪些操作要回滚、哪些要补偿、哪些要记录。
不变量编写技巧 :问自己三个问题*------*
- 这个功能改了数据,会不会破坏某个跨表的恒等式?
- 这个功能改了状态,会不会产生非法状态组合?
- 这个功能并发执行时,会不会破坏数据一致性?
好坏对比:
- ❌差:不写不变量。(开发不知道隐含约束,容易产生Bug)
- ✅好:" 订单金额*=* 商品总额*-* 优惠总额,取消后该等式仍成立。"
A. 数据状态变更(强制性)
-
\] \[如:订单表 status 变更为 'CANCELLED'
-
\] \[如:库存表 available_qty + 1
-
\] \[如:取消记录表插入一条记录 / Flash写入开锁日志
B. 对外通知(非强制性,但必须触发)
-
\] \[如:发送MQ事件 ORDER_CANCELLED / MQTT上报开锁事件
C. 不变量 (Invariants) ------ 全局约束
-
\] \[如:资金恒等:已付金额 = 退款金额 + 优惠退回
-
\] \[如:**状态机约束**:只有X或Y状态的订单才能转到Z状态
-
\] \[如:**时间约束**(嵌入式):单次开锁总耗时 \< 3s
-
\] \[如:**能耗约束**(嵌入式):单次开锁能耗 \< 10mAh
D. 失败回滚策略
-
\]如:外部接口失败 → 本地事务整体回滚,不保留中间状态
-
\]\[如:MQ发送失败 → 不阻塞主流程,记录日志由定时任务补偿
-
\]\[如:电机堵转(嵌入式)→ 立即断电回缩,维持锁舌原状态
9. 具体场景实例 (GWT Scenarios)
编写要点:
- 每个场景必须对应 第5 节(S1 )或第6 节(E1 、E2...)中的一条路径。
- Given:用具体数据描述前置状态(造数指令)。
- When:具体的触发动作(含具体参数)。
- Then :可验证的技术断言(返回值、DB 状态、缓存、MQ、日志、物理动作)。
覆盖完整性检查 :第6 节有几行扩展,第9 节就应该有几个对应的E场景。
关系说明 :第5 、6 节定义*"* 怎么走*"* ,本节定义*"* 走完之后,具体字段变成什么*"*。
|---------------|----------|--------------------------------------|---------------------|----------------------------------------------------|
| 场景 ID | 对应流程 | Given (前置数据锚点) | When (触发动作) | Then (技术断言) |
| S1 | 正常流程 | 如:订单O001,status='待发货',qty=10 | 用户请求取消O001 | ①返回code=0;②DB status='CANCELLED',qty=11; ③MQ发出 |
| E1 | 扩展-条件1 | 如:订单O002,status='已发货' | 用户请求取消O002 | ①返回E2001;②DB status不变;③无MQ |
| E2 | 扩展-条件2 | ++++如:模拟支付网关超时++++ | 用户请求取消O003 | ①返回E3005; ②事务回滚,status不变 |
| E3 | 扩展-条件3 | ++++如:指纹匹配失败++++ ++++3++++ ++++次++++ | ++++用户按压指纹++++ | ①LED红灯; ②冻结30s; ③记录失败日志 |
10. 非功能性约束 (NFR)
编写要点:
- 只写本功能特有的 ,全局基线(如*"* 系统响应时间*<2s"*)不在此重复。
- 常见维度:并发、性能、幂等、安全、可观测性、实时性、功耗、可靠性。
- 每个约束必须有可量化的验收标准 ,不能用模糊词(如*"* 尽量快*"*)。
好坏对比:
- ❌差:" 系统应快速响应。"(不可验收)
- ✅好:" 触发到锁舌动作*< 200ms* 。"(可测量)
|----------|------------------------|----------------------------------------------|
| 维度 | 约束描述 | 验收标准 |
| 并发 | ++++同一资源不允许并发冲突操作++++ | ++++使用乐观锁,并发时仅一个操作成功,其他返回冲突提示++++ |
| 性能 | ++++涉及外部接口调用,需设置超时++++ | 超时阈值3s,超时快速失败 |
| 幂等 | ++++重复请求不产生副作用++++ | 使用requestId去重,重复请求返回缓存结果 |
| 安全 | ++++操作权限校验++++ | ++++仅资源创建者可操作,否则返回++++ ++++403++++ |
| 可观测性 | ++++关键操作需记录日志++++ | ++++成功++++ ++++/++++ ++++失败均输出结构化日志含关键字段++++ |
| 实时性 | ++++嵌入式:触发到执行完成++++ | 从触发到锁舌动作 \< 200ms |
| 功耗 | ++++嵌入式:单次操作能耗++++ | 单次开锁能耗 \< 10mAh |
| 可靠性 | ++++嵌入式:异常自恢复++++ | 硬件看门狗20s强制复位 |
针对该模板的具体填写案例,参见文章:写给AI的系统功能规格说明书案例-CSDN博客