准确估算软件项目的时间
准确估算软件项目的时间有什么价值?低估和高估哪个危害更大?为什么准确估算很困难?我们又该如何实现准确估算?本文将探讨这些问题。
准确估算的价值
准确估算的价值,我认为主要体现在两个方面:成效和信任。
首先说一下成效。需要厘清的是,成效(effective)不等于效率(efficiency)。成效是一个结果指标,体现结果的价值(一般指商业价值),常用投资回报率(ROI)来衡量。而效率是一个过程指标,体现过程中资源利用率的优化程度,常用生产率(productivity)来衡量。
注释:「结果指标」和「过程指标 」这两个装逼名词是我从知乎著名产品经理 —— 产品经理胡笛笛—— 那里偷师来的,我认为笛笛的表达切中肯綮。
理想情况下,成效和效率是相辅相成的关系 —— 高效率促进高成效,高成效追求高效率。然而现实中,常常会发生高效率低成效的情况。比如在项目开发过程中,一个程序员消失了一周,用一周时间高效地完成了一项原本需要两周时间的代码重构工作,但由于这项工作和正在进行的项目无关,反而耽误了项目进展,导致项目延期,造成了营收损失。显然,在这个例子中,这个任性的重构工作就是高效率低成效的。(程序员常常会误认为重构代码会在长期内降低开发成本,然而这些收益要等到项目结束后很长的一段时间才能兑现,却又实实在在影响了我们当前项目按时按质交付的目标。)
那么,准确估算对成效的帮助体现在哪呢?
本质上,项目时间估算是对项目成本(之一)—— 人力成本 —— 的估算。项目成本是公司决定资源投入的重要依据。公司倾向于投入高成效的项目。如果估算不准确,误导了公司的投入方向,会导致公司和个人的成效都会很低。因此,准确估算可以说是高成效的一个必要条件。
其次说一下准确估算影响的第二个方面 —— 信任。尽管在程序员看来,估算只是对项目时间的猜测,但实际上,当我们把估算的时间告诉领导和客户时,他们往往会把这个时间视为一个「届时完成」的承诺。虽然这种看法是不正确的,但游戏规则就是如此。
我们需要完成「承诺」以获得他人的信任。获得领导的信任能让你在职场如鱼得水,获得客户的信任则能增加客户复购产品的信心。信任成为人脉,而人脉具有复利效应,从长期利益角度看,毫无疑问对我们的发展帮助非常大。因此,我们得尽量把时间估得再准点,成为一个他人眼中值得信任的人。
低估和高估,哪个危害更大
帕金森定律:在工作能够完成的时限内,工作量会一直增加,直到所有可用时间都被填充为止。(人话翻译:工作预估的时间内,即便工作事实上完成了,也会没事找事,用其他的的事项填充掉剩余的时间。)
学生综合征:如果给开发人员过多的时间,他们就会一直拖延到项目快结束的时候才匆忙赶工, 结果反而很可能无法按时完成项目。—— Goldratt
准确的估算可以帮助我们取得高成效和他人的信任,而不准确的估算——低估或者高估——会给我们造成损失。那么低估和高估,哪个损失更大呢? 《软件估算的艺术》中给出的分析如上图所示。书中认为,低估造成的损失更大。因为低估的损失呈指数型增长,而高估的损失仅仅是线性增长。
低估造成的问题可能有:
- 降低项目计划的有效性。例如组建的团队规模小于实际的需要,也会破坏小组间协调能力 —— 一个小组工作未完成,其他小组工作无法集成。
- 未做好前期基础工作导致结果更差。低估会导致在开发的上游活动(需求和设计)上花费的时间太少,后期需要重新设计和返工。相较于在前期解决这些问题,后期解决的代价可能是 10x,甚至 100x。
- 后期破坏性的变因(dynamic)导致项目结果更差。因为项目一旦进入延误状态,就需要大量的额外活动,例如开会讨论挽救措施,重新估算项目,修复先前为缓解进度压力而投机取巧导致的一些问题等。 显然,这些问题造成的损失会显著提高项目的实际成本,大大延缓项目时间。
而高估带来的损失主要是人力成本的损失,原因是「帕金森定律」和「学生综合征」。这是有上界的线性损失 —— 工作会花掉所有预估的时间,但不会进一步占用更多的时间。
准确估算的困难和办法
侯世达定律:做事所花费的时间总是比你预期的要长,即使你的预期中考虑了侯世达定律。 —— 侯世达, 《哥德尔、埃舍尔、巴赫》
准确估算的困难有其客观性和主观性。
客观上,估算值应该是一个概率分布的区间。如上图所示,实际项目完成时间在这个区间内的概率呈偏态分布(skewed distribution)——因为最乐观的情况是有限制的,而最悲观的情况是无限制的(例如项目过程中发生极端事件,导致永远无法完成)。
然而,在实际工作中,我们常常被要求提供一个单点估算值(设定 deadline)。这种以点表示区间的方法实际上是一种以偏概全,和赌博没有什么区别。又有谁能在赌博中战无不胜呢?无论是高进(周润发)、小刀(刘德华)还是阿星(周星驰),都不行!更何况你我。
因此,如果有可能,最好先以区间([最乐观,最悲观]) 的形式提供估算值,随着项目的进展,事情逐步明了,再逐步缩小区间范围。
估算除了存在这些客观上的困难,还会一些主观人为因素的干扰。程序员在估算时可能会采取一些错误的估算方法:
- 即兴估算。会议上,领导拍脑袋安排任务,程序员也拍脑袋给出估算时间,拍胸脯说保证搞定。会后仔细分析,拍大腿暗道坏了,根本搞不定,最后只能拍屁股走人了 :)
- 锚定估算。领导故意问能否在两周内完成需要几个月时间的项目,程序员受锚定效应影响,可能只敢给出三周 —— 比锚定的两周多一周。
- 逞强估算。为了表现自己,故意压低估算时间。很多刚毕业的年轻人喜欢这么干,结果往往付出惨痛代价。
- 压力估算。领导说客户必须在某个时间点要,程序员只能无奈修改估算值。
解决这些问题的办法是:一是使用正确的估算方法,二是坚持第一点,一百年不动摇。
我认为,正确的估算方法包含两步:第一步是估算工作量(通常以人日描述),第二步是将人日转化为自然日。
常用的估算方法是拆解估算法:将大任务拆解成小任务,先估算小任务的工作量,然后累加得出大任务的工作量。拆解的粒度要细,尽量细化到每个人日。
拆解估算法相对于直接估算大任务总体的工作量会更准确一点。直接估算大任务偏差会很大,而估算小任务虽然也会有高有低,但当估算的小任务数量足够大时,估算会更加贴近期望值,这体现了大数定律。
为了增强对估算结果的信心,我们也可以用其他思路交叉验证,例如《人月神话》中的经验法则:
- 1/3 计划
- 1/6 编码
- 1/4 构件测试和早期系统测试
- 1/4 系统测试,所有的构件已完成
我们可以估算出最乐观和最悲观情况下的工作量,作为估算的结果区间。如果进一步需要提供一个单点估算值,我们不能直接使用区间中点。因为很多时候,最差情况比所谓的预期情况差很多。使用中点会导致不必要的高估。
一个著名的方法是 PERT 估算法(Program Evaluation and Review Technique,计划评审技术)。PERT 估算法除了需要估算最乐观和最悲观的时间,还要估算最可能的时间。然后运用估算公式:
公式 1: 估算时间 = (最乐观 + ( 4 × 最可能) + 最悲观 ) / 6
举个例子说明一下:假设一个项目最乐观需要 5 天,最可能需要 8 天,最悲观需要 15 天,那么单点估算时间 = (5 + 4 × 8 + 15) / 6 ≈ 9 天。
然而考虑到最可能估算往往也是偏乐观的,那么就可以给最悲观估算增加些权重。改进版本的公式如下:
公式 2: 估算时间 = (最乐观 + ( 3 × 最可能) + (2 × 最悲观) ) / 6
使用改进版公式,单点估算时间 = (5 + 3 × 8 + 2 × 15) / 6 ≈ 11.5 天,看起来更可靠。
完成第一步工作量估算后,第二步是将人日转化为自然日。转换公式如下:
公式 3:估算时间 = 工作量人日 × 自然日转换系数
自然日转换系数可根据实际工作情况确定,例如每周实际工作时间(除去开会,其他人的 code review,休假等无关事项)为 2.5 天,那么自然日转换系数就是 2。假设第一步单点估算的工作量是 10 人日,那么最终需要的自然日就是 20 天(当然,这不包括周六日)。
以上就是我总结的一些估算方法。很明显,这些方法不是银弹(当然也不存在银弹),但相比前面提到的一些错误估算方法,这些方法的可靠性更高,值得一试。
在掌握了这些估算方法后,我们还需要做好所谓的第二点 —— 坚持它们一百年不动摇。
换句话说,估算结果不容谈判。话虽如此,很多时候领导和客户很可能不认可我们的估算结果,并会对我们施压。这时我们一定要坚持原则,不能妥协,也不能争吵。我们需要带上同理心和逻辑与领导沟通(同理心和逻辑是我认为的沟通能力最重要的两个工具)。
从同理心的角度,可以先思考领导和客户的需求是什么。通常来说,领导和客户需求是希望客户在某个时间点能用上一些产品功能。从逻辑的角度,我们和领导以及客户的目标是一致的,绝对存在共赢的可能性。我们需要找到一些变通的办法实现目标。这时可以拿出另一个工具 —— 产品-进度-成本三角。
产品-进度-成本三角的含义是,如果想要提升进度,一种办法是牺牲产品(的功能或质量)—— 缩小功能 scope 或者允许一些非关键 bug,另一种办法是增加成本 —— 例如在项目早期增加人手。这两个办法都是空间换时间思想的一种体现。
当把这两个办法摆给领导和客户的时候,我相信能取得他们的一些理解,最终共同讨论出可行的办法。如果不被理解,那么要么你得再锻炼下沟通能力(提升同理心和逻辑),要么考虑下请领导吃炒鱿鱼,把天赋带到下一家值得的公司 :)
无论什么情况,请始终记住,使用正确的估算方法并坚持它。一旦妥协,必定会在成效和信任上受到损失。毫无疑问,这是更为惨痛的代价。
总结
本文探讨了准确估算的价值,分析了低估和高估的危害以及准确估算的困难,并提出了一些解决方法。尽管这些方法并不是银弹,但肯定能够提升估算的准确性。希望能对读者有所帮助。
参考
- 《软件估算的艺术》
- 《快速开发》
- 《人月神话》
留下评论