The mythical 10x programmer

Salvatore Sanfilippo

传说中的10倍程序员

原文由 Salvatore Sanfilippo 发布,订阅该博客

在编程的神话里,所谓10倍程序员,指的是能够完成普通程序员十倍工作量的程序员。这里的“普通程序员”可以理解为能够胜任本职工作、但不具备那种神奇能力的程序员。更准确地说,“普通程序员”代表的是在这个行业中,以专业为生的程序员群体的平均产出水平。

编程社群对于这种“神兽”是否真的存在,观点极度两极分化:有人认为根本不存在所谓的10倍程序员,也有人认为它不仅存在,只要找对地方,甚至还能找到100倍程序员。

如果把编程看作一门“线性”学科,10倍程序员显然就显得荒谬不经。怎么可能有一个跑步者比另一个快10倍?或是一个建筑工人能在同样时间内比另一个多盖10倍的东西?然而,编程在非常特殊的意义上是一门设计学科。即使程序员没有参与程序的整体架构设计,实现过程本身依然需要对实现策略进行次一级的设计。

因此,如果程序的设计与实现并非线性能力,那么在我看来,经验、编码能力、知识、对无用部分的识别等,就不仅仅是线性的优势,它们在创造程序的过程中是以相乘的方式协同作用的。当然,这种现象在程序员能够同时掌控设计与实现时表现得更为明显。任务越是“目标导向”,潜在的10倍程序员就越能发挥自身能力,以少得多的投入达成目标。当手头的任务非常僵化,对使用什么工具、如何实现都有明确规定时,10倍程序员在更短时间内完成大量工作的能力就会被削弱:他仍然可以利用“局部”的设计空间把工作做得好得多,却无法从更根本的层面上改变通往目标的路径——而这种根本性的改变,甚至可能包括直接从项目中删掉部分需求,让最终目标看起来几乎不变,但实现所需的工作量却大幅降低。

在二十年的编程生涯中,我观察过许多与我共事、由我指导去达成特定目标的程序员,也看过为 Redis 及其他项目提交补丁的人。与此同时,也有很多人说他们认为我是个写代码非常快的程序员。考虑到我远非工作狂,我也会把自己作为快速编码的一个参照。

