敏捷开发用户故事系列之八:剖析用户故事描述语法(兼谈不同种类故事的语法)

这是敏捷开发用户故事系列的第八篇。( 栏目目录)
本文内容来自火星人团队对火星人产品中300个用户故事编写后总结的经验和成果,欢迎致力于敏捷开发而又对用户故事感到困惑的开发者参与讨论。
本篇文章尤其适合参加MPD专场“用户故事颗粒度、分类及组织结构”的学员,及参加火星人敏捷开发产品培训的学员。
用户故事中,最有名的就是三段式语法了:“作为一个……(角色),可以……(功能),以便……(客户价值)。”
然而这种语法用于描述用户的业务操作比较方便,但若用于描述非功能性需求(包含重构、缺陷等),或用于描述对功能的增强,则有点力不从心。
让我们来剖析一下用户故事语法,并尝试写一下其他类型故事的语法。

分析

传统用户故事的语法为何得以成功流传10年而没有发生变化?

“因为他们是大师发明的。”

错,因为发明了这个语法,他们才成为大师的,这是因果倒置。

真正的原因是,这个语法很好地表明了需求的三个最重要的要素:角色,功能,客户价值。

角色

为什么要角色?

1. 有利于开发人员理解场景。

普通用户/管理员,存款客户/银行职员,……这些区别,令开发人员更容易理解产品的用途、风格、操作人员的熟练程度、操作习惯等。

2. 有利于找特定的用户核实

无论是产品的潜在用户调研,还是项目中与客户核实需求,如果有一个“角色”字段,都令沟通工作可以与适当的角色地进行,完成的产品自然也就令这些角色的人员满意。

功能(标题)

功能是最好理解的,就是程序员原来写的那种功能的名字,或称为标题。

不过,要放到这种语法里边,还是要动点脑筋的。

1. 主语-谓语原则

比如:(在某个用户管理系统中)“显示所有用户”,就不是一个好功能,为什么呢?把它套到用户故事语法中:

作为一个系统管理员,可以显示所有用户,以便……。

是不是感觉有点别扭?对,应该用“查看所有用户”,会更好一些。

作为一个系统管理员,可以查看所有用户,以便……。好多了。

可是,难道所有用户故事的名字都要和语法中的功能相同吗?不能写一个名为“显示所有用户”,但内容是“作为一个……,可以查看所有用户,以便……。“的故事?

能,但不要这样写,因为这违反了DRY原则。

DRY原则就是Don't Repeat Yourself原则,一件事情不要做两遍,尤其是这种本来就差不多、很容易混淆的事情。

所以,好的功能是以用户为主语的一个谓语。

2. 动宾词组原则

如果连续有用户的新建、删除、编辑、查看,是否可以只写”新建“”删除“?

这是在一次培训中大家实际讨论到的问题。

理论上说在这种场景中可以(有一些小问题),但是在其他时候会遇到大问题。

小问题:”查看“往往分为”查看所有用户Index“和”查看单个用户详情Details“两种,不写宾语不容易区分。

大问题:在故事板、燃尽图、我的个人中心等地方,如果凑巧一个故事需要单独存在的时候,失去了动作的宾语,会出现多个”新建“”删除“故事,容易混淆,不如”新建用户“”删除用户“来得好。

火星人在开发过程中尝试了各种方案,最后最佳结论是:

故事标题=功能;角色-功能是主语-谓语关系;功能本身是动宾词组。

用户价值

用户价值看似简单,其实很难写。

请看:作为一个管理员,可以查看所有用户,以便了解系统中有哪些用户。

看上去还不错,对吧?但是如果这个系统是CSDN博客,里边有600万注册用户,这个管理员为什么要查看所有用户?他怎么才能查看所有用户?如果这个系统是QQ,又会如何?

所以一个管理员,不会无缘无故查看所有用户。但是,也不能不查看用户(否则无法查看详情、删除、申诉、找回密码、禁言……),但是,要为管理员找到一个合理的理由,并以合理的方式查看某种用户,才是正确的故事。

实际案例剖析:火星人中新建用户

”作为一个管理员,可以新建用户,以便在系统中新建一个用户。“

好像可以,但又有点像废话。怎么办?

在亲自编写了300个用户故事后,我们发现可以尝试这样:

1. 尝试找到功能的现实用意,然后写出不同于功能的用户价值。

”作为一个管理员,可以新建用户,以便将特定用户添加到火星人系统中。“

不管汤、药如何,读起来顺嘴一些了。

但如果觉得还不够好,请尝试2。

