为什么软件项目花费的时间比你想象的要长——一个统计模型

任何做过一段时间软件开发的人都知道,估算一件事情需要多长时间是很困难的。当某项工作本质上是为了解决某件事时,很难对这件事需要多长时间做出一个无偏差估计。长期以来,我最喜欢的一个理论是,有些软件项目花费的时间看起来比预计的要长只是统计上的假象。

我怀疑开发人员实际上能够很好地估算完成任务所需的“中值”时间。之所以计划很难,那是因为他们的平均水平很糟糕。

-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万!一种解释是,有些任务最终基本上是不可能完成的。事实上,这些极端情况对平均值的影响是如此之大,以至于任何任务的平均放大系数最终都是趋向无穷大的。对于那些想赶在截止日期前完成任务的人来说,这是个坏消息!

总结

如果我的模型是正确的(前提是如果),那么我们从中可以学到:

  • 人们很好地估计了中值完成时间,但不是平均值。
  • 由于分布是非对称的(对数正态的),平均值实际上比中值差得多。
  • 当你把n项任务的估计值加起来,情况会变得更糟。
  • 不确定度最大的任务(而不是大小最大的任务)通常会影响完成所有任务所需的平均时间。
  • 完成一项我们一无所知的任务的平均时间实际上是无穷大的。
  • 备注

  • 这显然只是基于我在 上找到的一个数据集。其他数据集可能会得到不同的结果。
  • 和任何统计模型一样,我的模型当然也非常主观。
  • 我更喜欢将这个模型应用于一个更大的数据集,看看它的结果如何。
  • 我假设所有的任务都是独立的。在现实中,它们之间可能存在相关性,这将使分析更加恼人,但(我认为)最终也会得出类似的结论。
  • 对数-正态分布值的总和不是另一个对数正态分布值,这是这种分布的一个弱点,因为你可以说大多数任务实际上只是子任务的总和,但是如果我们的分布能像这样稳定就好了。
  • 我从直方图中删除了小任务(估计时间小于或等于7小时),因为小任务会扭曲分析,而且恰好在7这个值的位置有一个奇怪的峰值。
  • 和往常一样,代码在我的Github上。
  • Hacker News和Reddit上有一些讨论。
  • 英文原文:https://erikbern.com/2019/04/15/why-software-projects-take-longer-than-you-think-a-statistical-model.html?译者:一瞬

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2019年3月26日
    下一篇 2019年3月27日

    相关推荐