【程序员度量】改善软件团队的分析学

根本就没有完美的团队这回事,并且也不存在最好的团队。但是,当你见到过卓越的团队,你会了解它。通过计划和思考,成功团队的模式可以识别出来,并且只要我们愿意,好的团队,甚至是优秀的团队是可以规划和打造的。


更新历史

  • 2022.10.09:完成初稿

读后感

不同阶段的团队需要不同的组织形式和执行机制,不能死板,更不能一成不变。数字一般来说不会说话,量化和透明是最简单的开始。完美团队是地平线,可望不可即但要不断追寻。

读书笔记

我见过一个简单的模式,或许你也看到过:我曾经所在的每个成功的软件开发团队中,总是至少有一位同事无怨无悔地去做一些琐事,比如创建安装程序,改善编译脚本,或者修改一些其他人的错误来帮助团队实现产品功能。如果团队里没人去做这些琐碎的事情,那些项目就总是无法完成,或者至少是做得不够好。

另一种模式是:我见过很多经验丰富的软件开发团队,其中一般都有一到两位程序员在充当明确的技术领导和关键人物,虽然他们未必拥有与之对应的头衔。这些关键的程序员不仅解决问题,而且他们对其他人产生了强大的影响力,比如其他的程序员技能飞速发展,越来越接近技术领导者的水平。其最终结果就是,一到两个牛人提高了整个团队的水平。

这里还有我在曾经亲身参与的一个长期项目中观察到的一个模式,这种模式尤其常在处在创业阶段的小团队中发现:当项目进展到80%的时候,项目团队往往就“撞墙”了。像马拉松运动员跑到20英里标志点一样,项目团队经过几个月的努力奋斗,每一个人都身心俱疲。有时候当团队遇到困难时,我们就停滞下来,并且无法重获生机。这样项目剩下的20%工作量似乎永远也完不成,最后,我们基本上都是跌跌撞撞地走向终点。但有时某些团队可以穿越那堵墙,重新恢复生机,再次调整好步伐。在任何情况下,能够重获生机源于团队中一些人的优秀品格,他们能够减轻团队的工作负担,营造轻松的工作氛围,鼓舞团队士气,并让每一个人都感觉良好。感谢团队中那些爱开玩笑的伙计,他们让团队中的每一个人重新找回(多数是)积极的心态,准备冲刺到终点。

目前绝大多数软件开发团队所使用的度量,一般是项目估算或项目管理过程中的一个简单的计数集合。我们使用bug数量、任务数、时间增量(时/天/周)以及敏捷团队中的故事点数(story point)和速率(velocity)来度量。项目估计中也有些更复杂的系统和工具,如使用千行代码量(KLOC)和功能点之类的数据进行规模度量。

但我们常用的度量标准没有提供足够的深度来回答我们所面对的很多关键问题,例如:

  • 我们的软件开发团队可以变得多么优秀?
  • 什么样的团队成员才能有助于团队的成功?
  • 哪种能力的提高有助于团队取得更大的成功?

度量的第一个目的是帮助你跟踪和理解发生了什么。尽管对事件的主观观察有时是非常具有洞察力的,但也经常带有个人偏见和经验色彩。在观察时,人们常被自己注意的细节和习惯的方式所左右,而且易于错过一些自己未曾注意到或识别的事情。

度量的第二个目的是帮助人们沟通发生的事情。度量本身成为术语的一部分,允许一组人在讨论一些情境的时候,对大家讨论的同一件事有一定的信心。定义和命名度量迫使你澄清你用于沟通的语言。没有这样的定义和清晰的术语,在沟通的时候,你会更容易进入误区,或者甚至都不能够很好地讨论那些事实上非常要紧的问题。

度量的第三个目的是帮助人们关注那些他们真正需要改善的事情。度量记录了你所做和所完成的事情,并且给出了一个关于你的期望水平和实际水平的比较。缺少参考点将使得你很难知道目前所处的水平,到底还有多长的路要走,是否已经实现了目标。

虽然不应该严格地认为度量是评级,但不可避免的事实是,任何好的度量系统都无法避免地识别出人与人之间的必然差异。在组织中,如果人们通过劳动获得报酬,并且他们的工资标准与他们的贡献和技能密切相关,那么好的度量数据与工资标准和其他额外津贴就存在着一些关联。但无论如何,你不应该因此而太过于在意捕捉和利用度量,或者认为人们会试图伪造数据。

另一个重要的模式是,度量可以帮助我们确认一个人对团队中其他成员的影响。例如,优秀的程序员,可能使其他程序员黯然失色,也可能帮助其他程序员更迅速地提高他们的技能。最难识别和确定的是那些涟漪效应的模式,但是一旦发现这种模式,这可能带来最大的价值。个体对团队的正面影响或负面影响是决定团队是否大于或小于个体之和的重要因素。

