[读书笔记] 改善用户故事的 50 个点子

DDD · abbey · 于 发布 · 799 次阅读
351

引子

《Specification by Example》一书的作者Gojko Adzic,同时还参与了“Fifty Quick Ideas”系列的著书,其中包括《Fifty Quick Ideas to Improve Your User Stories》、《Fifty Quick Ideas To Improve Your
User Stories
》和《Fifty Quick Ideas To Improve Your Retrospectives》。它们和我钟爱的《Parallel Programming in the .NET Framework》一样,都是100多页的“马桶读物”,价值则是洗发水说明书等远非能及的。

最近有幸拜读了武可先生《[读书笔记] 五十个改善测试的点子》,我便愈加渴望读到这个系列。终于,在五一期间,我如饥似渴地读完了《Fifty Quick Ideas to Improve Your User Stories》(以下简称Improve User Story)。现在,就一起来看看这50个闪光的点子吧。

为什么一定要讲好故事

纵观当下的各种软件开发方法,几乎无一例外地都是从用例入手。因为这种由动态行为逐步转入静态模型的方式,是探究用户需求和系统行为的重要途径,也是从OOA向OOD过渡的自然渠道。一方面,这种在特定场景下、剧本式的描述,对客户来说有很强的角色带入感,能加深其对系统运作过程的理解;另一方面,具体详尽的流程描述,以及各种分支情况和异常,也给开发团队理解业务流程和逻辑、划分模块和子域等带来了很大的帮助。所以,“讲好故事”对于我们的开发,有着很好的引导和驱动作用。即使到了最后,这些故事还能作为系统验收的参考标准。

但是,用例究竟怎么写、写些什么内容、何时才算完成,都是实践中需要把握的问题。我曾经读过《编写有效用例》一书,但是还是会遇到那种动辄十几个分支的用例,尽管我们可以把它切分得更细、划得更小,使用迭代的方法逐步丰富其内容,但无论是前期撰写,还是后期理解与维护,其代价都是巨大的。

所以,写好故事是有难度的。

好故事的标准

关于标准问题,Gojko在《Specification by Example》中已经给出了很好的答案——Example四原则,他在Improve User Story一书中还将作进一步阐述:

  • Example总是明确具体的。
  • Example总是完整的。
  • Example总是现实的。
  • Example总是易于理解的。

Improve User Story的体例

每章都以一张生动的图片作为开头,随之用一些事例引出问题,再分析并给出解决方案,继而是以Key benifits讲出这样做的好处,最后以How to make it work结尾,带出实践的具体方法。节选其中一部分展示如下:

Tell stories, don't write them

User stories are often misunderstood as lightweight requirements, given by the business stakeholders to the delivery team. This misunderstanding leads to stories being collected in a task management tool, with a ton of detail written down by business representatives. Except in the very rare case where the business representative is also a technical expert and has a great vision for the product, this division of work prevents organisations from reaping the benefits of user stories.
... ...
Key benefits
Discussions allow business representatives not only to explain what they want, but also to ensure that the delivery team members understand this correctly. Misunderstandings between different roles are a major problem with any kind of hand-over. Explaining a story face to face prevents problems from falling through knowledge gaps.
... ...
How to make it work
There are several common reasons for writing down detailed stories. Most of these needs can be met without document hand-overs. Here are the most common excuses:
- When regulatory requirements or the political environment require formal sign-offs, written details serve as a record of what was approved.
- When different business stakeholders have to agree or approve plans, having something written to send out is useful. Geographically distributed organisations often have this need.
... ...

50个点子

