@Lenciel

技术团队的绩效度量

最近在TGO做了一次关于绩效管理的分享,slide发出去之后,很多朋友希望知道具体讲了啥,就在这里整理一下。

作为技术管理者,我们经常要回答下面这些问题:

  • 作为成本中心为什么还要这么多人?
  • 提个需求怎么折腾这么久不能上线?
  • 我们的研发为什么没有996? 不够拼啊?
  • 你们究竟怎么说明自己的价值和人效?

每次我们被问到的时候可能心里面都充满了委屈或者辛酸。以“要不要搞996”为例,本质上这无非是“人月神话”的衍生物:通过增强人手或者工作时间来更快地完成软件系统的开发工作。如果是短期内目标非常明确并且业务发展需要,可以搞一下。如果把它当成灵丹妙药,那就真的只会把团队拖垮,把能干的小伙伴逼走了。

所以,这里我们来尝试讨论一下团队的绩效如何可以科学的进行度量。需要注意这里说的是团队的绩效,在货车帮技术团队的个人绩效是结合KPI和OKR两种手段来给每个人制定的。

首先是度量

能够被度量的,才是能够被考核,从而有提升的。

但是,要量化互联网行业里技术团队的输出是很困难的。有人可能会争论说,有很多的“手艺活”,比如画画,比如陶艺,仍然是可以通过工时或者计件进行绩效的度量的,为什么软件行业就不行呢?

首先,和生产制造或者销售等工作不同,技术工作的产出是“无形的”,在财务上资本花的时候也是算作无形资产。

其次,虽然在软件工程的早期,这个行业被类比成建筑行业:我们的架构师跟建筑师一样叫做Architect,瀑布开发流程也明显有很多建筑体系的影子,甚至今天我们还自嘲是搬砖的。但实际上同一个建筑设计图,拿给两个合格的建筑施工队,工期和交付的产出应该都是基本一致的。而同样的需求,两个不同的技术团队不管是工期还是产出物,甚至可以说没有一行代码是一样的。

再次,整个技术工作对工作量的估计和任务的拆解是非常主观的。特别是进入敏捷时代了之后,研发的各个阶段工作并不是顺序发生的。很多时候测试还在进行这个迭代的测试,产品已经在整理下一个迭代的需求了,要把一个周期内的工作量度量清楚,更加困难。并且敏捷流程本身其实也是有代价的。

最后,核心的问题在于,软件本身的复杂度,造成了它的工作量本身就很难被评估。

旧手段的问题

过去我们衡量绩效的核心是放在工作效率(productivity)的衡量上的,它有下面几方面的问题:

  • 关注输出的总功而不是有用功
  • 关注个人的输出而不是团队的
  • 关注productivity而不是performance

下面我们挨个看看最常用的一些手段。

计算代码行数

计算代码行数是国内很多公司,包括华为这样的大公司都常常在用的指标。只要稍微理性一点我们都知道,同样的问题被10行代码解决了,要比1000行代码好得多。我们每天都说要还技术债,实际上代码本身是最大的技术债:一旦有代码被写出来,它的维护和变更都会产生巨大的代价。但,同样的,另一个极端:用尽量少的代码解决问题,也不值得推荐,因为如果太tricky的话,没有人看得懂,可维护性会变差。

计算story points

story points更多的是一个velocity,用来衡量团队的capacity,它本身连productivity都说明不了。用它来作为绩效标准会有两个问题: 1. 它是对某一个团队自身进行衡量的相对值,不能用来作为团队之间的比较。并且同一个团队处于不同的上下文时输出也不一样。 2. 一旦被当成绩效,团队会把“完成”尽量多的story当成目标,可能造成有用功比例降低,甚至是影响团队之间的协作。

记录工时

记录工时等都算是统计资源(包括人和各种别的生产资料)利用率的一个变种。但是高资源利用率意味着团队其实没有时间来响应需求的变更,插入,以及现有系统的优化。

数学里面的排队原理说明,一旦资源利用率达到100%,lead time就会趋于无穷大。也就是说,当你资源利用率非常高的时候,很可能你要完成一个事情的时间是趋于无穷大的(到处都是死锁)。

我们怎么度量

