旧文重发:程序员的七种武器

这篇文章发表在《程序员》杂志2007.03期的专辑“程序员的武器大家谈”中。

《程序员》:请谈谈您所定位的优秀程序员应该有哪些技能?您是怎样理解程序员七种武器的?

**周爱民:**一般来说,剑客用剑、刀客用刀,所以所谓七种武器,用在手上的,或许也就一件两件。但如果以技巧、技法论,却不是一件两件兵器就可以胜出江湖的。例如不懂刀的剑客,遇到用刀的人时便不知道如何刺击了。因为要先知其长短,才能避强而击弱。

不懂刀的剑客与不懂剑的刀客对打起来,大概会如同演舞一般,各练各的招式。

所以,优秀的程序员或程序高手并不是通晓七种武器的全才,必然是精通其一,且概知其它。与江湖不同的是,我们事实上并不拿一种武器去与拿另一种武器的人比斗。我们的对象是一个软件,或者某个工程。我们要克“敌”制胜,而敌是死物,不是活人。换言之,我们了解这些技术方法的目的,并不是要站到擂台上去比较谁懂得多,或者谁精通什么。我们只是要做一个软件或者具体的工程,那么所谓技术方法,只要对这个软件或工程有效即可。因此,用汇编写内核的人不必看不上用C写协议层的人,用C++写平台应用的,也不必看不上用SQL写脚本的人。放在一个团队里,汇编、C、C++和SQL在一个项目里可能各有其用,非得让这些人分个高下出来,最终是项目的失败。

任何的一种工具都有使用它的境界。很多人看不到这一点,而轻视其它语言或者工具。例如SQL,几乎所有使用高级语言(我当然不是说它比别的语言好而显得“高级”,而只是存在着这么一个分类)的开发人员都认为SQL是“一种相当简单的脚本”。但事实上,我的朋友中就有能把SQL用到出神入化的,他能由SQL的写法来推断数据库设计的失败,或者反过来,为特定的数据库系统写出最优化的SQL。重要的是,这个朋友会针对不同的存取环境、网络结构而设计特定的数据库和SQL,以达到最优。
优秀的程序员是对工具没有偏见的、能适应场合活用语言的人;而程序高手则基于这个前提,并专精其一,进而通一晓十的人。

《程序员》:您认为什么是程序员的基本技能?哪些是最重要的?

周爱民:“七种武器”中,数据结构是成为真正的程序员的基础,而面向对象思想则是门径。

程序员能否在软件开发这条道路上走下去,很大程度上取决于他对数据结构的了解。任何一种新的语言,或者任何一种新的体系结构的出现,都可以在数据结构上找到相关的解释。

因此,程序员如果能精通数据结构,那么相当于拥有了“以不变应万变”的资本。对此,《人月神话》中用一句话指出了关键:“数据的表现形式是编程的根本”。

对象是数据结构抽象的一种,但并不是唯一的一种。从这个角度上来说,对象并不是唯一的编程之道。我曾经说,人造卫星也是在面向过程的时代上的天。也就是说,面向过程也可以组织足够复杂的程序。

然而,所有这些都并不能否认面向对象的价值。面向对象是对事物的本体特性与行为特性的高度抽象,它将数据结构从“死的内存”变成了“活的物件”。面向对象的思想使我们在增强对现实的表达能力的同时,避免了复杂数据结构带来的藕合。由面向对象、信息隐藏和接口抽象三个相关联的概念,构成了整个软件体系设计的理论基础。这三个概念中,面向对象是与软件开发人员关系最密切,最容易理解的,因此它是使你成为真正的程序员,以及从程序员走向程序设计师的最佳门径。

《程序员》:如果用一个问题来测试一个人是不是程序高手,您会怎样问?

**周爱民:**我的问题是:你参与或组织过怎样的开源项目,如何评价它?

在程序高手这个级别上,能脱颖而出的是那种有合作能力的、思想开放的优秀人才,而绝不是技术高下的简单辨别。而观察他对开源项目的经验和兴趣,是一种不错的方式。

这里说的不是“把源代码公开”就是开源项目了。我说的是真正有组织的、持续的、公开源码的项目运作。之所以做这么多的限定条件,是因为现在很多人都已经接受了“源码公开”的思想,但这仅表明这个人有了分享的精神,并不表明他有组织和管理项目的能力。开源项目的生命力是在项目管理者在长时间的维护过程中得以延续的,同样的,项目管理者也在这个过程中历练了自己的技能与心性。而这些,正是高手在成长中不可或缺的要素。

《程序员》:您在成为一个优秀的开发人员过程中,哪几个阶段是最让您难忘的?

**周爱民:**我做程序之初,只是喜欢而已,其实真的是楞头青。这个阶段看来,就是代码不规范、接口随意,并且经常会推翻重来。“代码不规范”是非专业人员的通病,我在很长时间里面,都有“自己的风格”,所以还专为这个跟以前的部门经理争辩过:我同意格式化呀,但为什么要按你说的格式呢?“接口随意”是没有设计就开始写代码的表现,而“经常推翻重来”则是其后果。非专业人员最初通常就是一个人开始练手,自己给自己写代码,接口怎么写自己都能理解,所以专门去设计反倒是麻烦。但到了团队里面,过于“独特的”程序接口则是灾难,因为你得去给每个人解释这个接口的用法,说服他们使用这种接口。而这往往会遵行强势原则:你要么屈从“更标准的接口设计”,要么团队就放弃你的这些代码。

