Fred Brooks(《人月神话》的作者)最早在他的论文“没有银弹——软件工程的本质和偶然性(No Silver Bullet - Essence and Accidents of Software Engineering)”中提出了“10x 程序员”的概念。技术社区对于这个概念呈现出两级分化的观点。 Redis 之父 Salvatore Sanfilippo( antirez )列出了 9 种特质,他认为,如果一个程序员同时具备了这 9 种特质,那么就可以说他是一个 10x 程序员。以下内容已获得 antirez 的翻译授权,查看英文原文 The mythical 10x programmer 。
一个 10x 程序员,在相同条件下,可以完成十倍于普通程序员的工作。这里所说的“普通程序员”,是指那些能够胜任自己工作的程序员,只是他们不具备 10x 程序员的神奇能力。普通程序员代表了这个领域所有专业程序员的平均水准。
对于是否存在 10x 程序员这种“神兽”,编程社区的观点呈现出两级分化:有人认为根本不存在所谓的 10x 程序员,有人则认为不仅存在 10x 程序员,如果找对了门路,甚至能找到 100x 的程序员。
如果说编程是一项“线性”的工作,那么很明显,10x 程序员是不可能存在的。一个跑步运动员怎么可能跑得比另一个快上十倍?在相同时间内,一个建筑工人建造的东西怎么可能是其他人的十倍?不过,编程是一项很特别的设计工作。虽然程序员可能不会参与程序的架构设计,但程序的实现仍然涉及到一些设计工作,而这部分需要程序员去完成。
如果说程序的设计和实现不是线性的,那么在我看来,经验、编码能力、知识和去伪存真的能力就不仅仅是线性的优势,它们在编程过程中相互交织,成倍地发挥效能。当然,如果程序员能够同时胜任设计和实现工作,那么这种现象就尤为明显。任务越是具有目标导向性,程序员就越是能够以更少的付出达成相同的目标,从而体现 10x 程序员的潜在能力。如果手头的工作很死板,而且限定了可使用的工具和实现方式,那么 10x 程序员事半功倍的能力就会大打折扣。不过,在不改变大前提的情况下,程序员仍然可能通过局部的设计优化来改进工作,包括在项目的某些部分不按常理出牌。所以,他们可以少付出很多却能达成几乎相同的目标。
在我的二十年程序员生涯中,我与其他程序员一起工作,作为同事,或者由我指导他们达成目标,为 Redis 和其他项目贡献代码补丁。在工作过程中,我仔细观察他们。与此同时,有很多人说我是一个高能的程序员。不过我不认为自己是一个工作狂,我只是编码速度比较快而已。
下面列出了我认为可以用于区分程序员生产力高低的重要特质。
编程裸技能:完成子任务
从处理编程子任务可以看出一个程序员的短板和长处,比如实现一个函数或者一个算法。但从我的经验来看,擅于应用基本的编程技能来高效完成任务的程序员并非如人们所想得那样普遍存在。有时候,团队里有些不是很称职的程序员,他们甚至不知道该怎么写一个简单的排序算法,但比起那些看似称职却缺乏实战经验的程序员,这些不称职的程序员却能完成更多的工作。
经验:模式匹配
我认为,经验就是一系列解决方案,它们已经被证实可以用于处理一些重复性的任务。经验老道的程序员知道该如何处理各种子任务,这样不但省掉了很多设计工作,而且避免了很多设计错误,而设计错误是简洁性最大的敌人。
专注:实际时间和假设时间
花在编码上的时间不仅要看数量,也要看质量。造成注意力不集中的因素既有内部的,也有外部的。内部的因素包括拖延、对手头的项目不感兴趣(一个人总是做不好自己不喜欢的事情)、缺乏练习、缺乏睡眠。外部因素包括频繁的会议、不固定的工作环境、同事的打扰,等等。集中注意力和避免被打扰对于提高编程效率来说是至关重要的。有时候,为了集中注意力,需要采取一些极端的手段。例如,我会时不时地查看邮件,但大部分邮件先不做回复。
设计权衡:用 5% 换取 90%
项目的非根本性目标在很大程度上导致了设计的复杂性,或者导致无法达成其他更重要的目标,因为根本性功能和非根本性功能在设计上存在竞争关系。如果意识不到这点,复杂性就会随之而来。实现全面的设计并不是件轻而易举的事,付出与回报之间不能通过简单的比例来衡量。对于设计者来说,意识到这一点是很重要的。如果项目要最大化产出,那么就要把精力集中在重要的事情上,并在合理的时间内完成。例如,在设计 Disque (一个分布式消息队列)时,我发现对消息进行排序之后,项目的其他方面就会得到实质性的改进:可用性、查询和客户端交互、简洁性和性能。
简洁性
简洁性是成败之间最为明显的分界点。理解复杂性的产生过程有助于理解什么是简洁性。我认为,不愿意做出设计权衡和设计错误的累积是导致复杂性的两个主要因素。
在设计过程中,每次走错一条道,就离最优的方案越来越远。一个初始的设计错误,如果没能被纠正过来,那么可能导致一条道走到黑,最终得到的是一个复杂的系统,而不是对原先系统的重新设计。项目会因此变得更加复杂和低效。
程序员可以在脑子里进行“概念验证”,从大量简单的设计想法中选择可行性最高且最直接的方案,从而达成简洁性。在后续的改进工作中,个人的经验和设计能力开始发挥作用,为子任务找到更加明智的解决方案。
不过,如果系统复杂性不可避免,那么在放弃挣扎之前也要尽量想办法降低系统复杂性,甚至尝试采取完全相反的设计。
完美主义(为了偏袒设计而放弃生产力)
完美主义可以分为两种:一种是追求程序极致性能的工程文化,另一种是个人特质。不管是哪一种完美主义,它们都会对程序员实现快速交付造成阻碍。完美主义和对外部评判的恐惧会导致设计上的偏袒,程序员根据主观的心理因素和无关紧要的衡量参数做出设计决策,却忽略了健壮性、简洁性和及时交付。
知识:理论有益
在处理复杂任务时,具备一些理论方面的知识会对设计产生重要影响,比如数据结构方面的知识、了解计算能力的局限性和一些重要的算法。我们没有必要成为无所不知的超级专家,但至少要知道一些问题的潜在解决方案。例如,在给一个给定流统计单一元素的个数时,我们可以在设计上做出权衡(接受一定程度的错误),并结合概率集合的基数估计(cardinality estimation)算法,避免设计出复杂、缓慢、低内存效能的解决方案。
底层:理解机器原理
程序的很多问题都是源于对计算机工作原理的误解,即使是使用高级语言开发的程序也不外乎如此。这种情况可能导致一个项目需要重新设计和实现,因为项目所使用的工具和算法出现了根本性的错误。精通 C 语言,知道 CPU 的工作原理,了解系统内核的行为以及系统调用的实现原理,做到这几点可以挽救你于危难之中。
调试技能
查找和解决 bug 经常会占用我们大量的时间。查找引起 bug 的问题根源,在合理的步骤内修复 bug,以简单的方式编写包含较少 bug 的代码,对于程序员来说,做到这几点可以显著提升效率。
一个程序员如果具备了上述几点特质,那么他们的产出将会有 10 倍的提升,对此我一点也不感到惊讶。综合这些特质,从一个可行的模型开始,实现更简单更好的设计。我认为简洁性就是一种“投机取巧的编程”。简而言之,就是在开发的每个阶段选择性地实现一些功能,以最小化的付出为用户带来最大化的影响。
感谢郭蕾对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论