一个简单的例子是,在很多成功的项目中,我们可以发现团队拥有很多相互帮助的程序员,但是在那些失败的项目里,程序员之间的互动很少。如果这是真的,为了提高未来项目的成功,让团队里的每个成员都了解这一点是非常有帮助作用的。度量帮助我们确定这样的模式,并且有助于与他人交流我们的发现。

我们不能由于没有获取太多的度量数据而简单地认为度量是没有用的。反之,我们应当承认度量的局限性,尽可能使用那些度量所能提供的好处。对于更好度量的探索不会停止,没有尽善尽美,有更多的东西等待我们测量和学习。

我意识到虽然不断增加的干扰正在骚扰程序员,但事实上也在帮助他们。这将让他们去思考更多真正的用户问题,了解更多人们感兴趣的是什么,并且让他们对质量和技术更敏感。频繁地与外界打交道,开发团队会变得身心健康。受到干扰之后,需要花一点时间重新回到编程状态中,但是程序员会多知道他们之前并不知道的一些事情。这种结果有利于编写好的软件,以及获得更新颖的解决方案。从那时起,一旦我看到了这种模式,我就能一次又一次地再看到它们。

我习惯性地认为打断是一件坏事情,我曾试图在工作时间把我自己和程序员遮蔽保护起来。今天,我依旧避免那些安排在一天的中间时间的会议。但是如今我事实上将“打断”作为我跟踪的一个关键度量。我这样做并不是想确定程序员不能得到太多的打断,而是想确定他们是否频繁地被打断。现在,我需要程序员被打断。我需要他们自发地与开发团队之外的人进行交流互动。对于那些没有遭受打断的程序员来说,一旦他们拥有足够的经验,我也会尝试把他们带到无休止的打断中。现在我更喜欢部门之间交叉安排位置,具有开放的楼层规划和开门的办公环境

下面的列表是我发现的一些有用的数据示例,将在后续章节深入讨论。此处只是说明性质的,因此仅仅描述了信息的类别或分类,而具体的数值(例如计数或者平均值)会在后面的内容中讨论。

  • 程序员加入团队的时间。
  • 团队规模、团队优化和团队建设。
  • 按复杂度分类并由程序员完成的任务。
  • 程序员协同完成的任务或程序员帮助他人完成的任务。
  • 特别紧急的任务,如修复严重的产品问题。
  • 显示程序员超常的创造力、创新和主动性的任务。·延期的、失败的或者取消的任务。
  • 程序员参与的项目、产品和产品领域。
  • 花在任务上的时间。
  • 花在会议上的时间,或者处理自己中断的事宜花费的时间。
  • 客户发现的问题,以严重性和复杂度进行分类。
  • 为了客户支持工作而进行联系的次数(电话、邮件或者聊天)。
  • 购买或使用产品或特性的客户数。
  • 试用了产品或特性,但决定不再使用的客户数。
  • 取消或停止使用产品或特性的客户数。
  • 维持、获得或直接竞争对手失去的客户数。
  • 从产品或特性的改变中获益的现有客户数。
  • 从产品、特性或者其他完成任务中获益的内部员工数。

以上仅是可使用在度量中的一些数据类型的例子。除了本书中提及的一些数据之外,毋庸置疑,也确实存在其他有助于程序员度量的数据类别。按一般原则,极有可能我并未完全尝试或考虑过许多潜在的数据。但对于有些数据类型,我本人曾经尝试或者深入思考过,而由于各种原因,这些数据并不是很有用或者存在更好的选择,因此本书中没有使用这些数据类型。下面是关于这些排除的数据类型的几个例子以及我排除它们的原因。

总结一下,如下是我对于收集程序员生产力的建议:

  • 将设计、编码和测试作为(单独的)任务进行跟踪。
  • 为任务建立复杂度评分体系,并且为每个任务进行评分。
  • 如果任务不能落在复杂度级别的范围内,则对其进行相应的合并或者拆分。
  • 在任务完成后对复杂度评分进行调整,以确保准确和一致。
  • 如果多个程序员负责同一任务,出于追踪目的对复杂度评分进行等分。
  • 不跟踪开发阶段发现和修复的bug。
  • 就如同其他的任务一样,分别跟踪生产环境的bug修复。
  • 对编码阶段的设计、测试和测试开发工作和编码任务进行合并。
  • 如同其他的任务一样,分别跟踪独立于编码的设计、测试或者测试开发任务。
  • 对程序员未能完成任务的次数进行跟踪。
  • 如果任务是部分完成的,则下调任务的复杂度评分。

下面是关于程序员速度度量的建议:

  • 以每周或两周为周期跟踪速度,或者使用其他一致的时间间隔。
  • 用每个程序员在每个时间周期内完成的工作(任务数和复杂度)作为速度的测度。

