作为架构设计人员或技术开发人员,相信你一定被问到过下面的问题:
- 有个新需求,请帮忙粗略估算下完成这个需求大概需要多少工作量
- 现在有100W预算,请帮忙估算下够不够完成这个需求的开发
- Story卡已经写完了,请帮忙做下详细的估算,看看我们需要多少开发资源
- 线上这个问题原因已经找到了,请帮忙估算下最快多久能修复
在软件开发的不同阶段,我们都会因不同的目的需要做估算,比如需要分配资源时、需要排开发计划时、需要评估成本时等等;然而,有些场景下我们也会发觉一些估算的理由很牵强,甚至是需求本身就不是很合理,感觉单纯是“为了估算而估算”。那么估算都有必要吗?如果有必要这个估算该怎么做呢?
为什么要做估算?
首先我们来回答第一个问题,要想知道估算是否有必要,就要先弄清楚估算的意义,估算到底帮我们解决了什么问题,这样才能明确目标,才能设计合理的方案,才可以判断是不是一定要通过估算来解决这个问题。
Martin Fowler在他的文章《PurposeOfEstimation》中详细阐述了为什么要做估算:
Estimation is valuable when it helps you make a significant decision. 估算是为了帮助我们更好的做重要决策
没错,回想起需要做估算的场景,我们都是需要估算的结果作为输入来帮助做决策,文章开头的一些问题也对应着一些典型的需要做估算的场景,比如:做资源规划,成本估计,安排开发计划,或者评估一个需求的投入产出比等等,在这些场景中,估算可以帮我们理清做一件事情所需要的人力成本和时间成本,进而帮助我们来做出合理的决策。
明确了估算在决策当中所起到的作用,我们就可以判段当前这个决策是不是一定需要估算作为输入,说到这里,当然也有一些软件开发活动并不需要估算也能顺利开展,感兴趣的可以阅读《PurposeOfEstimation》找到一些不需要估算的示例。
如何做估算?
明确了估算的意义,那如何做估算才能算是有效的估算,才能帮助我们做出合理的决策呢?从估算在软件开发过程中所处的阶段,可以简单的分为两类:
- 开发团队介入前的需求成本估算
- 开发团队在进入开发阶段前的Story估算 然而不管是哪种估算,正常的流程应该至少包括如下的步骤:
- 理清业务需求
- 确定技术解决方案
- 将要做的事情拆分成任务
- 针对每个任务做出评估
有效的估算应该关注什么?
上面的流程很简单,但不同的人遵照这个流程得到的估算结果可能会是不同的,一方面不同的人给出的解决方案可能是不一样的,另一方面不同的个人经验也会导致任务拆分结果的差异,进而导致估算结果的差异;
估算结果的差异并不代表估算是有问题的,因为做估算基于的前提条件是有差别的,那么怎样才能保证估算的结果可以满足帮助我们做决策的要求呢?在整个估算过程中,我们要重点关注以下几点:
- 明确估算粒度 估算粒度决定我们的设计要做到多细致,估算的解决方案要做到多细致。通常开发团队介入前的需求成本估算,目的是用来判断完成这个需求大概需要多少成本,粒度会比较粗;而开发团队进入开发阶段前的估算,目的是为了做详细的开发计划,粒度会比较细。
估算粒度的大小可以指导整个估算过程的进行,避免大家陷入无休止的细节讨论之中,当遇到问题争论不休时,我们可以立刻问一个问题:这个争论的结果会影响我们的估算吗?如果不影响,可以在后面有了更多输入的时候再进行讨论;如果有影响,那就要尽快找到可以做决定的人来进行决策。
- 需求理解一致 在流程的第一步通常是业务分析人员对业务需求进行讲解,阐明需求设计的业务价值,当前的业务现状,需要做的改动,以及交互设计的一些细节;
在这个过程中参与估算的架构设计人员或开发团队需要理解需求的全部内容,并结合自己对当前系统的理解评估新的设计和改动是否和既有的实现有冲突,及时给予反馈,对设计上不理解的地方及时提问,保证大家对业务需求的理解在同一个层次上,这样才能保证后续解决方案的合理性以及估算的合理性
- 估算应该是协作的结果 为了确保估算的相对准确性,在敏捷开发中当Story卡准备好之后,通常整个开发团队都要参与到估算当中,估算较高或较低的同学要给出理由,尽量避免因为上下文不一致导致估算的偏差。
而对于粒度较粗的估算往往会忽略这点,一方面粒度较粗,不需要特别细致,准确性往往会被忽略;另一方面在软件开发初期能够做估算的人力资源有限;然而,这个粒度的估算对决策的影响往往更大,估算偏差较大对软件开发项目的影响是巨大的,可以试想一个场景:在最初的成本估计过程中,如果低估了项目的复杂性,给出了较小的估算,一方面在开发过程中不断涌现的复杂性,对开发团队来说是不可预期的,会影响开发团队对整体开发进度的控制程度,另一方面没有足够的预算,很有可能导致项目开发到一半因为资金不足而失败。
因此,在做较大决策相关的估算时,建议尝试建立解决方案Review小组,估算的结果在小组内进行评估,确保不会产生较大的偏差。
- 明确估算基于的假设 从估算的基本流程可以看出,估算是基于一个假定的解决方案,不同的解决方案的估算可能会有很大的差异,比如:
现在要把一个文件里的内容导入到生产环境的数据库中: 解决方案可以有两种:
- 人工解析文件内容,转化为SQL,将数据写入到生产环境的数据库中
- 开发一个功能,操作人员可以通过Web端选择文件上传到生产环境的数据库中 两个方案都可以解决问题,但不同的方案的优缺点也是明显不同的,影响也是不同的,因此在估算给出的同时,要明确指出估算基于的假设,一旦假设不成立,我们就需要进行重新估算。
估算需要考虑哪些因素?
前文提到不同的人对同一个需求做估算,结果可能是不同的,因为解决方案可能是不同的,估算的假设前提也可能是不同的。从团队的视角出发,不管是解决方案小组来Review估算,还是开发团队一起来做估算,我们可以认为解决方案是一致的,假设前提也是相同的,在这种情况下怎么能保证不同的人给出的估算是基本一致的,是符合团队预期的呢?
本质上来说是要消除人的经验对估算产生的影响,因此我们要尽可能多的找出影响估算结果的因素,在每次估算过程中,大家都要通过各种问题来澄清这些因素是否会对估算结果产生影响,以及会产生多大的影响。
经过大量估算的分析,我们认为以下因素会对估算结果产生较大影响:
- 技术难度,新的技术/框架的引入
- 业务逻辑的复杂程度
- 交互设计的复杂程度
- 第三方的系统集成难易程度
- 数据量级,数据迁移的复杂度
- 是否破坏已有功能
- 跨功能性需求,比如性能、数据安全等等
- 对基础设施的需求
之前项目上的同事为了保证不同的人在估算过程中能够尽量给出符合团队预期的结果,设计了很多问题帮助大家在估算时理清需要考虑的因素,我整理了一下,供大家参考:
类别 | 问题 |
---|---|
前端 | 是否需要引入新的前端组件/框架? |
是否需要修改/复用现有组件?这些组件在哪些场景使用? | |
是否包括较多的样式细节调整? | |
是否有特殊的异常处理逻辑? | |
是否涉及较多的业务场景(组合情况)? | |
是否有复杂的交互逻辑和校验逻辑? | |
与后端服务的集成逻辑是否复杂? | |
后端 | 是否需要新建/修改API? |
是否会大量改动现有代码/测试? | |
是否有大量的跨服务交互? | |
是否有比较复杂的业务流程控制? | |
是否有新技术的引入,需要做进一步的调研? | |
是否有性能风险?涉及数据量级有多大? | |
是否需要写大量的测试代码(单元测试、契约测试)? | |
数据 | 功能验收的数据准备是否复杂? |
是否需要新建数据表结构? | |
是否需要做数据迁移?数据迁移的数据量和复杂度有多大? | |
当前数据结构的修改是否会影响到其他功能,比如报表、ETL任务等? | |
系统集成 | 是否包含系统集成? |
是否需要在集成中考虑失败重试的场景? | |
是否需要考虑集成接口的幂等性? | |
系统集成逻辑和场景是否比较复杂?是否有很多异常场景需要处理? | |
集成对端系统是既有功能还是新开发的? | |
是否需要在系统集成过程中做大量的沟通工作? | |
系统集成测试环境的搭建是否困难? | |
系统集成的联调工作是否容易开展? |
结语
估算在整个软件开发周期当中起着非常重要的作用,往大了说,它可能决定了整个项目的开发资源配置,它也可能决定了整个项目的开发周期和交付节奏,它甚至也可能决定了一个项目还未开始就不会继续下去。因此,在做估算之前,我们要清晰的认清这次估算在接下来的决策中到底起到什么作用,估算可以帮我们解决什么问题。
然而,在整个世界都在高速发展的大环境下,唯一不变的就是变化,敏捷软件开发也因其能应对需求的快速变化而成为主流的开发模式。估算是基于一定的假设前提,在一定的上下文下才成立的,一旦假设发生变化,估算就失效了,我们需要重新做决策,必要时估算也需要重头来过。