2. 对顽固的不好描述的用户故事,尝试添加一些形容词、副词、壮语,用以描述这种操作的核心价值。

什么叫核心价值?有些操作希望”方便“”快捷“,另外一些则需要”安全“”一致“,这就是核心价值。

”作为一个管理员,可以新建用户,以便快捷地将特定用户添加到火星人系统中。“

恩,好像可以了。但是……如果一个管理员,要一个一个在弹出窗口中新建用户,保存,再新建,再保存……这个功能可能挺快捷,但对最终业务而言,如果有1000个用户要添加,实在谈不上快捷。

所以,请看3。

3. 如果感觉用户故事无法满足核心价值,请尝试改进故事,乃至换一个新故事。

”作为一个管理员,可以批量创建用户,以便快捷地导入已经有的用户数据。“

批量创建比创建快多了,每行一个用户,用逗号分隔用户名、邮箱……可是出了错怎么办?

弹出”输入的数据不符合要求,请检查格式是否正确。“

但如果有1000行,该怎么办?额……请看4。

4. 请验证改进后的用户故事能达成核心价值。

既然要快捷,除了错也应该迅速定位。

这样吧:所有识别成功的用户先暂存起来,所有不成功的行,则留在屏幕上(最多也就是几行),修改后再次识别,直到全部成功;确认后开始批量创建。

这个过程不用写在故事语法里边,因为没地方放。但要写在需求详情/测试用例里边。

好了,这就是火星人产品中”批量创建用户“的辗转经历。

不同种类故事的语法

让我们来尝试为其他种类的故事(非功能性需求)分别编制一套语法。首先解决两个问题:

1. 这种故事有哪些最重要的要素?

2. 如何编写才能突出这些要素?

在编写了300多个用户故事后,火星人团队摸索到了一套自己的编写语法,并预置在火星人产品中(请在8月中旬关注本博客,了解在线体验系统的信息)。

在看具体示例之前,先写一下最后的总结,方便大家理解我们为何识别了这些要素。

语法总结:

1. 角色多数时候是必需的

增强、重构、Bug……都有其受益者或受害者,若没有角色字段,很难站在真是位置上猜想其真实需求,也很难找人核实、询问优先程度。

2. 客户价值(或潜在损失)多数时候是必须的

若不能识别客户价值(或潜在损失),就不能知道增强、重构后是否达到了商业效果,或Bug修正后是否避免了潜在损失。

3. 原来“功能”的位置各不相同。

火星人中的几个实例

由于未必了解这些故事的背景,读者可能不会很清晰地判断故事的好坏,但请重点留意语法格式的作用。

增强:突出显示本次 / 上次 / 下次意向表 (增强一个操作)
实现后 作为 一个产品经理, 可以 查看意向表 ,突出地看到本次和上次迭代的意向 表, 以便 连贯地思考本次迭代的需求规划。
在这个实例中,“实现后,作为一个……(角色),可以在……(原功能)时,……(超出的功能),以便……(超出的价值)。”这一语法突出了实现前后的功能差异。(仅限于对功能的增强描述)
增强类型中,一般会暗含一个被增强的功能,但描述内容则是超出的功能和超出的价值。
重构:重构界面及 ViewModel
实现前 ,原来的中间为树两侧为迭代的展示方式较为占用空间,树的高度太大导致难以完整看到; 实现后 ,以故事树为主体配合左侧的当前迭代故事,查看和操作更加快捷。
在这个实例中,“重构前,……;重构后,……”的语法对比了重构前后的差异,这种差异必须面向用户进行描述,以便产品经理能正确理解和排序。
缺陷:在加入故事时产品按钮不刷新
作为一个 产品经理, 加入或挪出故事 ,顶端的产品按钮上人天数据不刷新, 导致 计划时对各产品的总量和比重的错误判断。
在这个实例中,“作为一个……(角色),在……(功能)时,……(现象),导致……(潜在损失)”的语法表达了在何时,会出现何种现象,导致何种业务问题。有些缺陷发生时“现象”很不明显(比如数据不刷新),因此必须描述导致的业务问题以便理解问题的实质。
债务:产品 ID 硬编码
当前 链接中的产品 ID 是硬编码的(直接访问火星人), 部署到实际环境中 将导致 链接失效。
在这个实例中,“当前……(当前的临时实现方法),在……(未来某种情况下)时,将……(可能出现的现象),导致……(潜在的损失)。”的语法表达了当前的何种技术原因,在何时,将会发生何种问题,并导致何种潜在的损失。

你可能感兴趣的:(工作,qq,敏捷开发,测试,产品,申诉)