Creating Stories 『创建故事』

  • Tell stories, don't write them

    故事不是预先写出来的,而是要通过语言交流慢慢讲出来的。

  • Don't worry too much about story format

    别太纠结描述故事的具体格式,BDD的三段式就很好。

  • Describe a behaviour change

    描述系统如何对用户行为产生影响、产生何样的影响,而不要局限于描述行为活动本身。溯根求源,才能更好地发掘并量化业务目标,准确回答“为什么要开发这个系统”的问题。

  • Describe the system change

    要描述系统在加入新的功能后因此产生的变化,如此才能更好地理解新近引入的概念和规则,对不同功能之间的依赖与耦合关系有更清楚的理解。

  • Approach stories as survivable experiments

    要视故事与客户的生存攸关,从业务价值的角度撰写故事。对故事不能一味求小、求细,要求在技术意义上的一个迭代周期内实现,而对其进行投资与回报的假设,这样才能实现与客户的共鸣,得到统一的认知和及时的反馈。

  • Watch out for generic roles

    即使是虚拟一个具体的用户角色,也甚过一个抽象的通用角色,要避免“As an user...”这样的描述。

  • Evaluate zone of control and sphere of influence

    正确地评估系统的控制区和影响范围,分清用户与系统的职责。

  • Put a ‘best before' date on stories

    要特别留意那些有『时限约束』的故事,给它们加上“要在某个时刻之前实现”的标签,使其尽早被纳入迭代的视野,从而可以避免临时抱佛脚,给团队增加不必要的压力。

Planning with stories 『做好计划』

  • Set deadlines for addressing major risks

    限定主要风险的截止日期,避免陶醉于小步的胜利(low-hanging fruit),而迷失了整个系统的方向和规划。

  • Use hierarchical backlogs

    把所有的故事根据不同的目的和功能,适当地进行分层和分组,而不要零散地堆砌在一起。这样不仅能给每一次的讨论限定一个语境,还能更有效地跟踪进度。

  • Group stories by impact

    学会使用Impact Mapping对故事分组,这是一个强大的可视化工具。

  • Create a user story map

    学会使用Story Map,将零散的、分层的故事串起来,形成完整的业务流程和发布计划。Story Map强调的,是水平方向若干环节之间的先后发生顺序关系。

  • Change behaviours using the CREATE funnel

    学会使用『CREATE』模式去描述行为变化。CREATE模拟了大脑决策的过程:Cue 感应并传递信号 → Reaction 条件反射 → Evaluation 代价评估 → Ability 决定可行与否 → Timing 决定即时与否 → Executing 执行决定。CREATE相比Story Map,强调的是水平方向每一个步骤应当具备的基本内容和彼此分工,因此CREATE模式的应用,更象是编制一份指南或者向导。

  • Set out global concerns at the start of a milestone

    在起步之初就要充分考虑诸如安全、日志、性能等具有全局性、横切性的需求,并依据FURPS+对其进行分类:功能性、可用性、可靠性、性能的、支持性等等。FURPS+具体内容请参见《UML和模式应用》 P42。作者使用了『milestone』表示每一个关键的业务目标,并以该目标为出发点、里程碑开始需求分析。

  • Prioritise according to stages of growth

    当面对关乎客户不同长短周期收益的各种需求时,如何进行权衡并决定优先顺序是一个让人挠头的问题。所以作者推荐参考《精益分析》中的方法,按“移情Empathy → 粘性Stickiness → 病毒性Virality → 营收Revenue → 规模化Scale”的阶梯式递进增长模式,排定各需求之间的先后次序。而我的理解,就是先设法聚集人气,产生一定收益后再设法扩大影响,聚集更多的用户,如此反复,最终形成规模性效应。由于各步骤之间存在紧密的依赖关系,因此要进行必要的风险评估,再针对性地对下一个步骤进行规划,并要征得所有利益相关者的一致同意。

  • Prioritise using purpose alignment

    这是一个被称为Moscow(Must have → Should have → Could have → Would like,紧迫性依次从强到弱)的分析工具,通过“是否关键性任务”和“有否市场主宰力”两个维度,把用户故事划入上述4个不同类别(Yes or No),从而确定其优先顺序。

  • Make a stakeholder chart

    这是类似Moscow模型的一个工具,但Moscow是从市场价值的角度进行划分,而Stakeholder Chart则是从利益相关者的角度,对系统中的各种角色进行分组,最后判断角色的重要性来确定谁的故事优先实现。只是这一次的维度换成了“谁更感兴趣”与“谁更有决策的权力”,由此产生Engage fully → Keep informed → Keep satisfied → Monitor四个角色组。

  • Name your milestones

    为你的迭代划定里程碑,才能做到有的放矢,不至于因此埋头苦干却不知所谓。这让我想起一句话:即便是无谓的虚荣,一个人也不能毫无追求。

  • Focus milestones on a limited number of user segments

    使用尽可能少量或有限的用户片段,避免引入过多的用户角色,以保证对业务目标的足够专注力。