以下是我认为对程序员生产力影响最大的一些特质。

  • 基础编程能力:把子任务做出来

    程序员最明显的一项短板或长处,就在于能否实际去实现程序的某个部分:一个函数、一个算法,或其他任何东西。令我惊讶的是,就我的经验而言,能够非常高效地运用基本的命令式编程结构来实现功能的能力,并不如人们想象的那么普遍。在团队中,我有时会看到一些看起来非常不合格、甚至连简单排序算法都不知道的程序员,完成的工作反而比那些理论上极其优秀、科班出身,却在动手实现上很差的程序员更多。

  • 经验:模式匹配

    我所说的经验,是指针对一系列重复性任务已经探索过的解决方案的集合。有经验的程序员最终会懂得如何应对各种子任务。这不仅能省去大量的设计工作,更重要的是,它是抵御设计错误的有力武器,而设计错误本身正是简洁性最大的敌人之一。

  • 专注:真实时间 vs 假设时间

    写代码花了多少小时,如果不看时间的质量,就毫无意义。注意力的缺失可能来自内部和外部因素。内部因素包括拖延、对当前项目缺乏兴趣(你不可能把自己不热爱的事情做好)、缺乏锻炼/状态不佳、睡眠不足或质量差。外部因素包括频繁的会议、没有独立办公室的工作环境、同事频繁打扰等等。显而易见,设法提升专注度、减少干扰,对编程生产力会产生不可小觑的影响。有时为了获得专注,甚至需要采取极端措施。比如,我只会隔一段时间才看邮件,而且大多数邮件都不会回复。

  • 设计取舍:舍弃5%以换取90%

    复杂性常常源于不愿承认:项目中某个非核心目标占据了大量的设计复杂度,或是因为核心功能与非核心功能之间存在设计冲突,使得另一个更重要的目标变得难以实现。对于设计者而言,识别出设计中那些并非“轻易可得”的部分至关重要——即投入与收益不成比例的部分。一个以最大化产出为目标去执行的项目,会恰好聚焦于那些真正重要、且能在合理时间内实现的部分。例如,在设计消息中间件 Disque 时,我在某个阶段意识到,只要对消息仅提供尽力而为的顺序保证,项目的其他各个方面都能得到实质性的提升:可用性、查询语言与客户端交互、简洁性以及性能。

  • 简洁

    这一点看似显而易见,却又什么都说明、什么都没说明。要理解何为简洁,值得先看看复杂性通常是如何产生的。我认为,复杂性的两大主要推手,是不愿做出设计取舍,以及设计活动中的错误不断累积。

    如果审视设计过程,每走一次错误的路径,我们就会离最优解越来越远。一个最初的设计错误,落在不恰当的人手里,不会导致对同一系统进行重新设计,而是会催生另一个复杂的方案来弥补最初的错误。于是,项目在每一次错误之后都会变得更加复杂、效率更低。

    实现简洁的方法,是用小型的“概念验证”在头脑中进行推演,这样程序员就能在脑海中探索大量简单的设计,从那个看起来最可行、最直接的方案开始着手。之后,凭借经验和个人的设计能力,再去改进设计,为需要解决的子设计找到合理的方案。

    然而,每当需要一个复杂的方案时,重要的是要花很长时间去思考如何避免这种复杂性,只有在考虑过完全不同的替代方案后仍找不到更好的可能时,才继续沿着这个方向前进。

  • 完美主义,或如何扼杀你的生产力并扭曲你的设计

    完美主义有两种表现:一种是追求程序可度量的性能达到极致的工程文化,另一种则是作为人格特质而存在。在这两种情况下,我都认为它是阻碍程序员快速交付的最大障碍之一。完美主义加上对外部评判的恐惧,会带来一种设计上的偏见,导致人们只依据心理上的或那些容易度量的参数去打磨设计,从而做出糟糕的选择,而像健壮性、简洁性、按时交付的能力等则往往被完全忽略。

  • 知识:一些理论终会派上用场

    在处理复杂任务时,关于数据结构、计算的基本极限、非常适合对某些任务建模的非平凡算法等方面的知识,会影响找到合适设计的能力。不需要对所有领域都成为超级专家,但至少要了解针对某个问题的多种潜在解决方案,这一点是必需的。例如,将设计取舍(接受一定的误差率)与对概率式集合基数估计算法的了解结合起来,就可以避免为了统计数据流中的唯一项而采用复杂、缓慢且内存效率低下的方案。

  • 底层:理解机器

    程序中的许多问题,即使在使用高级语言时,也源于对计算机将如何执行某项任务的误解。这甚至可能导致需要从头重新设计、重新实现整个项目,因为所使用的工具或算法存在根本性问题。对 C 语言的良好掌握、对 CPU 工作原理的理解,以及对内核如何运作、系统调用如何实现的清晰认识,可以让人避免后期出现糟糕的意外。

  • 调试能力

    为了找到缺陷,很容易就会耗费巨大的工作量。善于循序渐进地获取关于缺陷的状态信息、并以一系列理性的步骤去修复它,再加上编写本身就不太可能包含太多缺陷的简洁代码的习惯,两者相加,会对程序员的效率产生巨大的影响。

在我看来,上述这些特质会对产出造成10倍的影响,这并不令人惊讶。它们结合在一起,使得那些从可行模型出发的设计能够得到良好的实现,并且可以比替代方案简单数倍。有一种强调简洁的方式,我喜欢称之为“机会主义编程”。基本上,在每一个开发步骤中,要实现的功能集合都是经过挑选的,目的是以最小的投入,对程序的用户群体产生最大的影响。

本文章由 muse-spark-1.2-contributor 进行翻译

评论