10倍程序员的秘密

高效的程序员应该具备哪些素质,"10倍程序员"给你答案!。

源文: The mythical 10x programmer (antirez)

在编程世界中,10倍程序员是指那些能够完成普通程序员十倍工作的程序员,对于普通程序员, 我们可以想象他是一个擅长一般编码工作,但并不具备10倍程序员这样具有神奇魔力的程序员。 其实为了更好地描述 "普通程序员 " 的特点,不如说它代表的是程序员这个群体中,拥有平均编程产出的人。

编程界对于是否存在这样的程序员观点明显两级分化: 一方说压根就不存在这样的10倍程序员,另一方又说它不仅存在, 只要你知道去哪里找,甚至还有100倍程序员存在。

如果你把编程看成是一门 "线性"学科,那么很显然,10倍程序员看起来是不太合理的。一个人跑步怎么可能比另一个人跑得快10倍? 又或者一个建筑工人在同样的时间内能建造出另一个工人10倍的东西? 然而编程是一门设计学科,它非常特殊。 即使程序员不参与程序的实际架构设计,实现程序的功能仍然需要进行精心地设计。

所以,如果程序的设计和实现不是线性的能力,那么像经验、编码能力、基础知识、识别系统无用部分的能力,在我看来,不仅仅是线性的 优势,也是创建程序的效率倍增器。当然,这样的现象通常发生在那些即能设计又能实现程序的人身上。越是“目标导向”的任务,一个潜在的10倍 程序员越能发挥自己的能力,以较小的付出达成目标。当手头的任务越是固定,对使用什么工具以及如何实现有确定的指导方针时,10倍程序员 在更短时间内完成大量工作的能力就会被削弱,但他仍能可以利用“局部”设计的可能性更好地完成工作。

在二十年的程序员生涯中,我观察了其它与我一起工作的程序员;也作为同事,在我的指导下,为了达成某个目标,为Redis和其它项目提供补丁。 他们当中很多人对我说,他们认为我是一个编程非常快的程序员。考虑到我还远不是一个工作狂,但我也会把自己做为一个如何快速编程的一个参考。

以下是我认为对程序员工作效率影响最大的因素。

  • 赤裸裸的编程能力: 完成子任务的能力

程序员最明显的限制或优势之一,就是实际编码实现程序子任务的能力:如编写一个函数,一个算法或者其它什么。 令人惊讶的是,根据我的经验,非常有效地使用基本的命令式编程结构来实现某些功能的能力并不像人们想象的那样普遍。 在一个团队中,有时我发现一些理论非常差的程序员,他们甚至连一个简单的排序算法都不知道,却能比那些理论上非常优秀, 但在实现解决方案的实践中表现非常糟糕的刚毕业程序员能完成更多的工作。

  • 经验: 模式匹配

我所说的经验是指针对一些重复性任务已经探索出的一套解决方案。一个有经验的程序员最终会知道如何处理各种子任务。 这既避免了大量的设计工作,尤其经验是抵御设计错误的极其有力的武器,而设计错误又是简单性的最大敌人之一。

  • 专注力: 实际时间VS假设时间

如果不看时间质量,写代码的小时数是无关紧要的。缺乏专注力可以由内部和外部因素产生。 内部因素是拖延症,对手头的项目缺乏兴趣(你不可能做好你不喜欢的事情),缺乏运动、健康,睡眠不好或很少。 外部因素是频繁的会议、没有办公场所环境、同事经常打断等等。似乎自然而然,试图提高专注力,减少干扰,会对编程生产力产生非边际效应。 有时候为了获得专注力,需要采取极端的措施。比如我会不时地看看邮件,但是大部分邮件都不会回复。

  • 设计牺牲: 牺牲5%,得到90%

当人们不愿意认识到项目的一个非功能性目标带来非常大的设计复杂性,或者使另一个更重要的目标很难完成时,往往会产生复杂性, 因为在功能特性和非功能特性之间存在着设计矛盾。 对于一个设计师来说,认识到设计中所有不容易实现的部分是非常重要的,也就是说,付出和产出之间是不成正比的。 一个项目的执行是为了实现产出的最大化,要准确地关注那些重要的、可以在合理的时间内实现的方面。例如在设计Disque这个消息中间件时,在某个时刻我意识到, 只要为消息努力提供最佳的排序,项目的其他方面都可以得到实质性的改善:可用性、查询语言和客户端交互、简单性和性能。

  • 简单性

这是一个显而易见的观点,意味着所有和没有。为了理解什么是简单性,值得检查一下复杂性通常是如何产生的。我认为,产生复杂性的两个主要因素是: 一,不愿进行设计牺牲,二,设计活动中错误的积累。

如果你在设计过程中思考,每追求一条错误的路径,我们就会离最优解越来越远。一个最初的设计错误,在错误的人手里,不会产生对同一系统的重新设计, 而是会导致设计另一个更复杂的解决方案,以应对最初的错误。因此,项目每错一步,就会变得更加复杂,效率降低。

实现简单化的方法就是用 "概念验证 "来推理,让大量的简单设计在程序员的脑海中探索,从一些看起来最可行、最直接的方案开始工作。之后根据经验和个人的设计能力,可以改进设计, 为需要解决的子设计找到合理的解决方案。

然而每次需要复杂的解决方案时,都要经过长时间的推理,如何避免复杂,只有在没有找到更好的可能性,甚至考虑完全不同的替代方案时,才会继续朝这个方向发展。

  • 完美主义,或者说如何扼杀你的生产力,让你的设计出现偏差。

完美主义有两种变体:一种是在程序中达到最佳的可衡量性能的工程文化,另一种是人格特质。在这两种情况下,我认为这是程序员快速交付程序的最大障碍之一。 完美主义和对外部评判的恐惧插入了一种设计偏见,会导致错误的选择,以便只根据心理或微不足道的可测量参数来完善设计,其中像鲁棒性、简单性、及时交付能力这样的东西,往往从不考虑。

  • 知识:一些理论会有帮助

在处理复杂的任务时,关于数据结构的知识、计算的基本限制、非琐碎的算法,这些都非常适用于某些任务的建模,都会对找到合适的设计产生影响。不需要成为一个什么都懂的超级专家, 但至少要知道一个问题的众多潜在解决方案,这当然是需要的。例如,可以将设计牺牲(接受一定的错误百分比)和了解概率集基数估计量组合在一起,以避免复杂,缓慢且内存效率低的解决方案, 以便对计算流中的唯一项进行计数。

  • 低层次: 理解机器

程序中的一些问题,即使是在使用高级语言的情况下,也是由于对计算机如何执行某项任务的误解而产生的。 这甚至可能导致由于所使用的工具或算法存在根本性的问题,需要重新设计和重新从头开始实施一个项目。 良好的C语言能力,对CPU工作原理的理解, 以及对内核如何运行和系统调用如何实现的清晰思路,可以避免后期出现不好的意外。

  • 调试技巧

为了找到bug,很容易花费巨大的工作量。善于循序渐进获取bug的错误状态,以便用一套合理的步骤来修复它,加上写简单代码的态度,不可能包含太多的bug, 这两者对程序员的效率有很大的影响。

程序员的以上素质对工作输出的影响是10倍的,这一点我并不奇怪。综合来看,他们可以从可行模型的开始设计良好的实现,并且可能比替代方法简单好几倍。 有一种强调简单的方法,我喜欢称之为 "机会编程" 。基本上,在每个开发步骤中,都会选择要实现的功能集,以便以最小的工作量对程序的用户群体产生最大的影响。

(全文完)