Discussing stories 『讨论故事』

  • Use low-tech for story conversations

    不建议使用高科技含量的展示工具或者舒适的讨论环境, 使用简单的白板并且站着讨论就好,这样才不会让参与讨论者分心或过于懒散。

  • Imagine the demonstration

    什么样的演示是最棒的?既不是恶心的进度表,也不是TDD或者BDD方式展示的一系列测试场景,而是由客户亲自进行的、可以当作验收过程的演示,这才真正表示用户理解与接受与否。团队也要围绕“我们如何演示这个故事”来组织相关的实现和测试,并与客户在此问题上取得一致,使之明白业务价值的源头正是来自每一个这样的故事,并通过演示不断逼近最终的系统实现。

  • Diverge and merge for story discussions

    按最多四至五个人的规模,把团队分割成若干个小组,使用具体的事例进行讨论,之后再综合小组的讨论结果,消除歧义、淘劣择优、取得共识。这种先分再合的方式,可以有效激发团队成员的参与热情,发现更多的可能,避免在一棵树上吊死,或使团队成为某个人的一言堂,从而达成殊途同归的最终目的。

  • Involve all roles in the discussion

    大规模的全队讨论是不切实际的、代价昂贵的,很容易陷入一言堂之类的陷阱,让人感觉太过大动干戈。所以推荐用“三剑客”(由开发人员、测试人员、业务人员组成的小组)的方式展开讨论。当然,也不局限于这三人,DBA、收益分析师等角色也可以介入,以尽可能获得关于某个片段的周全考虑。

  • Measure alignment using feedback exercises

    讨论和对话不能无休无止,但何时才算结束呢?作者建议使用反馈练习来结束讨论。我的理解就是围绕故事中的一些边界条件,尝试用智力问答的方式,看是不是能在参与者之间就该条件下应该得到的结果取得一致。如果一致了,讨论结束,否则就继续讨论,直到彻底消除分歧。

  • Play the devil's advocate

    在讨论和对话过程中,有人唱红脸,就得有人唱白脸。所以始终要有一个人来扮演魔鬼的代言人,他总是要跳出来唱反调,说明故事中原定的场景没有必要这样或那样做,从而引发争论,激发团队从相反的视角去看待和思考问题。

  • Divide responsibility for defining stories

    要分清责任,别变相地让客户成为解决方案的提供者,而让团队退化成为编码工具。客户只需说清楚他要什么,而至于如何设计并实现则是团队的责任。(这个观点在实例化需求等书籍中已得到反复重申)

  • Split business and technical discussions

    划清业务与技术不同层面的讨论,别让技术实现的细节干扰甚至制约业务本身的需要。

  • Investigate value on multiple levels

    一个系统将牵涉到众多的利益相关者,因此必然也其各自不同的业务价值,所以无法一言以蔽之。这些价值围绕一个核心的业务目标,相互嵌套,形成洋葱式的不同层次,也是必然。而在实践中,可以从用户及其所属的组织如何获益作为起点,让同一利益的受益者们聚在一起讨论。有共同爱好才能产生共鸣。

  • Discuss sliding-scale measurements with QUPER

    这个主题与此前在《实例化需求》、《UML精粹》等书中提到的是一致的。就是对性能、响应时间等这些无法准确表述的需求引入了QUPER模型,从可用性、分化性、饱和性三个方面展开讨论。

