设置风格

我们已经覆盖了配置项目时的大多数一次性任务:选择一个许可证,安排初始的网站等等。但是开始一个新项目时最重要的方面是会变化的。选择一个邮件列表地址很容易;而保证列表的对话不走题且有效率则完全是另一回事情。如果项目经过多年的关闭,内部的开发,重新开始时开发过程将会改变,你需要准备开发者来应对这种变化。

第一步是最难的,因为未来管理的先例和预期都没有设置。正式的规则还没有带来项目的稳定性,而是由开发过程中共享的难以稳定的团体智慧带来。也许有已经写好的规则,但通常是通过难以预料的,不断进化的协议来引导项目。写好的规则不能定义其描述的项目文化,即使后来也是近似而已。

这里是如此解决问题的一些原因。成长和高转化率不会像一般人想象的那样损坏社会规范的积累。只要变化不要快,就有时间让新来者学会如何做事,在他们学会之后,他们自己就会来加强这种方式。考虑一下数世纪以来儿童歌曲的发展。现在孩子们演唱的歌曲和几百年前有大致相同的韵脚,即使现在的孩子从来没有生活在那个时代。小点的孩子听到大点的孩子唱歌,然后当他们长大了,他们又会在更小的孩子面前演唱。孩子不是故意参与这个传递程序,当然,这些歌曲的传承确实是因为有规律和重复的传递。自由软件项目不会以世纪(我们还不能知道)作为测量的时间刻度,但是变化和传递非常类似。转化率更快,不管怎样,必须以更活跃和慎重的传递投入来作为补偿。

人们通常会期望和寻找社会规范的事实,会成为这种努力的辅助。这也是人类的做法。在任何以共同努力统一的团队中,加入者都会凭直觉寻找可以将自己标记为团队一部分的行为。尽早设定先例的目标是让这些“组内”行为对于项目发生作用;一旦建立,多半会生生不息。

