开发时间评估为什么总是差这么多

4,041 阅读11分钟

相信大家都会遇到开发时间评估短了的情况,如果是个人项目还好,晚了就晚了,但是在一个多人协作的团队里,开发完成时间总是延迟就很不好了,小的方面会影响自己的信用(总是不能准时完成承诺),大的方面会导致项目交付时间推迟,影响下一个环节的同事时间安排。因此我总结了一些会导致开发时间评估偏差的原因。因为我在的是一个小团队,所以一些经验未必会适合十人以上的团队。

估不准的根本原因

首先我们必须认清评估开发时间不准确的一个结构性原因:无法提前预估所有的实现细节,所以就会有偏差。 举个例子,我们知道 A 地到 B 地有 40km,已知我们的速度是 10km/h,那么我们可以评估出从 A 地出发到 B 地要多少时间吗?当然可以,这个评估谁都能做。那么类比到软件开发上,如果我们知道一个版本所需要的代码总行数,再计算一下一天能写多少行代码,这样就能得到一个准确的时间了。

这个解决方案的问题在哪里呢?

首先,我们不一定能确认我们要去的是哪里。可能需求做着做着就变了。 假设我们有了确定的需求,但是实现起来的方式也不是只有一种,路线也有很多种: 就算确定了实现方式,你还是可能会估错实现的速度,因为很多程序员总是过于自信。 总的来说,在项目开始的时候程序员还不太了解项目是实现细节(几乎不会遇到曾经做过一模一样的需求),因此无法做出一个合理的估计。不过随着你对如何实现做了越来越多的调查,误差会逐步缩小。在开始编码后,又会再一次缩小。在项目开始前,偏差最大的时候要求程序员做出一个准确的估计,然后不再修正这是一个错误的做法。

敏捷开发并没有解决这个问题

传统的开发方式开发周期比较长,最后开发完成时间偏差的比较大。敏捷开发里把每个开发周期缩短了,因此在每个周期里的偏差时间绝对值上少了,但是实际上并没有解决开发时间评估偏差的问题。

也有一种把开发周期改为日期驱动,定好一个日期后,到了这个日期就结束开发。每个迭代里都开发优先级高的功能,这样每个版本就都是价值最大版本。这种策略高级了一些,缓解了程序员秃头的压力,因为它放弃了评估开发时间这个问题。

但是逃避虽然有用,但是也不是每次都能逃避成功。还是会遇到功能驱动的版本。比如老板可能会突然对你说,我们要加个直播功能,你告诉我什么时候做完上线。我想你应该不会回答说等我做完的时候我再告诉你。

理解需求背后的业务场景

第一步要做的是理清需求。很多人拿到需求埋头开始做,做完以后和产品经理想要的不一样,时间肯定是耽误最多的。产品经理一般关注的是流程、交互,对技术方案的性能不是很理解。所以这边如果两边没有沟通清楚,两边的预期就可能不一致。比如用户的一组设置保存到服务器,是要实时自动保存,还是用户手动点击保存后才保存。是只保存一份还是可能保存很多份,有没有删除操作。最后都可能影响到开发时间的估计。

这个环节首先需要开发去理解需求背后的业务场景,这样我们才能知道技术要解决的真正的问题是什么。产品真正想要的是我们去解决一个业务问题,而不是最后我们有一个按钮。理解了业务场景后,就可以得出技术指标的要求,然后我们和产品经理确认技术指标。确认了技术要求后,也确认了技术实现方案。这个沟通做好了,就可以避免产品经理说这个需求很简单,为什么需要做 3 天。因为我们会告诉他 3 天的实现的方案缺点在哪,他是不是可以接受这样的技术指标。

记录开发中的需求变更

我强烈建议在研发流程中引入需求变更的统计。对开发时间影响最大的变量就是需求的变更。需求变来变去,虽然开发者投入了两三倍的时间,但是实现的还是一个需求。最后导致交付时间推迟,未必是开发者的问题。如果这中间没有记录呈现,可能最后团队里成员就会简单的以为是开发者开发的慢,或者开发时间估计严重错误。

如果要记录需求变更统计,首先就需要有一个明确的需求列表。需要开发者把产品经理的需求拆分成研发需求列表。每一条研发需求的功能描述都要在迭代开始前和产品、测试团队确认。因为我的团队是用 gitlab 管理代码,因此每个迭代开始前会拆分成一条条 issue。

进入研发后,如果需求不在研发需求的描述中,就会算一次需求变更。无论是需求漏掉了一个流程,设计图改了都要把变更记录更新到对应的研发需求 issue 下面。这样最后版本交付以后,就可以统计出因为需求变更导致的开发时间影响有多少。

开发中沟通效率