在此处我建议按照如下的步骤来跟踪程序员准确性:

  • 对发布后的所有产品问题进行跟踪。所谓产品问题是功能失常,或者是系统没有按预期执行。
  • 按照对用户影响的严重程度对每个产品问题进行评分,保持度量的一致性和简单性,并考虑调高回归bug严重性。
  • 对每个问题影响到的客户的百分比进行估计和跟踪。
  • 定义细分的产品领域,把每个产品问题分配给相应的产品领域,识别出从事每个区域的程序员。
  • 如果把一个产品的问题分配到由多个程序员负责的领域,则出于跟踪目的,在程序员之间等分该问题。
  • 不要根据修复这些问题所涉及的工作的复杂度来进行评分。

为了测量程序员的广度,我建议:

  • 定义精细的产品领域,最好是保持和问题跟踪的定义相同。
  • 保证每个程序员任务都分配到一个或多个产品领域。
  • 用此数据跟踪每个程序员从事的产品领域。

对于度量程序员的乐于助人,我有如下建议:

  • 程序员每周报告他们收到的与工作有关的请求以及他们的响应(超出分配给他们的任务)的频繁程度。
  • 如果软件开发团队的其他成员得到了主动的帮助,或者他们观察到一个程序员主动帮助了别人,也进行报告。

跟踪主动和创新很重要,我建议:

  • 让团队成员在程序员呈现显著的创新或主动性时报告。
  • 要求团队领导为每一个程序员保持这些事件的数量记录

尽可能跟踪每个软件产品或项目的关注和采用,我有如下建议:

  • 使软件能够跟踪和集中报告不同类型的用户(评估者和客户)的活动以及活动的日期。
  • 使软件跟踪和集中报告能够按用户(如登录次数和持续活跃的时间)进行汇总,如果可能,细化到不同的产品领域或特性(如执行一个特定类型的行为的次数)。
  • 用软件或数据采集系统来跟踪和集中报告用户的取消、不再活跃或长时间闲置的情况以及检测到的日期。

为了测量所做的工作是否交付了关键的用户效益,我建议:

  • 使用软件来测量、汇总和集中报告相关的数据和关键统计数据。这将会表明是否该软件满足了设定的目标。
  • 对于不能使用软件度量到的效益,确定用户的一个目标子集,询问他们一个具体的判断型问题来确定是否他们获得了预期的效益(如果你的组织有一个方法来进行用户调查或用户测试,这个数据可能会以另一种方式获得)。

作为一种跟踪顾客满意度的方法,我建议:

  • 保持对客户支持问题的跟踪,并按照软件领域进行分类。
  • 根据客户需要解决问题的迫切程度来对支持问题进行评分。

架构师:被任命为架构师的程序员通常是团队中较有经验的成员。他们的任务可能和其他程序员不同,有更高比例的复杂任务,包括设计任务。可能期望他们花更多时间来引导和支持其他团队成员,以确保软件设计良好并且质量高。

资深程序员:资深程序员在技术上更有经验,因而我们通常对其预期更高的生产力,更高的质量,并且有时候更有领导力。有时候他们是专才,有时候他们是通才,不管是哪种情况,他们都是团队中更强和更稳定的贡献者。

初级程序员:基于初级程序员的教育、背景、个人倾向以及能力,他们可能具有各种贡献并且展示出许多类型的技能。不像架构师或高级程序员,他们顾名思义是团队的更资深成员,这些团队可能有固定的模式(至少对那些已经在一起一段时间的团队),而初级程序员更像未知数。我们可能对初级程序员会做什么,他们的优势和弱势是什么有点概念,但是又不确定。

设定关键目标:当你打算构建一个新团队或改善既有团队时,通过基于度量的方法的第一步是:确定关键“业务”或者团队的组织目标。那些目标应该是可通过适当度量进行跟踪的。一旦确立了这些目标,你就可以通过它们来指引你的人事选择,并且你可以通过跟踪度量来分析那些结果。

识别约束:一旦团队目标已经制定,就需要确定是否存在约束条件,以及在这些约束条件下目标能否达成。预算是一个常见的约束,这会限制团队的程序员的数量和类型。对于现有团队而言,另一个约束可能是我们无权进行人事变动,因此你必须依靠现有的团队成员做出改善。

如果你定期地使用度量,把其作为你们开发流程的一部分,并且如果你们正在团队会议上分享和讨论它们,那么通过教练流程对目标领域的提高变得相当简单,你可以:

  • 通过确定那些已经在需求领域显露出优势(或者偶尔地)的程序员来培训其他人;
  • 确定你希望每个程序员需要达到的目标度量及其值;
  • 确保每个程序员必要时可以减少其他工作职责,以关注新的领域;
  • 跟踪程序员在关键度量上的提高,定期地与程序员一起进行检查。

根本就没有完美的团队这回事,并且也不存在最好的团队。但是,当你见到过卓越的团队,你会了解它。通过计划和思考,成功团队的模式可以识别出来,并且只要我们愿意,好的团队,甚至是优秀的团队是可以规划和打造的。