任何做过一段时间软件开发的人都知道,估算一件事情需要多长时间是很困难的。当某项工作本质上是为了解决某件事时,很难对这件事需要多长时间做出一个无偏差估计。长期以来,我最喜欢的一个理论是,有些软件项目花费的时间看起来比预计的要长只是统计上的假象。
我怀疑开发人员实际上能够很好地估算完成任务所需的“中值”时间。之所以计划很难,那是因为他们的平均水平很糟糕。
-ErikBernhardsson(@fulhack)2017年5月11日
假设你估算一个项目需要一周的时间。再假设有三种等可能的结果,要么花1/2周,要么花1周,要么花2周。中值(median)结果实际上与估计值相同:1周,但是平均值(mean,也叫average,或者期望值)是7/6=1.17周。估计值实际上是对中值(这里是1)的修正(无偏),而不是对平均值修正。
一个合理的“放大系数”模型应该类似于对数-正态分布。如果估计值为一周,那么我们将实际时间建模为随机变量,该随机变量在一周左右按照对数-正态分布进行分布。这个模型的一个特性是,该分布的中值正好是一周,但平均值要大得多:
如果我们取放大系数的对数,我们会得到一个以0为中心的普通正态分布。这里我们假设的中值放大系数是1倍,正如你所记得的一样,log(1)=0。但是,不同的任务在0附近可能有不同的不确定度。我们可以以不同的σ参数来进行建模, 这里的σ参数与正态分布的标准偏差相关:
我们在这里加入一些数字: 当log(实际/估计)= 1时,放大系数是exp(1) = e = 2.72。也就是说,一个项目被放大系数exp(2) = 7.4放大之后与它在exp(-2) = 0.14完成的可能性是相同的,即在估计时间的14%内完成。从直觉上来看,平均值如此之大的原因是,完成的比预期快的任务无法补偿完成的比预期时间长得多的任务。我们以0为界,但在另一个方向上是无界的。
这只是一个模型吗? 你说的没错! 但我很快就会讲到真实的数据,并通过一些经验数据来说明这实际上与实际是很好地对应的。
软件估计
到目前为止一切都很好,但是我们来真正试着理解一下软件估计到底意味着什么。假设我们在看一个开发路线图,它由20个不同的软件项目组成,我们尝试着估计一下:完成所有这些项目需要多长时间。
这就是平均值变得至关重要的地方。平均值增加,但是中值不增加。因此,如果我们想知道完成n个项目总共需要多长时间,我们需要查看平均值。假设我们有三个不同的项目,它们具有相同的σ值,σ= 1:
请注意,平均值是加起来的,即4.95 = 1.65*3,但是其他列没有。
现在,我们来以不同的西格玛值将三个项目相加:
平均值仍然是相加的,但每一个值都与你估计的3周相差甚远。注意, σ= 2的高不确定度项目基本上最终左右了平均完成时间。对于99%百分位数来说,它不仅左右了项目完成时间,它基本上是吞并了所有其他任务。我们可以举一个更大的例子:
同样,一个行为不端的任务最终主导了计算,至少在99%的情况下是这样。即使对平均值而言,一个奇怪的任务最终也会占用完成所有这些项目大约一半的时间,尽管所有这些任务的中值完成时间都差不多。简单来说,我假设所有任务的估计值大小都是相同的,但是不确定度不同。同样的计算方法也适用于改变任务大小的情况。
有趣的是,我有这种直觉已经有一段时间了。当你最终需要处理多个任务时,将估计值加起来很少会奏效。相反,你需要找出哪些任务具有最高的不确定度——这些任务基本上会支配平均完成时间。
我有两种估计项目大小的方法:
(a)把一个项目分成子项目,分别估计,再加起来
(b)基于我对意外风险的紧张程度进行直觉估计
到目前为止(b)对于任何周期超过几周的项目都要精确得多
——Erik Bernhardsson(@fulhack) 2019年3月8日
下面的图表总结了平均值和第99百分位与不确定度(σ)的函数关系图:
这就变成了数学问题! 我在项目计划期间就开始意识到这一点: 我真的认为,将任务估计值相加,对于某件事需要多长时间来说,实际上是一种误导,因为某些疯狂扭曲的任务最终会左右完成时间。
经验数据在哪里?
很长一段时间以来,我都把这段话记在大脑中的“好奇的玩具模型”(curious toy models)里,我偶尔会想到,这是我所观察到的真实世界现象的一个简洁例证。但有一天,我在 上浏览时,发现了一个有趣的管理项目估计和实际时间的数据集。这太棒了!
我们来绘制一个快速估计与实际完成时间的散点图:
这个数据集的中值“放大系数”(实际时间除以估计时间)恰好是1倍,而平均值放大系数是1.81倍。再一次证实了开发人员对中值的估计很好,但最终的平均值要高得多。
我们来看看放大系数的分布。先看看它的对数:
可以看到,它以0为中心,其中放大系数为exp(0) = 1。
使用统计工具
我现在要对这个统计结果做些分析——如果你不喜欢,可以跳过。我们能从这个经验分布中推断出什么?你可能认为放大系数的对数会按照正态分布进行分布,但这并不完全正确。注意,σs本身就是它们的随机性,并且每个项目各不相同。
对σs进行建模的一个便捷的方式是从一个逆伽马分布中进行取样。如果我们假设(像以前一样)放大系数的对数是按照正态分布进行分布的,那么所有放大系数的对数的“总体”分布将服从学生-t分布。
我们来对上面的分布拟合一个学生-t分布:
在我看来,完美契合! t-分布的参数还定义了σ值的逆伽马分布:
注意,σ>4是极不可能出现的, 但是当它们发生时,就会造成平均值放大数千倍。
为什么软件任务需要的时间总是比你想象的要长
假设这个数据集是软件开发的代表(当然是存在问题的!),我们可以推断出更多的数字。我们有t-分布的参数,因此,我们可以在不知道一项任务的σ值的情况下计算完成这项任务的平均时间。
虽然从这个拟合中得出的中值放大系数是1倍(和以前一样),99%百分位数放大系数是32倍,但是如果你达到99.99%百分位数,那结果将是一个惊人的5500万!一种解释是,有些任务最终基本上是不可能完成的。事实上,这些极端情况对平均值的影响是如此之大,以至于任何任务的平均放大系数最终都是趋向无穷大的。对于那些想赶在截止日期前完成任务的人来说,这是个坏消息!
总结
如果我的模型是正确的(前提是如果),那么我们从中可以学到:
备注
英文原文:https://erikbern.com/2019/04/15/why-software-projects-take-longer-than-you-think-a-statistical-model.html?译者:一瞬
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!