固定价格合同很有害,这是敏捷实践者经常说的。从另一个角度来说,这些合同是很多敏捷团队必须面对的现实。但是,如果我们试着去驯服它而不是去反对它,那结果又会如何?一个公司如何用敏捷实践执行这种合同来达到更佳效果和更低风险?这篇文章试图回答这些问题。
那让我们从合同本身开始。
固定的价格、时间和范围
固定价格合同同时冻结了全部三个神奇因素:资金、时间和范围。资金和时间对敏捷团队来说是个问题吗?应该不是。事实上,时间盒是很普遍的敏捷实践。限制资金投入只不过使时间盒工作得更好而已。
固定价格合同的真正问题是范围,需要构建的东西也是固定的,而不是可以选择构建的范围。
为什么客户这么执着于固定范围?我们理解他们想知道他们需要付多少钱(谁都想知道)以及什么时候可以交付。他们唯一不知道的是自己真正想要什么(即使他们坚持说他们知道)。
固定范围的根本问题是:
- 签约人互相之间缺乏信任
- 缺乏对软件开发流程的理解
- 对范围的误解
每份固定价格合同都伴随一份文档,类似于“需求分析”之流。这份文档试图降低忘记重要事件的风险,也试图建立需要完成事件的共同理解,让人们产生存在可预测性的假象。
固定范围的关键错误假设是:
- 前期的范围定义越仔细,我们越能彼此理解
- 定义良好的范围可以防止发生改变
- 范围需要固定,以便更好地预估价格和时间
从固定范围转移到固定预算
敏捷思维方式的应用和固定价格合同的主要差异在于固定范围,如果我们理解了这一点,那我们就可以把焦点从固定范围转变为固定预算上。
这意味着我们需要使用用户故事形式,捕获尽可能多详细需求规范,而不是提供它们。我们需要构建一个初始的产品待办事项列表,然后尝试用故事点技术和诸如规划扑克这样的团队整体预估技术进行预估。
首先,我们需要理解:软件需求规范中的更高层次细节对合同双方意味着完全不同的东西。软件公司通常会专注在技术细节上,而另一方则会更注重业务导向。规范通常由软件公司制定,会很有保护性。这是三个关键因素发挥作用的舞台。
用户故事,作为表达需求的一种方法,同时能被客户和供应商理解。这种理解能建立信任和共同的远见。用户故事可以快速写出也能快速消灭,特别是写在索引卡上的用户故事。它们同时也是特征功能驱动的,所以能对实际项目的范围提供很好的参考。我们也可以比较它们的大小和工作量。
故事点数,作为估计故事的一种方法,在开始阶段给客户解释起来更难,因为这不是表达工作量的常用方法。但是从回报看来,使用故事点数降低了低估范围的风险。如何做到的呢?故事点数从本质来说是相对的,着眼点放在整个范围或者一组故事。而传统的估计(通常以“人 - 小时”做单位)试图逐个功能单独分析。
“完成”的定义,是另一种建立信任的方法,使双方对流程和今后项目计划有共同的理解。通常这会是客户第一次看到用户故事。虽然他们也许会喜欢这种写故事的方法,但是如何实现故事却并不明显。要和客户一起讨论“完成”的定义的团队更了解客户的期望。它们也能更好地被估计。另外,从客户角度来说,“完成”的定义建立了验收用户故事的高层标准。
比如说,对一个新建网络应用的故事,“完成”的定义可能引入以下标准
- 在 IE 7/8、Firefox 3.x 以及 Chrome 里做过测试
- 在“用户指南”里有相应的章节
之后,团队可以在“完成”的定义中加入其他偏重技术实现的元素。不过在建立合同阶段,概要指导在客户和团队间提供了共同理解的基础,为在选定范围内需要做的工作达成共识。
希望在有了“完成”的定义之后,我们可以给出一些价值,体现为以点数定义预算范围。而这价值,不是价值背后的用户故事,是在合同中需要确定下来的第一件事情。这使变化变得可能。
虽然我们(以点数的形式)固定了范围,我们还想在敏捷方法中拥抱变化。我们有工具(用户故事和点数),可以用它们来比较不同的需求。这允许我们在开发途中,可以在预定的范围限度之内交换需求。如果我们能保持那个限度,那我们也能保持固定的价格和时间。
初始估算
准备固定价格合同最难的部分,是根据定义好的范围制定固定的价格和时间表。让我们看看团队对这样的合同能做什么样的贡献,如何以敏捷的方式做初始项目估计。
首先,要引导客户。和你的客户见面,描述你们将要采取的工作方式。我们需要说明故事是什么,我们会如何估计它们,什么是“完成”的定义。通常我们需要在更早的时候做这些事情,比如当我们回应客户的提案要求(RFP)时。
下一步是收集用户故事。这可以安排 1 至 2 天的时间盒会议。这足够找到大部分的用户故事来组成产品愿景,而不用掉入缓慢的功能分析。在这个时刻,与客户讨论故事的“完成”的定义、迭代、发布是很重要的事情。
我们需要知道:
- 故事被测试的环境(像浏览器的种类、手机平台或者操作系统)
- 需要哪些文档
- 完成的故事该在哪里部署,使得客户可以看到他们
- 客户需要做什么?(比如,参加演示会议)
- 我们多久碰一次头,谁将参加
- 其他
这个因素和许多项目特定因素会影响估算,需要双方对期望和质量建立公共的理解。这样他们不会不切实际地做出估计,避免团队只考虑故事的实现技术。
与客户讨论过一系列故事和“完成”的定义后,我们现在可以开始估算。这部分的流程很多人都知道。最重要的是让尽可能多团队成员参与,做出全面估算。如规划扑克这样的技巧被很多人熟知,它能降低由于特定团队成员的单独观点而产生低估的风险,特别是这些团队成员也是最有经验的成员时,常常会发生只由一个人完成估算。故事应该由真正实现系统的人来估算,这点很重要。
类似斐波那契数列的数字(1,2,3,5,8,13,20,40,100)在估算故事点数时能派上用场。相对估算从找到一系列最简单或最小的故事开始。他们会得到 1 或者 2 点,作为将来估算的基准点。
事实上,初始估算中很难用类似 1 或者 2 的低价值来估算故事。关键是,估算越高,我们对故事了解得越少。这也是为什么在初始阶段用点数来估算会更容易。毕竟说出故事 A 的复杂度是故事 B 的两倍,比说出完成故事 A 需要 25“人 - 小时”(记得“完成”的定义吗?)而完成故事 B 需要 54“人 - 小时”要容易得多。
即使我们选择 3 或 5 点的故事作为基准点也会很有成效。如果我们这样做,可以在以后的开发过程中很容易的把他们拆分为更小的故事。然而,需要注意 20、40 或 100 点的故事。这些估算表示我们不知道该如何实现。所以,需要和客户一起讨论更具体的细节,而不只是开心地放进合同里。
估算的结果是描述构建产品初始范围的故事点数的总和。这个数字应该代表范围在合同中被固定,而不是特定的故事本身。
固定价格和时间
基于一批初始故事的预估点数总和,并不能直接给我们价格和时间。那如何得到它们?我们需要一些神奇的数字。
这应该并不奇怪,因为在固定价格合同中总有神奇的数字出现。所有预估的价值也都是这样的数字。目前我们只是在改变做估算的方式,但是最终我们也要基于对过去的了解对将来做出估算。所以,我们需要知道什么?预计团队的速率。
让我们假设我们估计了总共 300 点的故事。我们需要基于以下因素确定团队的基础速率:
- 团队之前项目的速率
- 在本迭代需要完成的活动数(见“完成”的定义)
- 与客户交流的容易度(当然,理想的情况很难达到,也就是有一个客户作为团队的一员在现场,但是通常这不是我们能达到的,不同客户愿意和团队一起工作的时间是不同的):客户给我们的时间越少,我们的速率越低
- 看过范围之后的感觉(没错,跟着感觉走)
假设我们有一个 5 人团队:3 个人负责编码,1 个人负责测试和一个组长。组长会与客户、干系人及团队之外的其他人交流(如 Scrum 中的 ScrumMaster 一样)。
我们现在可以决定:团队会尝试实现每个 2 周迭代完成 20 个故事点数的速率。这是在合同中主要的神奇数字。项目中的很多因素会影响速率,然而如果一起工作的团队不是新团队,工作的项目也不是很不熟悉的领域,这个数字实际上可以基于一些过去的证据和观察而给出。
现在,我们可能面对客户在合同里强加给我们的两种约束之一:
- 客户希望以我们能做的最快速度得到软件(如果可以的话,甚至更快)
- 客户需要在日期 X 之前尽可能多做(这就是我们的最后期限)
情景 1
在第一种情况下,我们可以通过以下公式来确定预计结束时间:
时间 = (< 点数 > / < 速率 >) * < 迭代长度 >
所以在我们的例子中,会是:
时间 = (300 点 / 20 点) * 2 周 = 30 周 (或者 15 个迭代)
如果大家无法接受计算出来的时间,那我们唯一能改的因素就是团队的速率。要达到这个目的,我们需要扩大团队。然而,这种做法并不是线性的。使团队大小加倍,并不能使速率加倍。
场景 2
我们知道再过 20 个星期就是最后期限,也就是只有 10 个迭代,所以我们只能完成 200 个故事点数。现在,客户需要决定:在不影响交付必要的客户价值的前提下,我们可以从范围中移除什么。
这里我们(在某种程度上)也可以通过改变团队大小来得到更高速率.
知道了需要的团队大小和目标完成时间,我们最终可以算出合同中价格的主要部分:工作时间成本:
金额 = < 每个迭代的小时数 > * < 迭代数 > * < 人 > * < 小时价格 >
在我们的例子中,会得到:
金额 = 80 小时 * 15 个迭代 * 4 个人 * $100= $480,000
所以我们现在有了固定价格合同的价值
- 价格:$480,000
- 时间:15 个迭代(30 周)
- 范围:300 个故事点
这些最简单的计算当然只是合同中成本的一部分,但是它们通常是最难定义的一部分。我们在这里试图呈现的是:我们在敏捷项目中的工作方式也可以转移到合同谈判的环境中。
还有一个问题需要处理。客户问:“为什么这么贵?”这通常是谈判的开始。我们想要在这里提醒的一点是,软件公司能改变的唯一因素是“人 - 小时”成本率。我们能谈判的是 $100,而不是迭代的长度,也不是迭代的数量。我们的团队没有超级英雄的能力,不会因为我们的谈判方式而工作速度加倍。
这是我们愿意损失的钱。如果我们说可以更便宜,那是因为我们会挣更少,而不是我们能做更快。
追踪进度和预算
既然我们已经签了合同(这还挺容易,是吗?),是时候在协议的期限内构建软件了。你可能已经听说了敏捷不能解决你的问题,但能使问题显现。这就是为什么我们希望及早知道我们做得如何,从而采取适当的行动。也有可能在固定价格合同中的神奇数字(我们的速率)是一个错误。
燃尽图是许多敏捷项目追踪进度的常用方法。
图 1:计划范围燃尽 vs. 真实进度
通过它们可以很好地看出计划进度和实际进度。比如,图 1 的燃尽图看起来很不错:
图 2:范围燃尽 vs 预算燃尽
图 2 显示了两种燃尽:范围和预算。为了使两者可比,这两种趋势都用百分比来表达。没有别的方法来比较这两个数量(一个是故事点数,另一个是“人 - 小时”或者用掉的钱)。
第二张表看起来并不太好。我们正在花更多的钱来使我们在期望的轨道上运行。这可能是因为用了额外的资源来达成期望的团队速率。所以,在一张表上的所有三个因素使问题可见。在这个例子中的第 4 个迭代,是我们应该和客户交谈的时候,那还不算太晚。
以这种方式追踪范围和预算,我们需要:
- 追踪每个迭代完成的故事点数(“完成”的定义)
- 追踪每个迭代实际花费的时间(以 [人 - 小时] 为单位)
- 重算项目中的全部故事点数,作为范围的 100%。基于剩余范围相对于总共范围的比例,画出一个燃尽点。
- 重算合同中固定的预算,折合成“人 - 小时”,这就是预算的 100%。基于现在已使用的预算,画出一个燃尽点。
在我们之前的例子中,我们有:
- 范围:300 故事点
- 预算:30 周 *4 个人 *40 每周小时 =4800“人 - 小时”
这会是我们的总数。所以,花了 120 小时来燃尽 6 个故事点数,意味着我们用了 2.5% 的预算来燃尽 2% 的范围。
拥抱变化
我们需要再次回到从固定范围转变到固定预算的那一点。在之前例子中的 300 故事点让我们能够交换初始用户故事列表的内容。这是我们用敏捷方法实现固定价格合同的最重要方面之一。
敏捷拥抱变化,我们需要做的是在固定价格合同中简化变化管理。这在过去一直是很艰难的工作,而且现在也是。
困难在于如何说服客户故事是可以交换的,因为他们应该可以在工作量上比较。所以,如果客户在任何时候有新的好想法,我们也可以用一组新的故事来表达这个想法(比如价值 20 个故事点),那这又应该由客户来决定是否应该从初始的待办事项列表中移去 20 个点数,留下空间给新的故事。
也许客户想要增加一个迭代(还记得速率为每个迭代 20 点吗?)。增加新故事时计算价格很容易:
金额 = 1 个迭代 * 80“人 - 小时” * 4 个人 * $100 = $24,000
这种合同中还有一个最难的地方,当我们在项目过程中发现一些故事需要比预期更多的时间,因为我们估算的时候它们还是很粗略的故事,现在我们的信息比开始时更多。然而,事情并非总是这样,因为有些时候,你会发现有些故事比预期花的时间要少。所以,重复一遍,在合同执行期跟踪进度,能提供有价值的信息。在早期讨论问题能帮助谈判,因为我们可以谈论预防措施,而不是等到巨大的、不可挽回的灾难发生后,再谈论救援计划。
获取信任
要使所有这些技巧能在固定价格合同中使用,需要一样东西:信任。但是如我们所知,仅仅描述团队将会为客户做多么伟大的工作,这无法让我们得到信任。
敏捷原则提供了一个很好的办法来解决这个问题。在每个迭代中,我们都为客户构建价值。更重要的是,我们关注在先交付最有价值的功能上。所以,建立客户信任的最佳方式可能是拆分合同。
从小功能开始,一些 2 到 3 个迭代的试点(也是固定价值的,但是更短)。交付的软件必须带给客户期望的价值。事实上,它必须包含关键功能的可工作部分。可工作的软件证明你能构建剩余的部分。这样也给你机会验证对速率的第一个假设,最终在下一部分可以重新谈判。
花在试点中的时间相对剩余的工作范围也应该较少。这样的话,如果客户不满意结果,我们可以在来得及的时候离开,没有必要继续合同并最终使项目失败。
总结
固定价格合同经常被认为是有害的,很多敏捷实施者认为我们应该避免它们。但是大部分时间,它们不能避免,所以我们需要找到一个方法使它们达到我们的目标——构建有价值的高质量软件。
事实上,一些固定因素甚至对敏捷团队更有利,因为我们习惯了工作在时间盒中,那正是合同中的固定期限(也是固定价格):只是时间盒和边界而已。唯一困扰我们的事情是范围,在这篇文章中,我们试着集合很多想法来处理这个限制。
这篇文章的目的,不是为了提出敏捷是固定价格合同的终极解药,而是为了呈现一些使它能在敏捷方式中工作的方法。
关于作者
Marcin Niebudek 是一个企业家、Agilers 公司的所有者之一、也是 tinyPM 的创始人,tinyPM 是一个轻量级的敏捷项目管理工具。Marcin 对软件开发有疯狂的唯心论,他强烈相信它是一门手艺。他享受经历各种敏捷和精益开发技巧的滋味。他也热爱写软件、读软件、想软件,并写入博客。他是敏捷博客“为敏捷而战(Battle for Agility)”的作者,博客中描述了在波兰 IT 业的敏捷运动。他主要使用 Java 开发,有 8 年企业系统开发经验,熟练掌握各种 Java EE 的技术。
查看原文: http://www.infoq.com/articles/agile-team-fixed-price-contract
感谢郑柯对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。
评论