在软件开发过程中,估算始终是一项具有挑战性的任务,因为软件开发包含很多不确定因素,而且任何项目都不尽相同。虽然很难(或几乎不可能)做到完美估算,但还是有必要努力提高估算的准确性。本文将根据自己的经验和深入研究来解释软件估算的原则。我保证,有了这些可操作的原则,你可以显著改善项目估算的结果。
为什么估算很重要?
为什么估算很重要?为什么客户、高管、销售人员或其他利益相关者总是问:"需要多长时间?""你们什么时候能完成?"他们会根据估算采取什么行动?答案是为了业务决策。估算的最终目的是支持业务决策。估算会直接影响时间和成本,这也是商人一直关心的问题,以便衡量他们的投资能获得多少收益,也就是所谓的投资回报率(ROI,Return on Investment)。估算不是为了降低风险、提高速度或确保质量,而是为了辅助决策。我见过很多人误以为自己在做软件开发,但实际上他们做的是业务。
在敏捷项目中,产品负责人(Product Owner)代表业务并负责决策,他根据三个因素做出决定:范围、资源和时间。估算与时间有关,产品负责人要监控这三个因素之间的平衡,以确定应该开发什么以及何时开发。例如,如果一项任务需要一天或一年的时间,做出的决定就会不同。如果任务估计只需要一天的时间,他可能会决定立即着手进行。相反,如果估计需要一年,就可能会取消或推迟。估算对产品负责人的决策有巨大的影响。在敏捷项目中,产品负责人(Product Owner)代表业务并负责决策,他根据三个因素做出决定:范围、资源和时间。估算与时间有关,产品负责人要监控这三个因素之间的平衡,以确定应该开发什么以及何时开发。例如,如果一项任务需要一天或一年的时间,她的决定就会不同。如果任务估计只需要一天的时间,她可能会决定立即着手进行。相反,如果估计需要一年,她可能会取消或推迟。估算对她的决策影响巨大。
决策三角
敏捷项目和瀑布式项目的决策方法不同。在敏捷项目中,资源和时间是固定的,而范围是灵活的。由于敏捷是为快速迭代交付而设计,因此产品负责人要考虑的是如何在有限的时间和资源内实现产品价值的最大化。如果估算的范围过大,无法在目标时间内完成,则应按照优先级缩小范围。
另一方面,在瀑布式方法中,范围是固定的,而资源和时间是灵活的。决策者的角色与敏捷项目中的产品负责人相同,需要考虑完成所有项目需要多少资源和时间。他需要采购必要的人力资源,并根据范围大小和估算制定计划。
阿特拉斯敏捷铁三角
虽然上述决策方法广为人知,但固定和灵活的因素可能会根据业务环境发生变化。例如,在敏捷方法中,如果利益相关者要求通过推迟交付时间来完成所有工作,那么时间就会延长。如果客户预算有限,而软件开发的成本超出了他们的预期,那么瀑布式方法中的时间范围就会缩小。应根据实际情况调整决策,同时牢记这些基本方法。
原则 1:明确需求
第一条原则是明确需求。不确定性三角的研究表明,明确的需求最能提高估算的准确性。换句话说,需求越明确,估算就越准确。
下图说明了估算变异性(不准确性)是如何随着时间的推移而缩小的。垂直线表示估算可变性,水平线表示时间(开发阶段)。如图所示,随着初步概念的形成、产品定义的批准、需求的完成以及用户界面的完善,估算变异性会明显缩小。在总时间的前 20%-30%,锥形线明显变窄,将估算可变性降低了 2 倍到 4 倍。如果不确定从哪里开始估算,请从尽可能清晰的定义需求开始。这一步看似显而易见,但在许多项目中却经常被忽视。
原则 2:定义"完成"的含义
第二个原则是定义项目中完成的含义,即"完成的定义"(DoD,Definition of Done)。DoD 可以区分已完成和未完成的 PBI(Product Backlog Item,也称为 ticket、issue 或 tasks),并提高产出质量。估算中最常见的误区之一就是忽视质量保证过程,这往往会导致估算过低。为了让客户满意,产品必须达到一定的质量,质量保证流程应定义为 DoD。增加质量保证步骤会让开发人员认识到他们需要更多的时间来完成任务,以防止低估。下面列出了一些例子。
- 必须编写单元测试,覆盖率必须超过 80%。
- 代码审查必须由两名软件工程师进行。
- 质量检查必须由测试人员进行。
- 功能必须向产品负责人展示,以获得反馈和最终批准。
尽管 DoD 被定义为敏捷最佳实践,但也可以(或应该)用于瀑布式项目,因为无论项目管理类型如何,它都能带来巨大的好处。而根据项目的不同,DoD 也有很大的不同。
原则 3:避免完美
第三个原则是避免追求完美,这意味着估算只是最佳的猜测,而不是开发团队无论如何都必须遵守的最后期限。软件开发中的估算具有挑战性,因为任何项目都不尽相同。史蒂夫-麦康奈尔(Steve McConnell)是不确定性三角(The Cone of Uncertainty)的作者,他说,没有一个项目具有相同的需求、相同的人、相同的业务背景、相同的技术和相同的限制。因此,所有项目都包含大量的不确定性和不可预测性,这给估算带来了困难。
与其追求完美的估算,不如随着时间的推移不断提高准确性,这就是所谓的"Kaizen"或"持续改进"。在开发结束时,软件工程师会回顾实际花费的时间,检查估算时间与实际时间之间的差距,相互分享经验,并在下一次开发中加以利用。在敏捷开发(Scrum)中,Sprint 回顾是分享经验的最佳时机,估算时间也会在 Sprint 中得到改善。如果一个软件工程师被一个复杂的错误困住了,花费的时间超出了他的预期,他就会分享问题是如何解决的,这样其他软件工程师就不会被同样的错误困住。尤其是,必须分享瓶颈所在,因为这将大大提高估算的准确性。
另一个避免完美的技巧是估算范围,而不要进行精确估算,只估算最小值和最大值。例如,一项任务估算的最小时间为 3 天,最大时间为 5 天。不同项目的范围各不相同,应与产品负责人和业务人员协商。只要估算能帮助他们做出决策,范围大小并不重要。三点估算也是一种估算技术,有三个点:最坏情况、最好情况和最可能情况,是相同的概念。
三点估算
原则 4:集体知识
第四项原则是利用集体知识,即集体估算。这背后的理念是,由多人做出的估算会比单独估算更加精确。单人估算容易出现个人原则造成的疏忽,而多人估算则可以防止疏忽并提高准确性。
"三人原则"(Three Amigos)是敏捷最佳实践之一,即由三个关键人物(业务人员、测试人员和软件工程师)对需求进行审核,从而使集体知识变得有效。业务人员作为领域专家提出见解,软件工程师从技术角度进行检查,测试人员审查如何确保质量。如前所述,需求的质量和清晰度至关重要,因为它们对估算的准确性影响最大。
德尔菲法(The Delphi method)是另一种利用集体知识进行估算的技术。一组专家交换信息并进行多轮讨论,直至达成共识。德尔菲法也证明了集体估算优于个人估算,因此自 20 世纪 50 年代问世以来一直被广泛使用。
原则 5:不估算故事点
第五项原则是不做故事点的估算。尽管故事点被广泛提及,仿佛是敏捷中的最佳实践,但其实有几个关键缺陷。最大的缺陷是,故事点永远无法帮助业务决策,而业务决策才是估算的最终目的。在进行软件开发之前,首先要做的是业务。因此,我们必须基于商业中常用的指标来支持商业决策。即使我们对某个任务的估算是 15 个点,业务人员也无法知道应该如何处理,最终还是会问:"你什么时候能完成?"或者"完成这个任务需要多长时间?"软件开发不是发明或研发,而是业务。无论项目的类型是 BtoB 还是 BtoC,投资者或赞助商关心的总是投资回报率。
第二个缺陷是,速度(velocity)对企业来说根本不重要。当我第一次了解到"速度"这一概念时,对其印象颇为深刻。然而,经过进一步思考,我开始思考开发速度的含义。例如,我从未听到有人谈论过业务速度或商务速度。没有人会说:"这个月的业务速度是 500 点",并为此感到高兴。同样,没有人会关心软件开发的速度,听到本月的软件开发速度是 1000 点就高兴得不得了。真正重要的是截止日期和任务是否完成。再说一遍,软件开发就是业务。
我们必须使用常见的业务指标,如小时、天或周,而不是故事点,因为业务使用这些指标,而且与职业、国家等无关。只要有助于业务决策,项目之间的度量标准可以不同。
原则 6:粗略估算是可行的
第六项原则是可以进行粗略的估算。在大多数情况下,业务人员在提出想法和确定需求之前,都会要求进行粗略估算。应该采取的正确做法是,在提出粗略估算时,强调这只是一个粗略估算,极有可能发生变化。这有助于业务决策,而且在修改估算时也不会有人生气。
试想一下,乘坐出租车时,司机说"我不知道要多久"或"要 30 分钟到一个小时"。前者对你没有任何帮助,而后者可能会让你放弃打车,改乘地铁。正因如此,大多数共享出行服务都会显示到达目的地所需的大致时间,尽管并不精确,而且由于很多不确定因素(天气、意外事件、事故等),很难预测交通情况。
不过,如果你是分包商,而客户还没有付款,情况就不一样了。由于估价是关键信息,需要花费大量精力,因此很多人都会假扮潜在客户,试图套取估价。在这种情况下,应该将其作为讨价还价的筹码,并仔细考虑是否应该给出估计以及何时给出。在为软件分包商工作时,我看到过很多人和公司都在问:"请只要告诉我估价就好。"但最后他们从不付钱。
原则 7:越小越好
小任务使估算更容易,也更准确。敏捷最佳实践之一就是将任务(用户故事)做得足够小,以便在一个冲刺(通常为 1 或 2 周,最多不超过一个月)内完成。这是因为当任务变大时,软件的复杂性会呈指数级增长,而不是线性增长。例如,估算下一周能完成的任务比估算下一年能完成的任务要容易得多。任务越小,估算就越准确。如果发现项目任务过大,就应该把它们分解成几周内可以完成的较小任务。这种做法也同样适用于瀑布式项目。
软件复杂度和任务规模
除了估算的准确性,小任务还能提高质量,因为规模小,使得开发、测试和发布更容易调试,也更容易识别受影响的区域。而大型任务则会使软件复杂度成倍增加,成为滋生错误的温床。
原则 8:尽量独立
独立的任务可以提高估算的准确性。依赖性是软件项目中最大的挑战之一,因为很难识别并会增加编程的复杂性。独立任务的复杂性较低,有助于提高估算精度。
在估算和任务管理中,独立任务指的是可以完成并发布的任务,而无需处理或等待其他任务。虽然由于软件项目的性质,不可能消除所有依赖关系,但必须努力尽可能将任务与其他任务隔离开来。
随着需求定义的深入,依赖关系会逐渐清晰。但是,如果在需求定义后仍不确定,那么领域建模会有所帮助。领域建模是埃里克-埃文斯(Eric Evans)创建的领域驱动设计(Domain Driven Design)的一部分,它从业务角度说明了对象之间的关系,并澄清了依赖关系。DDD非常有效,正如 SAFe(大规模敏捷框架)所阐明的那样,"如果在敏捷中只对一件事建模,那就对领域建模"。
结论
估算的主要目的是帮助业务人员进行商业决策。业务人员根据范围、资源和时间这三个因素决定何时做什么,而估算与时间有关。他们的决策会因完成工作所需的时间长短而大相径庭。
- 原则一是明确不确定性三角的需求,对开发阶段和估算精度之间关系的研究表明,明确的需求对估算精度的提高最大。
- 原则二是在团队中定义完成的含义,即DoD。DoD 可以区分已完成的项目和未完成的项目,提高产出质量,防止低估。
- 原则三是避免尽善尽美,逐步提高估算的准确性。由于估算只是最佳猜测,而不是最后期限,因此当情况发生变化时,应通过协商进行调整。范围估算法和三点估算法通过范围进行估算,既能避免完美,又能帮助业务人员进行决策。
- 原则四是依靠集体知识,即与小组成员一起估算,而不是单独估算。这背后的理念是,集体估算比单独估算更准确,因为这样可以防止疏忽。三人原则:业务人员、软件工程师和测试人员,是审查需求以提高估算准确性的最佳做法。
- 原则五是不进行故事点估算。虽然"故事点"被广泛提及,似乎是敏捷的最佳实践,但无助于决策,尽量避免使用。没有业务人员会用故事点来做决策,这不是商业中常用的衡量单位。
- 原则六是可以进行粗略估算。在大多数情况下,业务人员会在有想法和确定详细需求之前要求进行粗略估算。在这种情况下,我们可以提出粗略估算,因为这对他们有帮助。但是,如果你是分包商,而客户还没有付款,就必须考虑是否应该避免提供,因为粗略估算是有价值的信息,很多人都会想方设法榨取这些信息,但不付钱。
- 原则七是越小越好。大任务会增加软件复杂性,成为滋生错误的温床。小任务能提高估算的准确性。此外,因为小任务更容易确定受影响的区域并进行调试,因此还有助于提高软件质量。
- 原则八是尽量独立。依赖性是软件项目中最大的挑战之一,会增加软件的复杂性。如果一项任务是独立的,就更容易估算。通常,需求越清晰,依赖性就越明显。如有必要,可以使用领域驱动设计技术之一的领域建模。