写点什么

Scrum 框架及其背后的原则(上)——Scrum 框架的伪代码描述

2011 年 4 月 07 日

Scrum 是应用最广泛的敏捷开发方法。同时,它的失败率却非常高,其创始人之一 Ken Schwaber 估计 75% 尝试 Scrum 的组织无法获取他们预期的效果 ( http://www.agilecollab.com/interview-with-ken-schwaber )。对此,通常的解释是“对 Scrum 框架的错误应用,和对其原则的错误把握。”Ken Scheaber 在“ Scrum Guide ”一文中对这两方面都提供了权威的阐述。本文的目的是在此基础上,提供更加明确的操作性的指导和检查工具。本文分成上下两个部分,分别讲述 scrum 框架本身和其背后的原则。

第一部分:Scrum 的框架

Scrum 并不是一个特定产品开发的流程或技术,而是一个容纳其它流程和技术的框架。作为一个迭代和增量的产品开发框架,Scrum 本身十分简单和明确。下面的一段伪代码,是对 Scrum 框架的完整表述。

复制代码
void run_scrum() {
const int Sprint_Length = 10;
int velocity = get_past_performance();
// Scrum 中的三个角色
Role team, product_owner, ScrumMaster;
// Scrum 中的制品
Product_Backlog product_backlog;
Sprint_Backlog sprint_backlog;
Burndown_Chart sprint_burndown_chart, release_burndown_chart;
Product_Increment product_increment;
// 开始项目的三个准备条件
setup_team(team);
define_Definition_of_Done(team, product_owner);
initial_project(&product_backlog ); // 标红的为输出参数,将带回值,下同
// 每一次 while 循环为一次迭代
while (!is_empty(product_backlog)) {
run_sprint_planning_meeting(product_backlog, velocity, &sprint_backlog);
// 每一次 for 循环为一个工作日
for(num_of_day = 1; num_of_day <= Sprint_Length; num_of_day ++){
run_daily_scrum_meeting(&sprint_burndown_chart);
do_development_activity(sprint_backlog, &product_increment);
}
run_sprint_review_meeting(product_backlog, product_increment);
run_retrospective_meeting();
update_product_backlog(&product_backlog, &release_burndown_chart);
update_velocity(&velocity);
}
}

这就是 Scrum 的完整框架,只有这些,很简单,我们下面将逐行解释。

复制代码
const int Sprint_Length = 10;
int velocity = get_past_performance();

Scrum 是一个迭代开发模型。每一个迭代周期,团队完成一部分产品需求,交付可工作的软件。在 Scrum 中,迭代被称为 sprint (本意为冲刺跑,一般不作翻译),典型的 sprint 长度是 1 到 4 周。值得强调的是,对于同一团队,sprint 的长度是固定不变的。

Sprint_Length – Sprint 长度:这里以 10 个工作日(两周)为例,const 常量修饰符,强调了其不可变性。

Velocity – 团队开发速率:也即每个 sprint 团队能完成多少量的用户需求,它是 Scrum 中计划和承诺的最重要依据。开发速率来源自过去实际产出结果,并在产品开发过程中不断修正。

复制代码
Role team, product_owner, ScrumMaster;

以上的实体定义是 Scrum 中的三个关键角色,在 Scrum 框架中也仅仅定义了这三个角色。

Team – 团队:团队负责产品交付,规模一般为 5~9 人,Scrum 强调团队的多功能(cross functional)和自组织。多功能指的是,团队应该整体具备各个职能所需的技能,如系统,开发和测试技能,同时也具备各个组件的技能如数据库设计、协议开发和 UI 设计等。团队的多功能是短迭代开发的基础,只有做到这一点,独立的团队才可能在一个 sprint 中交付对用户有意义的产品增量。自组织指,在目标清晰的前提下由团队自主决定完成目标的具体方法。

Product Owner – 产品负责人: 多直接称为 PO。PO 负责把握产品的方向,包括需求的收集、定义,优先级设定等。PO 通过这些活动以及和团队的合作,最终确保产品 ROI(return of investment, 投资回报)的最大化。

ScrumMaster: 一般不作中文翻译,ScrumMaster 并不直接负责产品交付,它向团队负责,确保团队按照 Scrum 的框架工作,具备良好的外部和内部工作环境,顺畅地交付产品,并不断的改进,提升交付的效率和质量。与传统意义上的管理者不同,ScrumMaster 更多是起服务、协调和引领的作用。如果注意观察会发现,在这段程序中,ScrumMaster 是一个定义,但从未使用的变量,这也正反映了 ScrumMaster 的协调和支持的作用。

复制代码
Product_Backlog product_backlog;
Sprint_Backlog sprint_backlog;
Burndown_Chart sprint_burndown_chart, release_burndown_chart;
Product_Increment product_increment;

上面的结构变量是 Scrum 中的核心制品,它们贯穿整个 Scrum 操作过程,分别是:

Product backlog – 产品待办事项:很多时候直接用英文表示,简称 PB,是一份用户需求列表。其中的每一项都是一个具体的端到端的用户需求,如“用户可以完成登录”等等。Scrum 产品开发过程就是,通过一系列的 sprint,每个 sprint 完成一部分“产品待办事项”,交付包含这些需求实现的产品增量,直至完成所有“产品待办事项”。Product backlog 的责任人是 Product Owner,它在产品开发的初期生成,并在开发过程中不断更新完善。

Sprint backlog – sprint 待办事项:是一个 sprint 中要完成的任务列表。其中的项目是为完成特定用户需求而要进行的设计、开发、集成、测试等具体任务,如“为模块 A 添加外部接口”等。完成 sprint backlog 中的所有任务,也意味着 sprint 开发任务的完成,对应的用户需求可以交付。Sprint backlog,在 spirnt 计划会议上生成,在开发过程中,可能会有所调整。

Sprint burndown chart – sprint 燃尽图:以坐标图表示团队在一个 sprint 中工作进展情况,横坐标是 sprint 已进行的实际天数,纵坐标是还剩余的任务需要的时间的总和。它直观的反应了 sprint 实际执行与计划的比较,以及团队离 sprint 的目标完成的距离。

Release burndown chart – 发布燃尽图:以坐标图表示当前版本的需求完成进展情况,横坐标是已经进行的 sprint 的个数,纵坐标是待完成的用户需求的多少。它直观的反应了产品需求的完成情况,以及团队离完成版本完全发布的距离。

Product increment – 产品增量:Scrum 要求每一个 sprint 结束都产生用户可用的软件,也被称着“潜在可交付的产品增量”(Potential shippable product increment, PSPI),事实上交付与否还要受用户习惯的约束。能否每个 sprint 生成满足质量定义的 PSPI 是 Scrum 执行效果的试金石。

复制代码
setup_team(Team);
define_Definition_of_Done(team, product_owner);
initial_project(&product_backlog );

上面代码中的三步操作是 Scrum 执行开始的准备条件。

Setup Team – 创建团队:创立和建设适合的团队是 Scrum 实施的第一步工作,团队应该满足上面定义的 Scrum 团队的基本属性,并形成自己的目标和愿景,理解 Scrum 工作模式。

Define Definition of Done – 定义完成标准:完成标准,是指一个用户需求完成应该满足什么样的标准。它是 Product Owner 和 团队之间的一个约定,有了这个约定,当团队说,这个需求完成了的时候,Product Owner 将明确知道这意味着什么,比如是否包含了针对这个需求的性能测试,或是否包含相应的用户使用手册等。在实际运用中,由于条件限制,团队在一开始可能无法做到 sprint 结果可交付,而会剩余一部分工作在交付前完成,如性能测试等,这一部分工作被称为“undone”的工作。完成标准在特定时间是固定的,但随着团队成熟度提高,团队应逐步扩展自己的完成标准,使其逼近向客户交付的条件,undone 的部分越来越少。

Initial Project – 启动项目:项目启动,是项目进入开发阶段前的一系列准备工作,如:项目目标的设定,项目初始需求的定义和澄清,工作量的估计,风险的识别,关键设计决策的产生,开发基础设施的选择和构建等。一般由客户(如果可能),PO,团队以及相关干系人共同参与项目启动。项目启动最重要的是输出一个初始 product backlog,它应该包含对其中条目的大小的估计和优先级别的设定。

上面三个操作的结果是,有了合适的 Scrum 团队,团队和 PO 之间就需求完成的标准达成一致的定义,并生成了一份初始的 product backlog。有了这三个条件便可以正式进入迭代开发了。

复制代码
While (!is_empty(product_backlog)) {
run_sprint_planning_meeting(product_backlog, velocity, &sprint_backlog);
……

每一次 while 循环代表一个 sprint 周期,直至 product backlog 中所有的需求被开发完成。

Run sprint planning meeting – 进行 sprint 计划会议: sprint 规划会议规划这个 sprint 目标和具体任务安排,它标志着一个 sprint 的开始。在 sprint 计划会议上要依次完成以下的内容:

  1. 团队决定在接下来的的 sprint 中要完成的用户需求,如过对需求存在疑问,团队应和 PO 进行澄清和确认。团队必须按照 PO 设定的 product backlog 的优先级别,从高到低选择,如因实现上的依赖关系,要调整需求选择的顺序,也需要和 PO 进行确认,以确保团队始终工作在最有价值的需求上。关于承诺多少需求,也并非取决于团队或专家的主观判断,而是根据 product backlog 中对每一个需求的大小估计,以及团队过去的实际开发速率(velocity),承诺相匹配数量的需求。
  2. 针对所选择需求的实现,进行简单和必要的沟通、分析。以确保第三步可以顺利的进行。
  3. 分别将每一个需求,分解成设计、开发和测试等任务。并估计每一个任务所需的工作量(通常以小时计)。

Sprint 计划会议由团队主导,但需要 PO 的贡献,特别是上面的第一条,需要 PO 的现场参与。其它条目,即使 PO 不在场,也应该随时可以提供远程的咨询。

作为 sprint 计划会议的结果,团队选择并承诺了接下来 sprint 中要完成的 product backlog 中的用户需求,并且,将每一个需求分解成具体的多个开发任务。这些开发任务的列表被称为 sprint backlog,它是 sprint 计划会议的最重要输出,接下来的工作,就是完成这些开发任务,交付对应的用户需求。

复制代码
for(num_of_day = 1; num_of_day <= Sprint_Length; num_of_day ++){
run_daily_scrum_meeting();
update_burndown_chart();
do_development_activity(sprint_backlog, &product_increment);
}

在这里,每一次 for 循环代表一个工作日,循环的次数也即 sprint 的时间长度。

Run daily scrum meeting – 进行每日 Scrum 会议: Scrum 团队每天都会进行一次同步 – Scrum 会议。Scrum 会议被限定在 15 分钟之内结束,每一天在同样的时间,同样的地点举行,旨在沟通同步项目开发状态,建立团队对项目的整体认识,并发现项目中的问题。会议上,每一个人都向团队回答三个问题:我昨天做了什么?我今天计划做什么?在前进的道路上有什么障碍? Scrum 会议结束后,要更新 sprint 燃尽图以反映团队的工作进度,和离 sprint 目标的距离。

Do development activity – 进行开发工作:Scrum 强调团队成员间的紧密协作,原则上任务应该由团队成员主动认领,而非被分配。为此,团队需要形成相应的规则,如:在同一时刻,不应该并行开始过多用户需求开发,这样可以确保团队有明确的工作重点,也可以避免在 sprint 结束时所有的需求都只是部分完成,而交付不了任何有价值的软件增量。随着开发进程的不断进展,软件增量得以生成、扩展和验证。

复制代码
run_sprint_review_meeting(product_backlog, product_increment);
run_retrospective_meeting();

Run sprint review meeting – 进行 sprint 评审会议:Sprint 评审会议又称为 sprint 演示会议,一个 sprint 结束,团队构建了包含新的用户需求的产品增量,团队在这个会议上展示过去的一个 sprint 所构建的产品。sprint 评审会议是开放的,应尽可能邀请相关人员参加,ScrumMaster、团队、PO、市场人员、客户、管理人员、维护人员、领域专家以及关联团队等。在会议上团队对照 product backlog 依次演示刚刚构建的用户需求,获取参与者的反馈,这些反馈将成为未来的产品设计和规划调整的依据,以使产品更好的满足客户的需求,更好的服务于组织的业务目标。

Run retrospective meeting – 进行 sprint 团队回顾会议:在评审会议之后,团队进行回顾会议,评审会议是对产品的检查和调整,而回顾会议是团队对自身的检查和调整。Scrum 强调通过经验性的过程,逐步检查和调整团队的协作和工作模式,持续改善。回顾会议是 Scrum 运行的十分重要的一环,其有效性是 Scrum 实施成功的保障。除非团队决定邀请额外人员,回顾会议一般只有团队参加,在回顾会议上,团队回顾刚刚过去的一个 sprint,团队在哪些方面做得好,应该坚持;哪些方面有待改进,并挖掘其本质原因,定义具体的改进计划,以在下一个 sprint 去切实实施。为保证回顾会议的有效,组织和团队都应该承诺愿意做出适应性的改变。

复制代码
update_product_backlog(&product_backlog, &release_burndown_chart);
update_velocity(&velocity);

Update product backlog – 更新产品待办事项:sprint 结束,产品待办事项内的一部分需求被交付,应该更新其状态。此外,由于 PO 和团队获取了更准确和详细的产品信息,product backlog 也应该相应更新,例如在 sprint 回顾会议激发了用户对优先级新的认识,在同 PO 确认后,product backlog 的优先级定义就需要做出相应的调整。更新产品待办事项的同时,发布燃尽图也需要相应更改,以反映最新的需求完成情况。

Update velocity – 更新团队开发速率:前面提到,团队承诺多少需求的依据是团队过去的开发速率。每个 sprint 结束,团队的参考发速率都需要根据实际情况做修正,这将有助于更好地把握开发节奏,合理地计划未来的工作。

至此,一个 sprint 结束,潜在可交付的产品增量得以交付或演示,团队和 PO 获取了有意义的反馈, product backlog 得到了调整,团队对工作进行了反思并定义了改进方案。这时就可以进入下一个 sprint,直至交付整个产品。

总结

Scrum 框架为团队敏捷实施定义了一个简单和明确的边界。在边界之内,团队探索和完善相关的管理和技术实践。我们一般建议,开始尝试 Scrum 的组织最初应严格遵循框架的定义,这时常会引起过于教条和形式主义的争议,团队会提出“应该抓住 Scrum 的实质,而不是强调形式”。问题是,只有通过严格的基本实践的学习和应用,我们才可能掌握其原则,区分哪些是实质,哪些是可以调整的形式。Ken Schwaber 对此的描述是,“对 Scrum 规则的修改,只有在 ScrumMaster 确信团队足够深入的掌握了 Scrum 的运行原理,有足够的技能和思维来修改规则时才可以进行”。

我们建议,那些准备实施 Scrum 或者已经实施但还处于探索中的团队,可以打印出这段伪代码,对照自身的实际操作,任何与这段伪代码不符的地方,团队都应该认真思考其合理性。我们更加建议,团队在实施 Scrum 的过程中,深入理解和思考 Scrum 框架背后的价值观和原则,Scrum 为什么可以和将怎样改进产品开发,为此我们需要做出哪些改变。对原则的理解和思考,有助于我们对实践的更好掌握,更快的从 Scrum 中受益。这也将是本文的第二部分要讨论的内容。(待续……)

* 本文部分参考了“ Scrum guide ”和“ Scrum Primer


感谢张凯峰对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2011 年 4 月 07 日 00:008907

评论

发布
暂无评论
发现更多内容

数字货币是大势所趋,新冠疫情后必须率先发展DCEP

CECBC区块链专委会

数字货币 银行

bug 回忆录(一)

志学Python

中国Prime会员独享巅峰64小时超长跨境网购时间

爱极客侠

一文领略 HTTP 的前世今生

yes的练级攻略

互联网 网络 HTTP 阿帕网

深入理解MySQL中事务隔离级别的实现原理

X先生

MySQL 数据库 后端 事务

华为全联接2020:环信AI领跑,输出5大行业最佳实践

DT极客

初学源码之——银行案例手写IOC和AOP

Java架构师迁哥

三年筑一“用”:长跑中的智能IP网络

脑极体

一个草根的日常杂碎(9月27日)

刘新吾

随笔杂谈 生活记录 社会百态

牛皮!应届生面试阿里Java岗,七轮过后定级P6,薪资44.8W

云流

计算机基础 Java 面试 编程开发 架构师技能

实践分享丨物联网操作系统中的任务管理

华为云开发者社区

华为 数据 物联网 进程

奈学开发者社区分享:Java - 设计模式的7个设计原则

奈学教育

Java 设计模式 设计原则

世界的下一个主宰——人工智能

CECBC区块链专委会

人工智能 智能时代

大学四年我是怎么写操作系统和计算机网络的?掏心掏肺的分享!

小林coding

学习 程序员 计算机网络 操作系统 计算机基础

架构1期第三周作业一

道长

极客大学架构师训练营

揭秘App的财富密码,剖析算法工程师价值来源

峰池

人工智能 互联网 推荐算法 互联网公司

公有云厂商哪家强?本月UCloud、百度云、阿里云位居三甲——2020年8月云主机性能评测排名

BonreeAPM

关于深浅拷贝

西贝

Java 前端 基础

一文纵览向量检索

华为云开发者社区

数据 搜索 检索 检查

H5选图预览到上传最佳实践

阿里云金融线TAM SRE专家服务团队

android H5

写给新人算法工程师

峰池

互联网 新人 推荐算法 算法工程师

关于互联网留存和收益你知道多少—带你走近用户成长体系

滴滴普惠出行

Binder那么弱怎么面大厂?

博文视点Broadview

Java android 通信 移动开发 Android进阶

奈学开发者社区分享:Java - 设计模式的7个设计原则

古月木易

Java 设计模式

戴尔G系列游戏本助玩家激战英特尔大师挑战赛

intel001

Electron 快速入门及最新安装教程

程序员学院

Java html 前端 Electron node,js

第二周-作业

咖啡

区块链会替代大数据吗?

CECBC区块链专委会

区块链 大数据

PPT画成这样,述职答辩还能过吗?

小傅哥

Java 小傅哥 流程图 架构师 PPT

for-range造就循环永动机?快来看看go中for-range的那些事!

新世界杂货铺

golang 后端 for

一个草根的日常杂碎(9月28日)

刘新吾

随笔杂谈 生活记录 社会百态

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

Scrum框架及其背后的原则(上)——Scrum 框架的伪代码描述-InfoQ