Splitting stories 『切分故事』

  • Start with the outputs

    无论是改造既存的老系统,还是全新开始一个系统的开发,都要留心随着开发进程的推进,市场机遇也同时在流逝。所以应当摒弃细枝末节,从系统能提供的产出入手,明确“我们究竟需要什么?”,为整个开发划定一张蓝图和交付计划,进而选择如何组合现在的功能、改进现有流程等等,这样才能找到最关注的信息和需求。毕竟,我们的目的是获得系统产出,而不是关心应该给它喂什么进去。

  • Forget the walking skeleton – put it on crutches

    别重复造轮子!先利用一些现有的别人造的轮子作为支撑系统运行的“拐杖”,让系统的临时模型先运转起来,以获得及时的反馈,推动迭代交付。只有当这些借用的轮子不再适用时,特别是一些非常耗时的组件,再考虑自己去逐步实现并取代之。

  • Narrow down the customer segment

    抓住系统的主线,精简用户的片段。这和DDD中专注核心领域、BDD中的核心事例等等是一致的。

  • Split by examples of usefulness

    这一点仍旧是在面对体积庞大的故事时,可以设法理出其中的关键需求,然后根据其中一项需求,逐个筛选哪些技术方案对其有用,从而找出支持关键路径所需要的那些事例和技术支撑。所以,从某种意义上讲,这点和上一点是基本一致的。

  • Split by capacity

    这就象系统在不同规模上的试运行,由简入难,一步步进行尝试。至于划定规模的指标,可以是同时上线的用户数、能读写的文件大小、并发的峰值等等。

  • Start with dummy, then move to dynamic

    系统功能的实现,总是各种组件之间协作产生的结果。在这一点上,我的理解是把系统看作一台联合收割机。从外部看,输入的是一撮撮的稻穗,而产出是脱粒后一袋袋的稻谷。而在内部,收割组件的产出,是脱粒组件的输入;脱粒组件的产出,则是包装组件的输入。所以就象单元测试里的Mock与Stub一样,我们可以在刚开始实现某个组件时,可以对其输入选择“硬编码”的方式,硬塞给它需要的东西,而不是等候提供输入的组件实现。由此在分割故事上产生的影响,就是能以不同环节的输出对大故事进行切分。

  • Simplify outputs

    简化输出,只要输出能表达需求的核心内容即可。比如用户需要的是一份Excel格式的报告,但我们可以暂时以一些更简单些的平面文本或三块式的表格表示。类似的还有:先暂时不对信息加密,临时记住用户的登录名,为处于不同环节的利益关注者提供不同形式的输出等等。

  • Split learning from earning

    软件开发总会遭遇大量的未知数。这些未知,部分来自第三方系统、新的标准或组件。为了掌握这些未知领域的知识,我们需要不断地学习。这个学习和研究的过程总是耗时耗力的。所以我的理解是,把这种学习任务隔离起来并限定时间,从而既能达到隔离风险的目的,又能进一步明确对这部分内容的验收条件。这种隔离,变相地就把大故事切分为需要时间学习的(Learning Stories)和直接能收获的(Earning Stories),对前者不能操之过急,也不能太早放到交付计划里去,而对后者则是要及早实现。

  • Extract basic utility

    尽早实现系统的最小功能集、关键集,就象平时经常采用的命令行工具、脚本、数据提取与导入工具这样的。目的是通过人工介入、半自动化地实现系统的部分关键功能,从而尽早获得反馈,并通过人工干预发现各环节、各组件之间的矛盾与冲突。

  • When all else fails, slice the hamburger

    当上面所有的这些办法都尝试之后仍不能解决故事切分问题时,可以象汉堡一样把故事再进行切片。我的理解,是以业务流程的若干环节作为垂直方向,以同一业务环节中的不同方案选项为水平方向,把所有可能的技术选项放进这个表格,然后逐环节筛选最恰当的技术选型或者实现方式,就象自己制作一块合乎个人口味的汉堡一样,只挑自己喜欢的部分。期间每一次取舍,都是容易产生思想火花的地方。最后,作者在这里建议最多不要超过10层。