好的衡量方式应该有两个关键:

  1. 应该关注整个团队的总体有效输出:比如在过去一个典型的情况是我们对研发衡量他们的产出,对运维衡量他们的稳定性,于是研发把一堆有问题的代码直接扔给运维;运维开始制定一系列规则繁复的上线流程来保障稳定性:最终都影响了作为团队的整体有效输出。
  2. 应该关注有用功,而不是总功。

在找寻符合这些标准的数据的过程中,我们最终锁定了四个指标:

  • delivery lead time
  • deployment frequency
  • mean time to restore service
  • change fail rate

Lead Time

在Lean Theroy里面,衡量lead time是一个非常核心的概念:它是指从用户提出一个需求,到这个需求被满足的时间。在软件开发的上下文里面,lead time分两部分:需求被确认,解决方案被设计出来,变成一个产品或者产品的一个功能;功能被开发出来并经过测试验证,并最终上线到用户可用的时间。

前面这部分是很难找到一个比较确认的开始时间的,并且它的输出也是比较模糊的。然而后面这段,设计确认了之后,从实现到测试到发布的时间,是比较好衡量的。

因此目前我们主要是统计代码从提交到真正进入生产环境需要的时间。这个时间越短,就说明我们响应用户需求以及解决线上问题的速度更快:

是一个小时内?一天内?一天到一周?一周到一个月?还是更久?

Deployment Frequency

lean theory里面还有一个很重要的指标是batch size。但是因为软件的batch size很难衡量,所以我们考察部署的频率:

  • 是按需的
  • 每个小时或者每天一次
  • 每天到每周一次

客户端系统要提高部署的频率,就需要有插件框架,支持不通过应用商店发布版本让用户获取更新。

MTTR

除开通过前面两个指标度量软件发布的能力,我们还需要度量系统的稳定性。传统上这是靠MTBF(mean time between failures)。但是因为现在的系统复杂度非常高,bug基本上是无法避免的,所以我们变成了另外一个维度:出问题时,多快可以恢复,也就是Mean Time To Restore。

Change Fail Rate

最后一个关键指标也是跟质量有关的,就是针对生产环境(包括了灰度环境)的变更(包括release和配置两个维度的变更)失败率(是否导致了服务降级,服务失效,需要hotfix/rollback/patch)。

其他指标

确定了这四个指标,还需要确定一些会对核心指标有影响的可量化指标。

平均进行中任务数

Working In Progress状态的Jira任务/项目人数

一个软件项目里的工程师需要快速地在计划、开发、审查和修复bug之间轮转工作角色。如果任务队列过载,队列上的事项就会出现积压,比如工程师开发代码时收到了新的特性请求,或者被要求参加评审会。

建议把这个指标逐步控制到至少2.0以下。

进行中任务总数

进行中状态的Jira总数

可以反映出正在同时进行的项目数(可以根据项目Jira的拆分力度,看看是统计story这一级,还是epic这一级)。

代码规模

过去三个月项目repo的commit数量

代码库和代码库里面增加的代码并不是越多越好,也不是越少越好。如果过多,其实就像实体经济一样,你的“库存”就多,代码一旦编写,就需要进行编译、部署和发布,就需要人进行维护。库存里的代码数量如果多到一个程度,对用户真正有用,交付了价值的代码比例必然是低的。

平均功能数

产品环境配置文件数/项目人数

如果说平均进行中任务数主要反应研发人员的“开发”工作量,平均功能数则主要是反应“维护”工作量。如果一个团队的平均功能数过高,工作的质量就会严重下降,公司可以根据这个来调整团队的人数或者是进行项目的分摊。

Bug数

每个项目的Bug总数

这个不用多解释,如果Bug多了,“需求消化时间”和“功能迭代时间”自然就上去了。

完成全部挤压需求的预期时间

项目平均“需求消化时间 * 挤压的需求数量

大量积压有三个负面影响。首先,它会不断增加了我们的“需求消化时间”,因为过多的需求堆积,会导致团队无法快速完成工作,而是陷入大量的对优先级的安排和争论中。其次,它降低了我们在未来改变计划的灵活性。最后,它降低了团队成员的积极性。

确定了这些指标之后,我们通过对Jira/Confluence/ReviewBoard的打通,来进行工具化、无侵入的指标收集,在不影响大家干活的前提下,形成项目情况的大看板。