SAFe之故事(Story)

如题所述

第1个回答  2022-07-25

故事 是用用户语言编写的一小块所需功能的简短描述。 敏捷团队 实现的是系统功能的小的、垂直的切片,其大小可以在单个 迭代 中完成。

故事是敏捷中用来定义系统行为的主要工件。它们是对功能的简短描述,通常从用户的角度出发,用用户的语言写成。每一个故事的目的都是为了实现系统行为的一个小的、垂直的片断,以支持增量开发。

故事提供了足够的信息,让业务人员和技术人员都能理解其意图。故事的细节将被推迟到故事准备实施之前才讨论。通过验收标准和验收测试,故事变得更加具体,有助于确保系统质量。

用户故事(User stories)将功能直接交付给最终用户。使能故事(Enabler stories)为支持探索、架构、基础设施和合规性所需的工作项带来了可见性。

SAFe的 需求模型 描述了工件的四层结构,这些工件概述了功能系统的行为: 史诗(Epic) , 能力(Capability) , 特性(Feature) 和故事(Story)。他们共同描述了创建解决方案预期行为的所有工作。但详细的实施工作是通过故事来描述的,这些故事构成了 团队Backlog 。大多数故事来自于“ Program Backlog” 中的业务和使能特性(Feature),部分故事来自于团队识别的工作。

每个故事都是一个小的、独立的行为,可以逐步实现,并为用户或 解决方案(Solution) 提供一些价值。它是功能的垂直切片,以确保每次迭代都能带来新的价值。故事要拆分得相对较小,必须能在一次迭代中完成(参见拆分故事部分)。

通常情况下,故事会先写在索引卡或便签上。索引卡的物理性质在团队、故事和用户之间建立了一种有形的关系:它有助于让整个团队参与到故事编写中来。便签纸还提供了其他的好处:它们有助于将工作可视化,并且可以很容易地放在墙上或桌子上,按顺序重新排列,甚至在必要时传递。故事可以让人们更好地了解工作的范围和进度:

虽然任何人都可以写故事,但批准它们进入团队待办列表并接受到系统基线中是 产品负责人 的责任。当然,便利贴并不能很好地在整个 企业 中扩展,所以故事通常会迅速转移到敏捷生命周期管理(ALM,Agile lifecycle management)工具中。

在SAFe中,有两种类型的故事,即用户故事和使能故事,如下所述。

如图1所示,故事通常是由业务和使能特性的拆分来驱动的。

用户故事是表达所需功能的主要方法。它们在很大程度上取代了传统的需求说明书。(然而,在某些情况下,它们可以用来解释和开发系统行为,这些行为随后被记录下来,以支持合规性、可追溯性或其他需求。)

因为它们关注的是用户感兴趣的主题,而不是系统,所以用户故事是以价值为中心的。为了支持这一点,推荐的表达形式是“用户声音”的形式,如下所示:

通过使用这种形式,引导团队了解谁在使用系统,他们在用系统做什么,以及他们为什么这样做。经常使用“用户声音”的形式往往会提高团队的领域能力(domain competence);他们会更好地理解用户的真实业务需求。图2提供了一个示例。

“用户画像(Personas)”描述了具有代表性的用户的具体特征,可以帮助团队更好地理解他们的终端用户。 图2中骑手角色的示例可以是一个追求刺激的“Jane”和一个胆小的骑手“Bob”。然后,故事说明将引用这些角色(作为Jane,我希望…)。

虽然用户故事语音很常见,但并不是每个系统都会与终端用户进行交互。有时“用户(user)”是一个设备(如打印机)或一个系统(如交易服务器)。在这些情况下,故事可以采用图3所示的形式。

团队可能需要开发系统结构或基础设施,以实现一些用户故事或系统的支持组件。在这种情况下,故事可能不会直接接触任何终端用户。这些是使能故事,它们支持探索、架构或基础设施。使能故事可以用技术而不是以用户为中心的语言来表达,如图4所示。

还有许多其他类型的使能故事,包括:

使能故事和用户故事一样,通常是通过展示所获得的知识、制作的工件、或用户界面、打桩或模拟来展示。

好的故事需要多个视角的观点。在敏捷中,整个团队(产品负责人、开发人员和测试人员)对要构建的内容有一个共同的理解,以减少返工并提高吞吐量。团队使用 行为驱动开发 (BDD)进行协作,定义详细的验收测试,明确描述每个故事。好的故事需要多角度的思考:

协同编写故事可以确保所有的观点都得到考虑,并且每个人都对故事的行为达成共识,其结果体现在故事的描述、验收标准和验收测试中。验收测试使用系统的领域语言(system’s domain language)与 行为驱动开发 (BDD)来编写。然后,BDD测试将自动执行并持续运行,以保持 内建质量 。BDD测试是根据系统需求(故事)编写的,因此可以作为系统行为的权威性声明(definitive statement),取代基于文档的功能详细说明(document-based specifications)。

