第 6 章 写出用户故事:说清楚你要什么
作为【角色】,我想要【功能】,以便【价值】;写不出来的地方,就是你还没想清楚的地方。
一句话需求为什么不够
还是上一章那个整理发票的例子。你对 AI 说“帮我做一个发票功能”,它很可能给你做出一套全自动发票识别系统:拍照上传、自动识别、分类统计,连导出报表都有,又大又复杂,还不是你要的。换一种说法:“作为一个要整理发票的运营,我想要一个能批量读取发票图片并按日期重命名的功能,以便我每月不用手动处理 30 张发票。”这一句话说完,AI 做出来的东西和你要的就不会差太远。
两句话的差别在于第二句把三个空都填上了。谁要用,运营;要什么,批量读图、按日期重命名;为了什么,每月少处理 30 张发票。第一句三个空全是空的,AI 只能自己猜,它猜出来的是“发票功能”在互联网上最常见的样子,而最常见的样子通常就是最大最全的样子。
这个格式一点都不高级,它就是软件行业用了二十多年的用户故事(User Story)的标准写法。它的用处在于你填这三个空的过程。填的时候你会发现,有的空填不出来。角色填不出来,说明你不知道为谁做;功能填不出来,说明你只有一个愿望;价值填不出来,说明这个功能可能根本不需要。
三个空怎么填
角色要具体。 上一章说过,为谁做要具体到一个人。写到用户故事里也一样。“作为用户”等于没写,“作为正在投简历的设计系学生”才有用。角色一具体,后面两个空就跟着具体:这个学生要的是把作品发给面试官,价值是让面试官三分钟内看完他最好的三个作品。
功能写成用户能做的一件事。 功能这个空最容易写成技术词:“我想要一个数据库”“我想要一个拖拽组件”。用户不会这么说话。用户说的是“我想把作品图片放上去,排成我喜欢的样子”。拖拽组件是你或者 AI 后面选的做法,不进用户故事。一个检验方法:这句话念给一个完全不懂软件的朋友听,他能不能听懂你要做什么。听不懂,就是写成了技术词。
价值要能检验功能。 “以便”后面那半句是整条故事里最重要的。它回答“为什么要这个功能”。写出来之后,你反过来看前半句:为了这个价值,这个功能是必需的吗?有没有更简单的办法达到同样的价值?如果“以便”后面写不出来,或者写出来是“以便功能更完整”这种空话,这个功能就该放到第 8 章的“以后再说”那一档。
拿 Bentoly 的一类用户试一下。作为做视频的人,各个平台的简介里只能放一个链接,我想要一个页面放下我所有的账号,以便观众从任何一个平台都能找到我在其他平台的账号。三个空都有了,再拿“以便”去检验别的功能:“我想要一个二维码”,为了让观众从任何平台找到我的其他账号,二维码帮得上忙吗?观众在手机上看简介,扫不了自己屏幕上的二维码,帮不上。于是二维码对这类用户进不了第一版。换一类用户,比如在线下活动上递名片的人,同一个功能的答案就变了。“以便”就是这样替你做取舍的。
填完三个空,再补三样东西,这是我在阿布的项目手册里给 Agent 定的要求:写清在什么情境下(谁,以及他当时在干什么),写清做完的标志(怎么算完成),给每条故事标一个优先级 P1、P2 或 P3。P1 是没有它用户就办不成那件事的,P2 是有了明显更好的,P3 是锦上添花的。每条故事都要能单独演示,也就是说,做完这一条,你能打开产品给人看“这件事现在能办了”。
还有一条规矩:需求有两种以上合理理解的时候,把几种理解都列出来,自己选一个,或者让 AI 列出来你来选。别默认挑一种就往下写。“分享主页”可以理解成复制一个链接,也可以理解成生成一张图片发朋友圈,还可以理解成生成一个二维码。三种理解做出来是三个不同的功能。先选,再写。选的办法还是看“以便”:求职者把页面发给面试官,发的是邮件或者聊天消息,链接最合适;要是用户是在线下活动上给人看,二维码才合适。价值不同,选法不同。
故事太大了怎么办
第一次写用户故事,写出来的多半太大。“作为求职者,我想要一个在线简历,以便面试官了解我。”这句话格式没错,但它说的是整个产品,你没法说“做完这一条我能演示什么”,因为它要做完整个产品才能演示。
太大的故事要切小,切到每一条做完都能单独演示为止。切的办法有三种。
按步骤切。 用户办这件事要经过几步,每一步切成一条。“在线简历”切成:选一个简历模板;填上自己的经历和技能;拿到一个地址发给面试官。三条各自能演示。
按情境切。 同一个用户,第一次用和第十次用是两种情境,电脑上用和手机上用是两种情境。“填上自己的经历”切成:第一次打开时,模板里已经有示例内容告诉我该填什么;回来修改时,直接点到要修改的那一块。
按人切。 同一个功能,不同的人用法不一样。“拿到一个地址”对求职者来说是发邮件,对做视频的人来说是贴到平台简介里,对后者,地址要短、要好记。切成两条,优先级可以不同。
切完之后给每条标优先级。标的时候问自己:第一版没有这一条,用户能不能把那件事办成?办不成的是 P1,办得成但明显更费劲的是 P2,几乎察觉不到的是 P3。这个问题第 8 章还会再用一次,用来决定第一版做什么。
切小还有一个好处,在和 AI 协作的时候才看得出来。一条小故事交给 AI,它做完你能马上检查对不对;一条大故事交给它,它要做一整天,你检查的时候已经分不清哪里是它理解错了、哪里是它做错了。第 16 章讲“每轮只聊一件事”,那件事的大小,就是一条切好的故事。
用户故事里不写什么
有三样东西,写用户故事的时候要忍住不写。
不写技术。 不写用什么框架、数据存在哪里、调用什么接口。这些是技术方案的内容,第 12 章和第 13 章再谈。写进用户故事,会把 AI 的注意力引到技术上,它会围绕你指定的技术去做,而那个技术可能根本不是最合适的。
不写界面细节。 不写按钮放在右上角、颜色用蓝色、字号多大。用户故事只说用户要办成什么事,界面长什么样是第 9 章到第 11 章的事。现在写下来的界面细节,到画原型的时候十有八九会修改,修改一次就要回来修改一次故事。
不写做的顺序。 “先做登录,再做编辑器,最后做分享”,这是做的顺序,第 15 章把文件交给 AI 时再定。故事之间只用优先级表达轻重。
忍住不写这三样,用户故事会短得让你不放心。这是正常的。一条好的用户故事就是两三行,剩下的内容各有各的地方。
用词上还有一条,第 11 章会展开:故事里的词要用用户自己会说出口的话。用户说“我的主页”,就写“主页”,别写“站点”“profile”;用户说“卡片”,就写“卡片”,别写“组件”“widget”。这些词以后会直接出现在界面上,从故事这一步就用对,后面省很多事。
做成什么样才算完成:假如、当、那么
用户故事说清了“要什么”,还要说清“做成什么样才算做完了”。这件事用三句话来写:假如处于某种前提,当用户做了某个动作,那么他看到某个结果。
拿 Bentoly 现在已经有的功能来示范。
- 假如我已经登录、也已经建好了主页,当我点编辑器右上角的“分享”按钮,那么我看到“链接已复制”的提示,剪贴板里是我的主页地址。
- 假如朋友拿到了这个地址,当他在浏览器里打开,那么他看到我的主页,和我在预览里看到的一样,页面上没有编辑按钮。
- 假如有人拿到的地址里用户名不存在,当他在浏览器里打开,那么他看到“页面不存在”和一个“返回首页”的按钮。
这三句里只有用户看得到的东西:按钮、提示、页面、地址。没有“调用接口”“写入数据库”“读取路由参数”。这是故意的。验收标准写的是用户的视角,你照着它去检查产品,不需要懂代码;AI 照着它去写测试,也不会被你的技术猜测带到别的地方去。你写“调用接口返回 200”,它就只测试接口;你写“朋友打开能看到主页”,它就得把整条路走通。
这种写法在行业里叫 Given-When-Then,三个英文词分别对应假如、当、那么。你不用记英文,记住“前提、动作、看到什么”三段就行。
每条 P1 用户故事至少配两三句这样的验收场景:一句写顺利的情况,一两句写不顺利的情况。顺利的那句谁都会写,不顺利的那几句才难写。
不顺利的情况从四个方向找:失败了,中断了,没有权限,没有数据。拿“分享主页”这条故事来过一遍:
- 失败了:假如网络断了,当我点“分享”,那么我看到什么?是“复制失败,请稍后再试”,还是什么都没有?
- 中断了:假如我改到一半关掉了浏览器,当我下次打开,那么我看到的是改到一半的内容,还是上一次保存的内容?
- 没有权限:假如我没有登录,当我打开编辑器,那么我看到登录页,还是能先编辑、保存时再要求登录?
- 没有数据:假如我选了空白画布什么都没放,当朋友打开我的地址,那么他看到一张空白页,还是看到“这个人还没有放任何内容”?
每个问题都要有一个答案,答案就是设计。答不出来的,说明这一块还没想清楚,先想完再往下。这四个方向是我给 Agent 画业务流程时必须包含的分支,写在项目手册里,下一节会用到。
画出用户怎么用,包括出错和没有数据
用户故事是一条一条的,用户用产品是一步一步的。几条故事写完,你得把它们连成一条路,看看这条路走不走得通。这件事用流程图来做。
流程图要从用户第一次打开画起,画到他把那件事办成为止。每一步写两样东西:用户看到什么,用户做什么。然后,在每个可能出岔子的地方画一条分支:失败了怎么办,中途退出了怎么办,没有权限怎么办,什么数据都没有怎么办。
下面这张是我照着 Bentoly 现在的样子画的。图是用 mermaid 写的,这是一种用文字描述图形的写法,第 9 章讲。
flowchart TD
A[打开网站] --> B{已登录吗}
B -- 没登录 --> C[登录页<br/>用户看到:登录表单,可切换到注册]
C -- 注册 --> C1[注册成功<br/>用户看到:欢迎提示和自己的主页地址]
C1 --> D
C -- 登录 --> D{云端有主页吗}
B -- 已登录 --> D
D -- 没有 --> E[场景选择页<br/>用户看到:六种场景和一个空白画布,右侧实时预览]
E --> F[点“开始创建”<br/>用户看到:欢迎对话框,说明怎么开始编辑]
D -- 有 --> G
F --> G[编辑器<br/>用户看到:自己的主页,可点卡片编辑、添加模块、换主题]
G --> H[每次改动约一秒后自动保存]
H --> H1{保存到云端成功吗}
H1 -- 成功 --> G
H1 -- 失败 --> H2[只保存在本机浏览器里<br/>用户看到:没有任何提示]
G --> I[点“预览”<br/>用户看到:访客视角的页面,可返回编辑]
G --> J[点“分享”<br/>用户看到:“链接已复制”]
J --> K[朋友打开地址]
K --> L{这个用户名存在吗}
L -- 存在 --> M[公开页<br/>朋友看到:主页,没有编辑按钮]
L -- 不存在 --> N[“页面不存在”<br/>朋友看到:说明文字和“返回首页”按钮]
G --> O[点“重置”<br/>用户看到:确认对话框,提醒所有更改会丢失]
四个方向里,这张图画了三种:没有权限(没登录就去登录页)、失败(保存到云端失败)和没有数据(云端还没有主页、用户名不存在)。
画这张图的时候,有一个分支让我停了一下:云端保存失败那一条。我去看了代码:每次改动先保存进本机浏览器,再上传到云端;上传到云端失败时,程序只在浏览器的控制台里记了一行错误,界面上什么都不显示。用户继续编辑,以为都保存好了,换一台电脑打开,主页还是旧的。仓库里的待办清单上确实有一条“保存失败提示”,标为待完成。这就是异常分支没有画出来的后果:没有人在设计的时候问过“保存失败了用户看到什么”,于是 AI 在写代码的时候随手决定了“什么都不显示”。
你画流程图的目的,就是在动手之前把这些岔路都走一遍。每条岔路上都要能回答“用户看到什么、能做什么”。回答不了的,要么补上设计,要么明确写“这一版不处理,用户看到某某提示”。不能空着,空着就是交给 AI 随手决定。
让 AI 起草,你来确认
用户故事和流程图都可以让 AI 起草。在阿布的项目手册里,这两步就是由 Agent 根据我的一句话需求起草,起草完交给我确认,确认之后才能往下做概念对照表(第 11 章讲)和功能清单(第 8 章讲),再往下才是技术方案。顺序不能倒过来:技术方案阶段不允许新增界面元素,确实需要新增的,回到用户故事这一步补上。
让 AI 起草的好处是快,它能在一分钟内给你十条故事和一张流程图。坏处是它起草的东西看起来太像样了,你很容易一路点头。所以确认的时候要带着几个问题读:
- 每条故事的角色,是不是我说的那类人?它有没有悄悄加进我没提过的角色?
- 每条故事的价值,是不是我真的要的?还是它从别的产品那里推断的?
- 流程图里的分支,是不是把失败、中断、没数据都画了?每个分支上是不是都写了用户看到什么?
- 有没有哪条故事,我读完说不出“这条做完我能给人演示什么”?
确认之前还有一个动作:让 AI 把它起草的故事用它自己的话复述一遍,顺便说出它对每一条的理解里有哪些是它推断的、你没有明说的。推断的部分就是最容易出分歧的部分。它说“我理解‘分享’是复制一个链接”,而你心里想的是生成一张图片,这一句就把分歧暴露出来了,这时候修改一个词就行;等它把复制链接做完了你再发现,要修改的就是一个功能。
读完之后,把你的修改告诉它,让它修改完再给你看一遍,直到你能把每一条都复述出来。然后在文件里记一行“某年某月某日已确认”。这一行很重要,往后 AI 做任何事,你都可以拿这一版对照:做出来的东西,能不能指到这些故事里的某一条。指不到的,就是多做的。
案例
Bentoly 的用户故事。 下面几条是我按它现在已经做出来的功能反过来写的示范,供你对照格式用。
- P1:作为正在找工作的设计师,我想要选一个“作品集”模板、换上自己的作品和介绍,以便一个下午就能有一个能发给面试官的页面。
- 假如我是第一次登录,当我在场景选择页点“作品集”再点“开始创建”,那么我看到一个已经排好三个作品位的页面和一段使用说明。
- 假如我点了某张卡片,当我修改了标题和链接,那么页面上立刻变成新的内容,一秒后自动保存。
- P1:作为已经建好主页的人,我想要一个地址发给别人,以便对方不用登录就能看到我的页面。
- 假如我已登录,当我点“分享”,那么我看到“链接已复制”。
- 假如对方拿到了这个地址,当他在浏览器里打开,那么他看到和我预览里一样的页面,上面没有编辑按钮。
- P2:作为不想用模板的人,我想要从一张空白画布开始,以便页面完全按我自己的想法排。
- 假如我在场景选择页,当我选了“从空白创建”,那么我看到一个只有个人资料卡片、没有其他模块的页面。
给 AI 的模板
下面是用户故事和业务流程的精简模板。完整版在模板仓库 01-方向/templates/product-brief.md 的第 1 节和第 2 节,那份文件后面还有概念对照表、功能清单、调研和技术方案,第 8 章和第 11 章会用到。
# 【功能名】· 用户故事与流程
## 1. 用户故事
<!--
每条写:谁、在什么情境下、想完成什么、做完的标志。
每条带优先级 P1 / P2 / P3,并且能单独演示。
验收场景用“假如 / 当 / 那么”写,只写用户看得到的东西,不写任何实现细节。
需求有两种以上合理的理解时,把几种理解都列出来,请我选。
-->
### P1-1 【一句话标题,用用户的话说】
作为【谁】,在【什么情境下】,我想要【完成什么】,以便【得到什么价值】。
- 假如【前提】,当【用户做了什么】,那么【用户看到什么】。
- 假如【前提】,当【用户做了什么】,那么【用户看到什么】。
### P2-1 【标题】
【同上】
## 2. 业务流程
<!--
用 mermaid 画。必须包含异常分支:失败、中断、没有权限、没有数据。
每一步写明用户看到什么、做什么。
-->
```mermaid
flowchart TD
A[用户【做什么】] --> B{【判断条件】}
B -- 是 --> C[【下一步】<br/>用户看到:【界面上的样子】]
B -- 否 --> D[【另一条路】<br/>用户看到:【界面上的样子】]
C --> E{操作成功吗}
E -- 成功 --> F[【结果】<br/>用户看到:【界面上的样子】]
E -- 失败 --> G[【失败时的表现】<br/>用户看到:【原因和下一步能做什么】]
E -- 用户中途取消 --> H[【回到哪里】]
```
> 用户确认(第 1、2 节):【YYYY-MM-DD,用户原话】
交给 AI 的时候,连同上一章整理出来的那段问题陈述一起给它,再加一句话:“按这个模板起草,起草完先别做任何实现,等我确认。”
专业上叫什么
- User Story(用户故事):“作为某人,我想要某事,以便某价值”这个格式出自 2001 年前后 Connextra 公司的实践,Mike Cohn 在《User Stories Applied》(2004)里把它推广开。
- Given-When-Then:本章“假如、当、那么”的写法,Dan North 在提出行为驱动开发(BDD)时定下的验收场景格式,2006 年前后。
- INVEST:Bill Wake 提出的检查一条用户故事好不好的六个标准,独立、可协商、有价值、可估算、够小、可测试。本章“能单独演示”对应其中的“独立”和“可测试”。