Redis之父:10x程序员应该具备哪些素质?
10x程序员,是指在编程方法论中,所做的工作10倍于普通程序员的程序员。而所谓的普通程序员是指擅长所做工作,但却没有10x程序员魔力的程序员。实际上“普通程序员”这么归纳也许更好:普通程序员是指在专业的程序员当中有着平均编程产出的人。
对于这样一种异兽是否存在,编程社区有着两级分化的观点:有人说所谓的10x程序员并不存在,而有人则说10x程序员不仅存在,而且甚至100x程序员都有,如果你知道去哪里找的话。
如果你把编程看作是“线性”的学科,那么显然10x程序员存在的可能性是不合逻辑的。一名跑步运动员怎么可能比另一名快10倍?或者一名建筑工人在相同时间内建造的东西怎么可能比另一名多10倍?然而,编程是一门设计学科,属于一种特殊的设计。即便程序员并未参与到程序实际的架构设计当中,但实现本身仍然需要对实现策略的子设计。
那么,在我看来,如果程序的设计和实现不是一种线性能力的话,像经验、编码能力、知识、对无用部分的识别等这些就不仅仅是线性优势,而且凑到一起会对程序的编制产生倍增效应。当然,如果程序员能够同时处理程序的设计和实现时,这种现象会出现得多很多。任务越是“目标导向”,10x程序员以事半功倍的方式发挥能力的潜能就越大。如果手头的任务比较僵化,对于应该使用什么工具以及应该如何实现东西等方面有着具体指南的话,10x程序员以更少时间完成更多事情的能力就会变弱:虽然仍然可以通过挖掘“本地”设计的可能性来把工作做得更好,但却不能以更加深远的方式(这种方式包括甚至连项目的部分规范都彻底去掉,从而仍然能够以几乎相同的效果实现目标,同时实现所需的付出却要少了一大截)去改变目标的实现路径了。
在20年程序员的生涯当中,我观察了跟我一起工作的程序员同事,他们在我的指导下实现给定目标,为Redis等项目打补丁等。与此同时,许多人告诉我说他们认为我是一个非常快的程序员。考虑到我远不是个工作狂,我也把我自己作为是编码非常快(效率高)的人的参考。
以下所列我认为是最能拉开程序员生产力差异的一些素质。
* 裸编程能力:完成子任务
程序员最大的限制或者说优势之一,就是处理程序实际实现部分的子任务,也就是实现函数或者算法之类的能力。令人吃惊的是,就我的经验来看,非常有效地利用必要的基本编程结构去实现东西并不是一种普遍具备的能力。在一个团队中我有时候观察到有的程序员看似非常的不胜任,因为他们甚至连一个简单的排序算法都没有意识到,但是所完成的工作却要比那些理论上极其胜任、但在实现解决方案的实践方面却非常糟糕的已经毕业的程序员还要多。
* 经验:模式匹配
所谓经验是指一组已经过探索的、针对若干周期性任务的解决方案。有经验的程序员最终会知道如何处理各种子任务。这既避免了大量的设计工作,但尤其重要的是它还是一项针对设计错误的强大武器,而后者是简洁性的最大敌人之一。
* 专注:实际时间 vs 假设时间
如果不看时间质量的话编写代码花费的小时数无关紧要。缺乏专注往往有来自于内外部因素的影响。内部因素是拖延症,对手头项目缺乏兴趣(不热爱的事情是做不好的),缺乏练习/快乐,睡眠不足或很少等。外部因素包括频繁开会,工作环境没有真正的办公室,同事经常打断自己等等。试图改善专注和减少中断会对编程生产力产生非边际效应,这是很自然的。有时候为了获得专注,需要极端的手段。比方说我只会时不时读读邮件,但是大部分都不会去回复。
* 设计牺牲:干掉5%得到90%
当不愿意认识到项目的一个非根本性的目标要对设计的很大一部分复杂性负责时,或者由于某基本功能与次要功能之间存在设计冲突而导致另一个更加重要的目标难以实现时,复杂性就产生了。设计的所有部分都不会轻而易举实现,也就是说,付出的努力与得到的好处之间是不成比例的,设计师意识这一点非常重要。旨在取得最大化产出的项目只会专注于重要且可以在合理时间内实现的事情上。比方说,在设计消息代理Disque的时候,在某一刻我突然意识到只需要为消息提供尽力而为的排序,项目的其他方面就都可以获得实质性的改进:比如可用性、查询语言以及客户端交互、简洁性和性能等。
* 简洁性
这一点的重要性很显然,意味着成王败寇。为了理解什么是简洁性,看看复杂性往往是如何产生是值得的。我认为复杂性的两个主要的驱动力是不愿意做出设计上的牺牲,以及设计活动中错误的累积。
只要思考一下设计流程,每一次追求到一条错误的路径时,我们就会距离最优方案越来越远。一项初步设计错误,如果落到错误的人手中的话,他不会对同一系统进行重新设计,而是会为了处理当初的错误而设计出另一套复杂的解决方案。因此每迈出错误的一步该项目都会变得更加复杂、效率更低。
简洁性可以通过在脑子里进行“概念验证”方面的推理来实现,这样可以让程序员对大量的简单设计进行探索,然后从看起来最可行和直接的解决方案开始。随后利用经验和个人设计能力可以改进设计,为有待解决的子设计找到合理的解决方案。
无论每次需要多复杂的解决方案,对于如何避免这种复杂性进行长时间的推敲都是很重要的,只有在考虑过完全不同的替代方案也没有发现更好的可能性之后才可以继续原方案。
* 完美主义,或者如何干掉你的生产力,偏袒你的设计
完美主义有两种派生:一种是痴迷在程序中实现可能达到的、可衡量的最佳性能的工程文化,另一种是作为个人特质。我把这两种情况均视为程序员快速交付的最大障碍之一。完美主义以及对外部评判的恐惧会植入一种设计偏见,导致会根据心理或者无关紧要的可衡量参数而做出糟糕的重新设计选择,而像健壮性、简洁性、及时交付的能力往往却从未考虑。
* 知识:一些理论会有所帮助
在处理复杂性任务时,有关数据结构、计算的根本性限制、非常适合对特定任务建模的算法方面的知识对于找到合适设计的能力会产生影响。你没有必要成为一切事情的超级专家,但是至少能意识到某问题存在大批潜在解决方案是必要的。
* 底层:理解机器
程序里面的出现一些问题,即便是使用高级语言的时候,往往都是因为误解了计算机执行特定任务的方式。就因为使用的工具或者算法存在根本问题,甚至会导致需要进行从头开始对项目进行重新设计和重新实现。非常擅长C语言,理解CPU的工作方式,对于内核如何运作、系统调用如何实现有着清晰了解的话,可以避免到了后面遇到糟糕的“惊喜”。
* 调试技能
为了找到bug往往很容易就会花费掉大量的精力。擅长逐步地获取bug相关状态,以便在合理的步骤内修补好问题,知道编写简单代码不大可能会导致太多bug,这些对于提高程序员的效率都会产生很大的影响。
在我看来,如果一位程序员具备上述特质的话,能够取得10倍于平均水平的产出并不奇怪。这些特质联合起来可以先从可行模型开始,慢慢做出好的设计实现,而且做出来的东西往往要比替代方案简单好几倍。为了强调简洁性,我愿意称之为“机会主义编程”。意思是说在开发的每一步都要对实现的功能集进行挑选,目的是为了以最小的代价对程序的客户群产生最大的影响。