做程序再熟练,过不了上面这个阶段就谈不上合作,也谈不上设计。一个人写程序,无需多少设计的功夫。但一个团队合作,没有设计就不行。因此我认为写程序的第二个阶段就是团队开发和专业设计。而这两点,正是从项目管理和技术实现上来组织大规模开发的不二法门。因此,我事实上在这里想说明的是:相对于个体开发,团队开发是更高阶的技术。

在你学会了团队开发,能够轻松地与人合作,或组织小型的开发团队时,要想在这个行业中安身立命就并非难事了。至于用哪种语言,由于你是“优秀的程序员”,因此语言的选择是应项目之所需的,所以不是接下来要谈的关键问题。

第三个阶段是你能否在行业中脱颖而出的关键。但这个关键与技术无关,而是一个人的秉性和个性的问题。我们一方面会很阿Q地说“酒香不怕巷子深”,另一方面又说“千里马常有而伯乐不常有”。问题在于,马不能主动地找伯乐,人又为什么不能呢?马困于厩而显凡俗,人立于世可显不群。有表现自己不凡的品质的空间而不施展,根本上说还是能力问题。所以学会沟通、交往,而不是沉迷于代码,可能是第三个阶段的重要瓶颈。

在第三个阶段,你可能面临非常多的选择。例如技术主管、项目经理或者设计师、分析师之类。但你应该会发现,这所有的选择都将使你被推到团队的前面,你必须面对整个团队,以及项目的干系人(例如客户)。而能否胜任这些,取决于你的综合素质,而非单一的软件开发技能。

最后你得记住一件事,上面的这个过程,不是一朝一夕,也不是一年两年,而是五年十年的时间。在这个过程中,所有成功者都必须具备的,是认真的态度和专业的精神。

《程序员》:请为开发人员提供几点实践性的指导。

**周爱民:**把语言作为“称手的兵器”,那么基本技能则相当于内家修为。练石锁也能练出个李元霸,这说明单单靠“不停地写程序”,也是能写出高手来的。但是,如果一上手就给个千百斤的大石锁,李元霸没练成便先牺牲了。所以凡事都有个循序渐进,所循的这个“序”,并不要求每个人都相同,别人的经验,大抵上适合做个参考。而我也不能言讲什么指导性的东西,所以上面所谈,大家尽可以当经验来看,当参考来用。是实践,却不是什么指导。

《程序员》:请您谈谈做游戏开发与一般的软件开发,在技能上的要求有什么不同?

**周爱民:**游戏开发涉及的领域是比较复杂的。例如对界面交互,一般软件开发中有可用性测试,而游戏中叫可玩性测试。可用与可玩,就已经是两种不同的界面交互设计理念了。一般软件开发很少在界面部分应用人体工程学的知识,而游戏界面交互设计中却经常要用到这种知识。但是同样的例子,如果你做游戏开发中的网络传输或者服务器端,就涉及不到人体工程学。所以这里要说的是,现在游戏开发过程被分解得很细,不同的技能在游戏开发领域中都可以找到位置,但不要指望能什么技能都精通,然后一两个人就搞完整套游戏。

大多数游戏开发能涉及到的领域,在一般的软件开发中也同样会涉及到。例如数据库,很多人认为数据库与做游戏风马牛不相及。但事实上,在游戏开发中,后台数据库的存取效能、分布特性等是严重影响游戏体验的。所以你在传统软件开发中做得很好的技能,在游戏开发中一样用得到。

然而不同之处还是有的,其中突出的几点表现在视觉特效、交互特性和网络性能。

一般性的软件开发中,我们会遵从操作系统的惯例为用户提供交互体验,但游戏正好是希望给用户独特的体验,因此通常有不同的交互特性。这可能小到一个按钮的设计,大到整个操作的流程。这种交互特性又与输入输出设备的性质相关,例如手机的屏幕与键盘与PC就不一样。所以游戏对整个系统的输入输出的研究,与操作系统和一般软件是不一样的,根源在于它要提供独特性。

游戏对网络层的研究,也与传统软件不一样,但这不是独特性导致的,而是用户量级的问题。大到银行、电信这样的系统中,人们对数据传输的效能通常是由数据库系统和硬件系统来保证的,因此你只需要研究数据和库的优化。但我们总不能让用户花钱买完mssql、架完专线再来玩游戏,所以游戏开发中要在相当高的数量级上,自己来解决数据传输和数据库使用中的问题。然而游戏是多用户、强交互的系统,因此很快爆发出来的问题是分布问题、并行问题等等。这些原本在其它开发中交给某个专属领域去解决的问题在游戏中都需要用自己的方法去解决。

我们很少去强调游戏开发与一般的应用系统开发在技能方向有什么不同。其根本的原因,在于软件技术以及其它知识都存在共通性。任何一项专精的技术都可以在某个领域上发挥它的独特效果,任何广博的知识也都有助于开发人员找到更合理的解决方案。除开这些之外,我认为更重要的兴趣与态度,例如游戏开发需要你去发现和寻找乐趣,而系统底层的开发则要求你有更加坚韧的毅力与深厚的基础。这些,并不是技能所能弥补的。