前言
在软件开发过程中,团队往往会有一个疑问:「工时怎么估才会较为准确?」对项目或产品的 owner 来说,这是他们衡量项目资源与时程很重要的一项信息,然而实务上却因此造成了许多问题。
许多开发人员总觉得 PM 根本是用 deadline 来回推工时的,他们根本不在乎时间内该 feature 是否能有质量的完成。「先求有,再求好」这句名言也因此在软件产业流传许久。
许多 PM 则总是觉得开发人员估工时都是灌水居多,平常看他们的工作状况好像都在摸鱼,看起来好像都是用业界流传的估工时方式:「先估个 3 倍时间当 buffer。」
事实上工时的确是无法估到「绝对准确」的,但可以采用一些方式来估到「相对客观」。因工时与需求的复杂度,往往呈现正相关,因此本文会先针对需求复杂度来说明目前常见的问题,提出一个建议的解决方案,以及解释解决方案中诸多设计的目的。
Problems
开发人员的地雷
· PM:「这很简单啊,应该不需要花太久时间就可以做出来吧?」
· PM 今天跟你说:「明天之前就是要交出来,先求有再求好。」
PM 后天跟你说:「为什么程序的质量这么差?」
· 已经 delay 的时候,其他同事:「你这怎么需要花这么久的时间?这有现成的 code 可以参考,这有做好的底层可以使用啊,你怎么没问我?」
· 其他同事:「这我只要一天,为什么你要这么多天?」
· PM:「这是 common sense 啊,需求即使没提,你也应该知道这要做。」
PM/PO 的地雷
· 内心OS:「为什么这么简单的东西,要花这么久的时间?」
· 内心OS:「为什么都看到你们在逛 Facebook ,东西却来不及做出来?」
· 内心OS:「为什么做出来的东西质量这么差?」
· 内心OS:「为什么他上次一天就做出来,你要做这么多天?」
· 因为规格或需求没写清楚,被开发人员讲成需求异动。
结果
· 角色敌对:需求单位与开发单位不再是为了交付一个可以带给使用者效益的产品,而是为了自己的目的,为了避免自己需要负额外的责任,而彼此攻讦。因此造成需求单位与开发单位根本不是一个团队的情况。
· 责任推诿:团队想的都是「我没有错,所以 delay 不是我的责任」,而不是把使用者需求放在最优先。
· 需求冻结:开发人员因为 deadline 的压力,所以要求需求不能改,否则会 delay ,责任又要算在开发人员头上。所以要嘛吵输了,加班赶工出来诸多 bug 的产品;要嘛吵赢了,做出不符合使用者需求的产品;而这两种都会降低使用者的满意度。
· 质量低落:台湾的环境中往往 PM 的职级地位比开发人员高,因此最后为了满足合约上的 deadline 或避免罚责等等,就会以「先求有,再求好」要求团队,但最后往往是「先求有,没时间求好」。技术债累积越来越多,结果就是现实世界的责任链模式,在链的最末端得扛最大的责任与成本。所以团队就像 stack pop 一样,开发人员受不了一个一个逃走,这也是为什么项目公司工程师流动率往往很高的因素之一。
· 养 code 自重:为了效率最佳化,永远都是用最熟悉的人的立场来估工时,所以永远都是最熟悉该模块、流程的人来处理相关的需求。最终也只有那些人能维护自己的程序码,那就像个潘朵拉的盒子,你永远不知道打开之后会跑出哪一些牛鬼蛇神。因为黑箱,往往就会藏污纳垢,但公司也没辄,你还要求神拜佛希望他不会离开,否则那一些程序码就没人看得懂了。
Solutions
这边所建议的解决方案,是在 Scrum 中很常用来估算需求复杂度的方式,但即使不是 Scrum 的团队,建议读者也可以依据其中的原则与设计目的,来找出最适合你们团队的估算方式。请记住,没有银弹,别人的 best practice 不一定适用你的团队,所以请先了解你团队目前所碰到的问题为何,然后针对问题从别人的 practice 找出适合自己的解决方式,只要没衍生出新问题,或是新问题的成本风险可被接受。
这边用来估算需求复杂度的单位为 story point (相对单位),而非工时(绝对单位)。这么做有几个原因:
1. 比较不会因人而异:需求的复杂度往往不会因人而异,实作所需要的时间才会因人而异。
2. 「相对」比「绝对」容易评估:若以工时来看,会比较需要估出绝对的数字,而且估算过程中会需要思考实作细节。用 story point 来估算复杂度,则只需要与其他需求进行相对比较大小即可。举个例子,就像你很难明确指出「台北101有几公尺高」,但你比较容易指出「台北101大概比高雄85大楼高出约 1.5 倍」。
3. 估算 story point 压力比估算工时小:关注在需求本身,而不用顾虑自身的资源与项目的资源,单纯评估需求的复杂度。估算过程中,团队成员压力较小,就像游戏般地进行软件开发的其中一个环节。
虽然需求复杂度往往与工时正相关,但因为实作情况不同,实务上还是有可能出现 story point 高的 feature,工时比 story point 低的需求来得少。但在 Scrum 中,可以透过 iteration 的 sprint 来评估,每一次 sprint 团队可消化的需求复杂度大概有多少。对 PO/PM 来说,与其估出一个达不到的时程,还不如估出一个较为精准客观的时程,让他们可以在第一时间了解,离项目预计的时程还有多远,如果资源有限,该如何安排需求的优先级,或是寻求其他支援。
接着针对解决方案的各个面向,进行说明。
When
· 在还没有决定需求由谁来做之前,进行评估:这样做的好处是,把开发人员的个人因素降到最低。因为不知道由谁来做,所以也无须所谓的 buffer 、灌水,或是因考量自身身上的任务或 deadline 而导致估算失真。
Who
· 只有要做事的人一起进行评估:两个重点,第一:只有做事的人可以估。需求单位所估算的工时或复杂度是不客观的,因为他们不是实际做事的人,没有权力左右开发团队依据需求评估的数字。如此也比较能避免发生由 deadline 来左右需求复杂度的评估。第二:做事的人一起估。因为不知道由谁来做,每个人一起估出来的数字,经过讨论与重新估算后,才容易取得共识。每个人都有参与,会比较有参与感,也因为每个人都有参与,估算结果是大家一起决定出来的,所以未来由谁来做,都比较不会有所怨言。
What
使用 Planning Poker(费氏数列卡片)来估算 story point。
类似费氏数列的 index card
费氏数列有一个有趣的特性,每一个数字都是前两个数字相加。另一方面来说,越大的数字与下一个数字的差距会更大。如上图,8 与 13 的差距为 5 ,而 13 与 20 的差距为 7 。这跟估算需求复杂度有什么关连呢?我们不是在上数学课啊。
估算也有个特性,就是越大的越估不准,把较大的需求或任务切到粒度较细时,往往估算起来就会比较精准。就像一个杯子中如果装的都是大块不规则的石头,那么中间的缝隙会比较多,这就是失准或浪费的部分。如果装的是粒度较细,一样不规则的石头,缝隙相对会少一些,而且容易进行调整,能比较方便地填满缝隙。
即使是前面的数字差距比较小,也没有关系,因为本身数字小,代表挪动弹性大,风险低,如果因为某些因素时间估算失准需要调整,前面小数字的任务,大概就是加班 20 分钟,而不是加班 2 天或 5 天的情况。
因为大的数字差距较大(费氏数列两个前后值的差异比率趋近于 1.618),所以能避免估算时发生「到底这个复杂度是 20 还是 21 」的情况。要嘛 13 ,要嘛 20 ,要嘛 40 。这样的级距差距可以突显出大家对同一个需求估算的差异,因为几乎都差了 1.5 倍以上,这比例对人类在判断相对大小是相当容易的,也因此可以减少许多细微差异所引起不必要的重新估算流程成本。
另外,上面的图片可以看到有几个特殊的数字,分别为 0、无限大、问号。0 可能代表这个需求根本不需要作,或是已经完成了。无限大,则代表需求明确,但超过最大的那一张数字卡,代表这个需求需要再被细分成多个粒度较细的需求。问号,则代表需求有不明确的地方,需要 PO/PM 再说明或厘清清楚。
How
1. 先定义出复杂度 1 的单位为何,例如一个单表综合查询的功能。因为我们的估算过程,是采相对比较大小,先定义出比较基准的单位,后面团队估算时才有个比较的依据。
2. 由主持人大声唸出需求说明(例如 User Story Card),确定大家都了解需求后,每个人一起呈现自己所预估的复杂度。建议用 planning poker 的原因,是因为可以同一时间呈现大家评估的数字,而不是轮流说出自己评估的数字,轮流说出数字容易造成后面的人估算的结果,被前面的数字影响而失真。
3. 若团队中存在不同的预估数字,则由估最小与最大的两人说明,自己评估为什么觉得复杂或单纯的原因。以上面的例子来说,在估算的过程,倘若出现有一人估算 story point 为 13 ,大部分人估算为 20 ,有另一人估算为 40 。13 与 40 几乎差了 3 倍,那么基本上一定存在某些重要信息没有被同步到。例如估算 13 的人觉得这个需求与过去某个需求几乎相同,而这个需求并没有想象中的复杂。而估算 40 的人可能因为对这个需求或流程不够熟悉,所以觉得应该相对复杂。
4. 最小与最大数字评估原因说明完毕后,再进行一次投票。如果投票结果仍存在不同的数字,且绝大部分的人有共识,没共识的预估复杂度与有共识的复杂度只差一个级距,则可以询问估算不同数字的成员,是否可以接受大家所评估的数字。
5. 如果数字仍有差距一个级距以上,或是无法获得共识,则重复步骤3~5,直到取得共识为止。
再次强调,只有实际会执行任务或完成需求的人可以参与投票的过程,PO/PM 不能干涉。
这里有个 15 分钟左右的影片,用来说明在 Scrum 的 Refinement meeting 中,各角色该如何估算 story point,我觉得解释地很清楚很好懂,提供给大家参考一下:Backlog Refinement Meeting
Why
透过这样子的估算方式,会有几个优点:
1. 由做事的人共同决定出一个合理客观的预估结果,有参与感且无怨言。
2. 决定的结果是 PO 与 team 的共识,减少未来针锋相对、各说各话的情况发生。
3. 每个人都可以了解需求,未来每个人都可以担任实作这个需求的人选,当需要支援时,也随时可以有人一同开发或备援。
4. 在还没动手作之前,就可以把需求不明确的部分,有疑虑的部分厘清。
5. 在还没动手作之前,就可以在团队中找到大家认同最好最有效率的实作方式。
6. 除非整个 team 都是灌水的人,否则这个数字就反映了团队共同认知的事实,PO 可从中了解需求与评估实作中间的落差。
7. 透过比较需求之间复杂度的相对大小,未来 PO 对评估 iteration 可能可以承诺完成多少需求,也会有个比较的基底。
结论
透过上述的估算过程,这样的决定公开、透明、客观且有共识。对两个角色而言:
· For PO/PM:
o 不用担心被某些特定的 member 呼咙或灌水。
o 评估过程中了解需求或任务在实作时,潜藏的难度在哪。
o 了解需求是否还有需要说清楚或被误解的部分。
· For team:
o 不再是不做事的人依照 deadline 给予一个不合理的时程限制。
o 在还没开始动手进行任务之前,属于开发人员之间的知识交换。不论因此增加或减少估算的数字,都让需求更明确,预估更客观。
o 因为还不知道由谁认领此任务,所以客观且有共识,透过过程也可以知道谁对此任务熟悉度比较高,实际进行时,可以结对编程或知道找谁询问与协助。
本文建议的解决方案,是一种 common solution ,重点不在于形式,而在于中间每个环节的设计目的,是为了解决什么样的问题。而这些问题,不一定存在于每个团队。
因此建议读者,如果你们团队也有估算需求复杂度或工时的问题,可按照那样的方向,把它改变成适合你们团队的进行方式(例如你们一开始仍习惯工时,而不是 story point )。记住,如果没有问题,就无须导入对应的解决方式,因为没有效益,那会变成只是为了作而作,为了改变而改变,可能反而会造成民怨喔。
后续 >> 估算需求复杂度(2)Dog Point Game