Managing Iterative Delivery 『管理迭代交付』

  • Don't push everything into stories

    不要把开发与交付环境准备工作等等这些没有客户参与的“伪故事”也放进用户故事里。

  • Budget instead of estimate

    用更量化的指标,比如最迟到何时交付、最多需要多少资金这样准确的值去界定交付目标,而别用还要多久这样估计、笼统的表述。

  • Avoid using numeric story sizes

    故事没有固定的尺寸与规格,所以要避免用数字标签式的方法去划分故事的大小,特别是对于一些周期较长的故事,这只会使团队误入歧途。建议的方法是先定义几个具有代表性的故事作参照物,用以衡量新故事的大小:太大、太小或者合适。

  • Estimate capacity based on rolling number of stories

    使用故事点数Story point的滚动平均值来估算交付量。而且这个均值只能在负责这一个迭代小块的团队内部使用,别将其扩散到团队之外。话说回来,这一小节讲的算是什么鬼,前面不才说别用这种数字式的尺寸标签吗?而且在上一小节的最后,作者还说尽量用故事的分析时间、数量这些指标来衡量这个交付量,而少用故事点数、速度,难道又是要因陋就简?

    Instead of using story points and velocity for capacity planning, try to manage capacity based on analysis time or number of stories.

  • Estimate capacity based on analysis time

    用分析故事所需的时间来衡量故事的复杂度、交付量的多少。可以用指定时长的分析或讨论时间作为一个小节,然后记录一个完整的故事需要多少个这样的小节才能完成讨论达成一致,最后以此来衡量故事的大小或要交付的量。

  • Pick impacts instead of prioritising stories

    不要尝试或习惯于对故事的优先顺序排座位,而应当侧重考虑和估算每个故事对获取业务价值产生的影响力是大是小。(别拿豆包不当干粮。)

  • Never say'no' – say'not now'

    对用户提出的要求,永远不要说“NO”,而应该记下来,并回答“NOT NOW”。你永远不知道用户提出的要求,究竟是一个潜在的、尚未发现的需求,或是因理解错误导致重构的可能原因。每次的交付,都基于这一次迭代前制定的计划。嗣后要就这些新增的东西是否纳入迭代、在何时纳入迭代达成一致,避免影响过度频繁地更改迭代计划。(好好好,顾客就是上帝,你说的我都会努力实现,但不一定是马上或者明天。)

  • Split UX improvements from consistency work

    提升用户体验的有关设计,从来都是让人头疼的,因为这玩意儿从来都是经验学的,就象审美一样,从没有一个完全适用于任何时代、任何人群的衡量尺度。所以如果将其纳入早期的交付计划,只会对开发造成更多困扰。所以把这些技术的、末端的、琐碎的东西,都当作影响交付的细枝末节暂时放在一边,转而围绕核心的、关键的功能交付付诸精力和时间。

  • Get end-users to opt in to large user interface changes

    大范围、起底式的UI重新设计,无论是对用户本身、还是对用户故事的组织,都是一大忌讳。由于这种改变,势必会影响用户的使用习惯,甚至影响流程本身。所以当万不得已出现这种情况时,一定要邀请最终的用户参与讨论,逐步展示这种UI的改变,并给出能令人信服的理由,逐步取得一致与认同。(这不就是冠冕堂皇地泡蘑菇吗?)

  • Check outcomes with real users

    作者给的图非常形象——厨师最好和食客面对面地交流,当面听取食客对菜品的意见。类比到软件开发领域,就是要让现实中的最终用户与开发团队一起,共同检查系统的输出是否符合本来的预期。(是骡子是马,拉出来遛遛。)

  • Throw stories away after they are delivered

    代码就是最好的文档,而不是过时的用户故事。这与《实例化需求》中阐述的观点是一致的,也是“活文档”的实质。所以故事交付了,就把它扔在一边吧,清晰的代码足矣。

读后感

书读完了,笔记也整理完了。回顾这个过程,读的时候很兴奋,读完了却怅然若失。因为这50个点子背后的道理非常浅显,却总是被我们一再忽视:抓住主线才能有效化繁为简,强调互动才能及早达成共识。

最后,附上我的思维导图笔记(图片上右键另存后可看大图)。

Mind Map for Improve Story


「软件匠艺社区」旨在传播匠艺精神,通过分享好的「工作方式」和「习惯」以帮助程序员更加快乐高效地编程。
本帖已被设为精华帖!
暂无回复。
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。