Ron Jeffries,XP的发明者之一,被认为是首先提出了描述故事的3C方法:

敏捷团队通常以业务可读的特定领域语言(domain-specific language)自动执行验收测试。自动化创建了一个可执行的规范来验证和核实解决方案。自动化还提供了对系统进行快速回归测试的能力,从而增强了 持续集成 ,重构和维护的能力。

由 Bill Wake [1]开发的 INVEST 模型描述了良好用户故事的特征:

敏捷团队使用故事点和“估算扑克”来估算他们的工作[1,2]。故事点是一个单独的数字,它代表了一组特性的组合:

故事点是相对的,它与任何具体的衡量单位无关。每个故事的大小(工作量)都是相对于最小的故事来估算的,最小的故事被赋予“1”的大小。 应用一个修正后的斐波那契序列(1,2,3,5,8,13,20,40,100),以反映估算中固有的不确定性,特别是大数(如20,40,100)[2]。

敏捷团队经常使用“ 估算扑克 ”,它结合了专家意见(expert opinion),类比(analogy)和分解(disaggregation)来创建快速但可靠的估算。分解是指将故事或特性分割成更小的,更容易估算的部分。

(请注意,还有一些其他的方法也在使用。)估算扑克的规则是:

进行一些初步设计讨论是合适的。然而,在设计讨论上花费太多时间往往是浪费精力。估算扑克的真正价值在于就一个故事的范围达成一致。这也是一种乐趣!

团队在一次迭代中的速率等于满足完成定义(DoD)的所有已完成故事的故事点数之和。随着团队的不断合作,他们的平均速率(每次迭代完成的故事点)会变得可靠和可预测。可预测的速率有助于制定计划,并有助于限制在制品(WIP),因为团队承担的故事数量不会超过其历史速度所允许的范围。这个衡量标准也被用来估算交付史诗(epics)、特性(features)、能力(capabilities)和使能故事(enablers)所需的时间,这些时间也可以使用故事点进行预测。

容量是指团队速率中实际可用于任何特定迭代的部分。假期、培训和其他事件会使团队成员在迭代的某些部分无法为迭代的目标做出贡献。这就降低了该团队在该迭代中的最大潜在速率。例如,一个平均每迭代交付40点的团队,如果一个团队成员休假一周,他们的最大速率就会调整到36点。提前知道这一点,团队在迭代计划时就只承诺最大36个故事点。这也有助于在PI计划期间预测PI中每个迭代的实际可用容量,从而使团队在构建PI目标时不会过度承诺。

在标准的Scrum中,每个团队的故事点估算以及由此产生的速率是一个团队内部的、独立的事务。从规模化敏捷的角度来看,当各个团队之间的速率的基准分歧很大时,将很难预测更大的史诗(Epic)和特性(Feature)的故事点大小。 为了克服这个问题,SAFe团队最初会校准一个起始故事点基准,在这个基准上,所有团队的故事点定义大致相同。不需要重新校准团队估算或者速率。在启动新的 敏捷发布列车 时,会进行一次校准。

标准化 的故事点提供了一种方法,可以让故事和速率达到一个约定的起始基准,如下所示:

示例 :假设一个6人团队,由3个开发人员,2个测试人员和1个PO组成,没有请假或节假日,那么估算的初始速率=5×8点=40点/迭代。(注:如果其中一个开发人员和测试人员兼职Scrum Master,可能需要将其调低一些)。

这样一来,各团队的故事点就有了一定的可比性。管理层可以更好地理解一个故事点的成本,并能更准确地确定一个即将到来的特性(Feature)或史诗(Epic)的成本。

虽然随着时间的推移,团队会倾向于提高他们的速率,这是件好事,但实际上,这个数字往往保持稳定。一个团队的速率受团队规模和技术环境变化的影响远远大于受生产力变化的影响。

较小的故事会带来更快、更可靠的实施,因为小的条目在任何系统中流转的速度更快、可变性更小、风险更低。因此,把较大的故事拆分成较小的故事是每个敏捷团队的必备技能。这既是增量发展的艺术,也是科学。Leffingwell的《Agile Software Requirements》[1]中介绍了十种拆分故事的方法。以下是对这些技术的总结:

图6展示了一个按用例场景拆分的示例:

正如 SAFe需求模型 一文中所描述的,该框架应用了一系列的工件和联系,以精益和敏捷的方式管理复杂系统的定义和测试。图7说明了故事在SAFe全局中的作用。

在规模化敏捷中,故事(Story)通常(但并不总是)由新特性(Feature)创建。而每个故事都有验收测试,也可能有单元测试。单元测试主要是为了确保故事的技术实现是正确的。同时,这也是测试自动化的一个关键起点,因为单元测试很容易实现自动化,这在 测试驱动开发 (TDD)一文中有所描述。

注:图7使用统一建模语言(UML)符号来表示对象之间的关系:零对多(0...*),一对多(1...*),一对一(1),以此类推。

Last update: 17 December 2019

相似回答
大家正在搜