通过特定实例,你可以设置好的先例。这不必是一个完整的列表,但是通过尽早设置这样的协作情绪的方法,可以大大的帮助项目。从物理上讲,每个开发者都在自己的房间独立工作,但是你可以设法让他们感觉是在一个房间一起工作。他们这样的感觉越多,就会在项目上花费更多的时间。我选择了这些例子,因为这些实例来自Subversion项目(http://subversion.tigris.org/),而我从一开始就参与并观察了这些实例。但是这不仅仅对Subversion有效;大多数开源项目中都会遇到类似的情形,这是开个好头的好机会。

避免私下讨论

即使你已经将项目公开,你和你的创始人也会经常希望通过私下讨论来解决困难的问题。这在项目的开始阶段尤其明显,因为此时需要做出许多重要的决定,而只有少量志愿者能够胜任。你会发现公开讨论的明显缺点:邮件对话本身的延迟性,需要保留足够的时间来达成一致,处理自以为是的幼稚的志愿者(每个项目都有;有些将来会成为明星贡献者,而有些会永远保持幼稚),也就是那些不能理解你为什么只希望解决问题X,而X明显是大问题Y的子集的人。秘密决定并使之成为既成事实,或者至少成为联合和有影响力的投票集团的坚实推荐,确实非常有吸引力。

不要这样做。

尽管公开讨论可能很笨重,但是从长远来看这样做更合适。私下里做出重要的决定就像是将贡献者排斥出项目一样。没有重要的志愿者会愿意呆在这样一个由秘密委员会做重要决定的环境里。此外,公开讨论也会从其副作用中获益,无论是多么短暂的技术问题,一经发起都会一直讨论下去:

  • 讨论有助于训练和教育新开发者。你不知道有多少双眼睛在关注着讨论;即使大多数人不会参与,仍然可能有很多人在静静的跟踪,收集软件的信息。

  • 讨论会训练如何向不熟悉软件的人们解释技术问题。这种技巧需要练习,你不能从已经知道你所知道的人那里获得这种练习。

  • 之后,讨论和结论将会一直存放在公共归档中,可以保证以后的讨论不会回到同样的步骤中。见Chapter 6, 交流the section called “归档的显著使用”

最后,很有可能某个人会提出一个你从想到过的好主意,给对话带来真正的贡献。很难说这有多大的可能;这仅仅由代码的复杂程度和需求的专业程度决定。但是如果允许我使用轶事作为证据,我会证明这样做比直觉所期望的结果更好。在Subversion项目,我们(创始人)相信我们面对的是一组深入而复杂的问题,为此我们痛苦思考了几个月,我们很明确的怀疑在新建立的邮件列表中的会有任何人做出真正的贡献。所以我们选择了一条比较懒惰的方式,开始通过私下邮件讨论技术想法,直到项目的一个观察者[10]嗅出了问题,并要求将讨论公开。眨了眨眼我们这样做了—后来的结果让我们十分惊讶,我们很快便获得了许多有见地的回复和建议。大多数情况下人们提供的想法都是我们从来没有想到的。结果是邮件列表中一下子多了许多非常英明的人;他们只是在等待正确的诱饵。可以肯定地是公开讨论比私下讨论会保持更长的时间,也能得到更多的产出,花费额外的时间是值得的。

我们不必把问题总结为:“团结就是力量”(我们已经见过许多更成功的团队),但可以确认的是有一些事情适于在团队中完成。首先是有了大量的审阅;其次是快速产生大量的想法。想法的质量由其所针对的思想决定,当然,在你用挑战性的问题刺激他们之前,你无法判断这些思考者是那种人。

当然,也有许多讨论必须在私下进行,通过此书我们会看到这种例子。但是我们有一个指导原则如果没有保持秘密的原因,那就公开进行。

要想使之发生,我们需要行动。仅仅保证自己所有的通告公开是不够的。你也需要劝说其他人放弃不必要的私下讨论。如果某个人尝试开始没有必要的私下讨论,你要义不容辞的立刻进行恰当的元讨论。在你将讨论成功的引入公开场所之前,不要对原始主题做出任何回复,或者去确定私下进行是否必须。如果你一贯如此,人们会很快会意,并开始首选公开论坛进行讨论。

防无礼于未然

从项目的一开始,你就应该保持论坛中粗鲁和无礼行为的零容忍。零容忍不是指技术上的实质强制。当有人侵犯其他用户,你不需要将其从邮件列表中删除,或因为其无礼的回复而收回其回复权限。 (理论上讲,可能最终你必须诉诸这类行动,但应该是其他方法失败之后才采用—这需要清晰的表述,而不应该是项目开始的情况。)零容忍指的仅仅是决不漏掉任何此类坏行为。例如,有人发布的技术回复中掺杂了对某一个项目开发者的个人偏好的攻击,首先你应该紧急回复来指明这种个人偏好的攻击,并指出作为技术问题本身,应该只包含技术内容。

不幸的是这并不很容易,更普遍的是,建设性的讨论演变为破坏性的论战。人们会在邮件里谈事情,而永远不会面对面谈论。讨论的主题只是放大了这种效果:在技术问题中,人们经常感觉对大多数问题有一个唯一的答案,而对此答案的异议只能被解释为无知或愚蠢。某人技术提议的愚蠢与某人本身的愚蠢不算太远。实际上,有时候很难说出技术争论和人身攻击从哪里开始,这也是激烈回复或惩罚不是好主意的一个原因。相反,当你发现此类事件发生,你应当回复来强调保持友善讨论的重要性,而不要指责任何人是故意为害。可惜这种“软规则”回复有点像幼儿园老师教导学生学习好的行为:

首先,请减少带有个人倾向的回复;例如,称J的安全层设计对“计算机安全基本原理的幼稚和无知”。这样说对错都有可能,但是无论何种情况,我们都无法进行讨论。J真心诚意地提出意见。如果存在Bug,请指出来,我们会进行修正并得到新的设计。我确定M对于J并无人身攻击,但是措辞是不合适的,我们会努力保持事务的建设性。

现在,对于这个建议。我认为M所说的是正确的...

因为此回复的不自然,会有显著的效果。如果你对于坏的行为保持一贯的行动,而不是要求攻击方进行道歉和承认,这样就让人们可以自由的冷静下来,而在下一次能够表现的更有礼貌一点—他们会的。这样做能成功的诀窍是不要将元讨论作为主题。它必须放在一边,成为回复主要部分的简短序言。通过顺便提及指出“我们这里不是这么做的”,然后转移到真正的内容,这样你就给了人们一些可以回复的话题。如果有人抗议他们不应该受到你的责难,只需要拒绝讨论这个问题。除了不回复(如果你认为他们只是精力过剩,不需要回复),也可以说你为反应过度而道歉,而且在邮件中很难感到这种微妙之处,然后回到主题。绝不在任何时候要求一个人为不合适行为作出承认,无论是公开还是私下的。如果他们选择随自己的意愿进行道歉,那样很好,但是要求他们那么做只会导致怨恨。

总体目标是将好的礼节视为“团队内”的行为。这可以帮助项目,因为开发者会由于论战而流失(即使是他们喜爱和希望提供支持的项目)。你可能甚至不知道他们为什么离开;有些人可能一直潜伏在邮件列表,考虑到加入到项目需要的厚脸皮,就会决定放弃加入。保持论坛的友善是一个长期生存策略,在项目还比较小的时候,这很容易。一旦这成为了文化的一部分,你就不是唯一提升这种文化的人。所有人会一起维护。

实践明显的代码评审

促进开发生产率的一个最好的办法就是让人们互相察看代码。需要一些技术基础设施来进行有效的支持—特别是提交邮件应该开启;更多细节见the section called “提交邮件”。提交邮件的作用就是每当有人提交了源代码的修改,就会发送一封包含日志信息和变更差异(见the section called “版本控制词汇表”差异(diff))的邮件。 代码评审是在代码来到时对提交邮件进行评审,寻找Bug和可能的改进的实践。[11]

代码评审同时满足多个目标。这是开源世界的同级评审中最明显的一个例子,直接促进维护软件的质量。软件的每一个Bug都是提交进来的,而且没有被发现;因此,关注的眼睛越多,将会带入越少的Bug。但是代码评审也有非直接的目标:它确认了人们所真正关心的东西,因为很明显一个人不会去花时间评审他不关心的功能。当人们知道会有人花时间评价他的工作,他们就会倾尽全力。

评审必须是公开的。即使有时我与其他开发者坐在同一个物理房间,我们中的一个做出了提交,我们也尽量不在房间中进行口头评审,而是将其发送到开发邮件列表。所有人会从看到发生的评审获益。人们紧跟着评论,有时会在其中发现瑕疵,即使没有发现,这也会一直提醒他们评审是一个预期的,有规律的活动,就像刷盘子和割草坪。

在Subversion项目,开始时并没有建立有规律的代码评审实践。无法保障所有的提交会得到评审,尽管如此,还是会有人在看到感兴趣的代码块时看一下修改。一些小Bug确实能够,也应该被发现。一个叫Greg Stein的开发者,从以前的工作知道代码评审的重要性,决定通过评审每个单独提交到源代码库的每一行来设立一个范例。每当有人提交,邮件列表就会紧跟着出现Greg的邮件,解剖这次提交,分析可能的问题,偶尔还会赞扬一下聪明的代码。很快,他就发现了其他人会略过而不会注意的Bug和非最优的代码实践。更深刻的是,他从没有抱怨他是唯一评审所有提交的人,尽管这样做占用了他很多时间,但是他确实一有机会就会盛赞代码评审。不久之后,其他人,包括我也开始了有规律的提交评审。我们的动机是什么?不是Greg有意识的让我们为此感到羞愧。而是他已经证明代码评审是值得花费时间的方法,它的贡献与编写新的代码不相上下。一旦他证明了这一点,它就成为预期的行为,以至于如果一个提交者发现没有人对其提交有任何反应,他会感到担心,甚至会在列表中讯问是否有人愿意花时间为其评审。不久之后,Greg得到一个工作,他也没有更多时间为Subversion工作,结束了有规律的评审。但是之后,他的习惯深深影响了我们,似乎这样做是天经地义的。

从第一个提交就开始评审。差异评审中最容易检查出来的问题包括安全漏洞、内存泄露、注释不足或API文档问题、位偏移错误、调用/被调用不匹配以及其他在较小的上下文就能发现的问题。然而,即使这类未能将重复的模式抽象到一处的较大规模问题,在经过有规律的评审后也可以被定位出来,因为对以前差异的记忆提醒了对当前差异的评审。

不要担心你未能发现任何需要回复的内容,或者你不是很清楚代码的每个部分。通常几乎每一次提交都会要说什么事情;即使你没有发现任何事情可以提问,你还是可能发现一些事情可以对其称赞。最重要的是让每个提交者清楚,他们所做的事情都正在被关注和理解。当然,代码评审不能让程序员逃脱在提交之前评审和测试他们所做变更的责任;人们不应该依靠代码评审来捕捉本应该他自己捕捉的问题。

将一个封闭项目开放时,对于改变的影响要格外敏感

如果你开放一个已存在的项目,其中已经有了许多习惯于在封闭源代码环境下工作的活跃开发者,你必须确保每个人理解正要发生的重大变化—你必须设身处地的为他们着想。

想象一下他们面对的情形:以前,所有的代码和设计决定都是由一组程序员做出,他们对软件有差不多相等的熟悉程度,而且都是从同一个管理中接受相同的压力,而且清楚其他人的长处和弱点。现在你让他们将代码暴露给随机的陌生人监视,而他们只会根据代码形成判断,而不会考虑造成这种决定的商业压力。这些陌生人会询问很多问题,这些问题让已有的开发者发现无论如何为文档苦干,仍然不足(不可避免的)。最关键的是,这些新来者是未知的,未露面的实体。如果你的一个开发者已经感觉到他的技艺不够安全,想想一下当新来者指出他所写代码的Bug时的严重性,更严重的,在他的同事面前。除非你有一个拥有完美编码员的团队,这是不可避免的—实际上,对于每一个人开始都会发生这种情况。这不是因为他们不是好程序员;只是因为任何超过一定规模的程序都会有Bug,而同级评审可以发现一些此类Bug(见本章前面的the section called “实践明显的代码评审”)。而此时,新来者开始本身并没有受到同级评审的支配,因此他们在熟悉项目之前不能贡献代码。对你的开发者,感觉指责正在到来,绝不会离开。因此,要小心这些老手的人心散了。

防止发生这种情况的最佳方法是警告每个人即将发生的情况,告诉他们开始的不适是完全正常的,鼓励他们一切都会好起来的。有一些警告应该在私下发生,在项目开放以前。但是你也会发现如果在公共列表中提醒人们会有好处,告诉他们这是项目开发的新方式,需要一段时间来调整。你能做的最好的事情是通过实例进行引导。如果你看到你的开发者无法回答足够多的新手问题,那么只要告诉他们回答更多也于事无补。也许他们对于何种问题需要保证回复没有太好的感觉,或者他们对于如何排定代码工作和新的外部沟通交流负担的优先级没有感觉。让它们参与进来的方法是你自己参与进去。作为一个公开邮件列表,确保在那里回答一些问题。当你没有回答某个问题的技能时,要明确的交给能做的开发者—然后观察确保有回答或至少是一个回应。当然现在还是有长期开发者进行私下讨论的诱惑,因为他们一贯如此。请确定你已经订阅了可能发生问题的内部邮件列表,并且告知他们此类讨论应该立刻公开。

对于开放的封闭项目,还有一些其它的长期关注。Chapter 4, 社会和政治的基础架构探索了混合付费和未付费开发者的技巧,Chapter 9, 许可证,版权和专利讨论了当公开的私有代码基包含其它组织编写或“拥有的”软件时所必须承担的法律义务。



[10] 我们这里不是为了还债,而是实践我前面讲的说教:这位观察者的名字是Brian Behlendorf,他指出了除隐私原因以外,保持所有讨论公开的普遍重要性。

[11] 无论如何,这是开源项目常见的做法。在更集中式的项目中,“代码评审”也也意味着许多人坐在一起,一起察看打印的源代码,寻找特定的问题和模式。