如果是团队中的开发,还要考虑到团队沟通的问题。接到一个需求,中间没有任务耽搁一口气开完的情况是很少的。你可能需要和产品沟通交互细节,比如问他如果这里操作失败要怎么处理。可能要和设计沟通,这个动效具体是什么效果,是 200 毫秒后消失还是 300 毫秒。也可能和后端沟通,这个接口的参数应该传什么值。又或者开发一个阶段后需要给其他成员演示效果。 这些团队间的沟通都发生在研发进行中。因此开发时间不仅是写代码的时间。评估开发时间的时候要把各个职能团队间的沟通时间计算进去。

开发路径依赖

假设一个版本中设计需要 3 天,前端需要 3 天,后端接口开发需要 3 天,那么 3 个人同时开发 3 天后能开发完吗?有过开发经验的人肯定都知道这三项工作不能完全的并行进行。那么是不是设计 3 天后做好设计图,前端就能百分百按照 UI 进入研发呢?其实也未必。

每个环节的对接并不总是能完美对接。设计图完成后交给开发可能需要沟通修改。后端接口交付到前端也有这样的风险存在,虽然两边接口文档定义好了,但是如果一个模块状态比较多,可能接入接口的时候还有一些问题。毕竟后端也不能保证接口开发一次性就能达到完美的质量。如果这个时候前端依赖后端的接口完整度,那么进度就被耽误了。

因此在开发时间估计的时候要把路径依赖计算进去。如果研发流程里没有设计评审,需要考虑到设计图完成后可能还会有修改。后端的接口虽然开发完成,但是不一定就能像预期的那样正常工作。比如后端计划 3 天后可以上线接口到测试环境,前端要预估半天或者一天调试接口时间。

别忘了代码还要架构设计

我觉得架构设计是程序员估计时间最容易忽略的时间。

太多的自信的程序员评估开发时间的场景都是有这么多代码要写,我开始飞快的敲键盘,需要要写多久。尤其是一个复杂的功能,模块、职责的划分的设计是需要不少时间的。甚至宁愿前期实现设计多花几个小时,避免写到一半发现发现扩展性很差推倒重来。

就算写的代码完成了功能性的要求,也并不意味着工作就完成了。对质量有要求的程序员这个时候还要 review 代码:可读性好不好,命名是否准确,代码的职责划分是否合理,要不要考虑未来的扩展性等等。在刚写完的时候审视是否需要重构肯定是最划算的,等到问题出现再重构,需要更多的时间去理解上下文。

如果你给自己安排了两天时间,两天时间刚好完成了功能开发。这个时候你忽然有强烈的预感,我还可以把代码优化一下,但是不想项目完成时间 delay,那就先这样吧。一个技术债就这样产生了。

架构设计还有一个问题是各个模块的 API 调用上。一个版本中几个人协作通常按照模块功能去划分。可能两个人独自开发一个组件,开发完成后连接起来的时候发现一方设计的 API 不合理。不得不说这是一个非常常见的问题,即使经验丰富的程序员也不能保证设计的 API 对于业务方完全合理。但是我们在开发时间估计的时候,常常忽略两个模块最后合并到一起的时候 API 调整需要花的时间。于是你的开发时间又估少了。

为了提高这部分时间估计的准确率,我在开发时间估计前会在研发团队内部进行接口设计沟通。会定义出数据流向的接口设计,这个环节团队的人都会参与讨论确认。各个模块间的 API,类的职责划分,数据结构都定义有了之后,大家各自开发设计部分需要花的时间就会偏差比较少。

代码的质量问题,如果研发流程中有 code review,就一定要把 code review 导致代码需要修改的时间算进去。这块的建议是核心的、复杂的类在开发前就先一起确认设计,避免在 review 的时候发现代码的设计完全不行,需要重写。其实只要把公开的接口定义好就够了。

兼容旧代码

自己开发的时间估计基本是可控的,但是如果你的代码要建立在祖传代码上时间就完全估不准了。

程序的需求总是在持续变化,如果早期的代码没有给新的需求做好扩展点,最坏的情况需要推倒重写。好的情况原来已经做好了扩展性的设计,只要几行代码就可以接入新的功能。

因此在估计开发时间的时候,一定要区分哪些需求是要在老代码上改的。尤其是如果你不熟悉原来的实现的时候,你基本上等于是瞎说一个数字。所以在这个部分一定要提前了解原有的实现细节,大概想好要如何实现后再估计开发时间。

别忘了还有自测的时间

有的模块测试起来是比较费时间的,如果有这样的需求开发时间中还要把自测的时间估计进去。如果不自测直接交出去,测试提出了很多 bug,最终浪费了更多人的时间。

总结

时间估不准的根本原因是研发过程中很多需要耗时的时间被你忽略了。也有一些你在做估计时没有确认工作量(比如架构设计、修改旧代码的时间)。把上面提到的这些点都计算到开发时间里,相信随着经验的成长你的时间估计偏差会越来越小。