社会和政治的基础架构 有关自由软件,人们经常问到的第一个问题是:“它能行吗?如何保持项目一直运行?谁来做决定?”我一直对关于知识界精化、合作精神、代码会说话此类的平淡回复无法感到满意。事实是这个问题很难回答。知识界精化、合作精神和运行代码只是其中的一部分,但它们对于解释日复一日的项目运转贡献不多,对于如何解决冲突什么也没说。 本章尝试展示支持成功项目的共同结构。 “成功”不仅仅指的技术质量方面,而且也包含了运行健康状况和生存性。运行健康状况是指项目将新代码和新开发者吸收进来,并对到来的bug负责的持续能力。生存性是项目独立于任何单独参与者或赞助商而存在的能力—考虑一下如果项目所有的创始成员离开后项目继续运作的可能性。技术成功不难实现,但是如果没有健壮的开发者基础和社会基础,一个项目就不能处理由初始的成功带来的成长,或者有魅力个体的离开。 获取此类成功有很多方法。有些涉及正式的管理结构,通过哪些争论被解决、新开发者被邀请加入(有时是离开)和计划的新特行等等。还有一些涉及不太正式的结构,但需要更有意识的自我克制,来产生一种人们可以依赖的正直氛围,作为事实上的管理形式。两种方式都产生相同的结果:一种由来已久的永恒感觉,由所有参与者都充分理解的习惯和程序作为支撑。这些特性在自我组织的系统中甚至比集中控制的系统更重要,每个人都知道一个坏苹果可以毁掉一桶,即使只是一会儿。 分叉能力(forkability) 能将开发者绑定在一个自由软件项目中的必需组成部分,能让他们在必要时愿意作出妥协,是代码的分叉能力:也就是任何人可以使用一个拷贝并使之成为一个竞争项目的能力,被称为分叉。怪异的是自由软件项目的中分叉可能性具备比实际的分叉更大的动力,很少会发生。因为分叉对于每个人都不好(会解释详细原因),分叉的威胁越大,越期望的人就越会妥协去避免它。 分叉,更确切说是分叉的可能性,是自由软件项目中没有真正独裁者的原因。考虑到在一个特定开源项目中听到某人被称为“独裁者”或者“暴君”是多么常见,这看起来是一个令人惊讶的断言。但是此类暴政是特别的,与一般意义上的字面理解非常不同。想象一下一个国王的臣民可以在任何时候复制整个王国,并搬过去按自己满意的规则统治。这与国王无论如何做,臣民都无法离开的情况是多么的不同? 这也是为什么即使项目不是完全按照民主方式组织时,在实践中,重要决定还是通过民主方式产生。可复制性暗指了分叉能力;分叉能力暗指了意见一致。也可能是每个人都希望与一个领袖不同(最有名的例子是在Linux内核开发中的Linus Torvalds),但那是因为他们选择如此,以一种非愤世嫉俗和非邪恶的方式。暴君没有项目的定身法。所有开源许可证都有一个关键特性,也就是在代码如何变更或使用上没有给任何组织更多的权力。如果一个独裁者突然开始做了一个坏的决定,就从此不得安宁,紧接着就是造反和分叉。除非,当然,很多时候不会到这一步,因为独裁者会首先妥协。 但仅仅因为分叉能力放置了一个上一个人在一个项目中发挥多少力量的上限,并不意味着项目的管理方式没有太大的区别。你不会希望每个决定都是某人要考虑分叉后的结果。那样会让人迅速疲倦,丧失真正工作的能量。下面两个小节会仔细检查组织项目平稳做出大多数决定的不同方法。这两个都是极端理想的例子;许多项目会处于中间状态。 慈善独裁者 慈善独裁者模型这一称号确实名副其实:最终的决定权完全取决于一个人,因为其人格和经验的力量,他被认为可以明智的运用这个权力。 尽管“慈善独裁者”(BD)是这个角色的标准术语,但是更应该将其视为“社区认可的仲裁者”或“裁判者”。通常来说,慈善独裁者并不会作出所有的、甚至大多数的决定。一个人很难拥有在项目所有领域中都能做出正确决定的专业技能,毕竟,如果对于项目的方向没有任何影响,有价值的开发者也不会在此停留。因此,慈善独裁者通常不会非常的独裁。相反,他们会尽可能的让事情在讨论和实验中顺其自然。他们自己也会参与讨论,但是作为某领域的普通开发者,他们一般会尊重拥有更多专业知识的领域维护者。只有当明显无法得出结论时,而且大多数成员期望有人能够指导作出决定,并让开发继续时,他们才会采取坚定的立场并说“这是我们前进的路。”避免使用命令作决定是所有成功慈善独裁者共同的特征;也是他们设法保持这个角色的一个理由。 谁可以成为一个慈善独裁者? 成为一个BD需要许多特性的组合。首先,要对自己在项目中的影响有经过充分磨练的敏感性,这样可以保证自我约束。在一个讨论的早期阶段,一定不能过于确定的表达自己的意见和结论,以至于让别人觉得继续发生分歧毫无意思.人们应当能自由的放飞思想,即使是愚蠢的想法。BD也会不可避免的屡屡发表愚蠢的意见,所以这个角色也必须具备认可和承认自己作出错误决定的能力—尽管这是一个所有优秀开发者都应该具备的能力,但如果她要长期呆在一个项目,这一点特别重要。但区别是BD无法无视其信誉的长期损害。但资历尚浅的开发者不必如此谨慎,所以BD必须对批评或反对决定的语句小心措辞,对于词汇的分量十分敏感,不仅是技术上的,还包括心理的。 BD的技术技能需要超越项目中的所有人。但她对于自己的代码工作必须足够精通,也必须能够理解考虑中的所有变更的讨论,但这还不够。BD的位置并不是通过恐怖的编码技巧获取或保持的。重要的富于经验和全局的设计感觉—不必是根据要求生产好设计的能力,只需要有识别好设计的能力,无论是什么来源。 慈善独裁者经常是项目的创建者,但这只是一种关系,而不是原因。这类特性让一个人能够成功的开始一个项目—技术能力、说服别人加入的能力等等—也都是BD所需要的。当然,创建者开始就自动有了相关的资历,在成为慈善独裁者的方法中,是所担心的阻力最小的。 请记住,潜在的分叉会以两种方式出现。一个BD可以和其他人一样分出一个项目,确实有些人已经这样做了,这是因为他们觉得要将项目带领到大多数项目成员不希望的方式中。因为可分叉的能力,慈善独裁者是否有项目主服务器的root权限(系统管理员特权)并不重要。人们有时候会将服务器的控制能力当做对于一个项目的权力根源,但实际上这毫不相干。将某服务器上某人的提交密码添加或删除的能力只会影响存放在那个服务器上的项目拷贝。对于此权力的长期滥用,无论她是BD或其他人,都会致使开发转到其他服务器上。 无论你的项目是否存在一个慈善独裁者,或能够在一个较弱的集中式系统下运行良好,都十分依赖于谁在承担这个角色。作为一个普遍的规则,通常对每个人来说谁是BD非常的明显,然后就会如此继续。但是如果没有明显的BD候选者,项目通常会使用分散的决策过程,这就是下个小节所描述的。 共识为基础的民主(Consensus-based Democracy) 随着项目的成长,通常会从慈善独裁模型转为更开放的民主系统。这不一定是源于对某个BD的不满,借用一个生物学的隐喻,可以简单的认为团队基础的管理更加“进化稳定”。每当一个慈善独裁者引退,或尝试将决策责任更均匀的分配出去,这就是团队选定一个新的非独裁系统的好机会—也就是要建立一套宪法。团队可能错过了第一次机会、或者第二次,但是最终会这样做;一旦做了,这个决定就不太会反转过来。常识解释了原因:如果某个N位成员的团队给某个人特殊的权利,也就意味着有N - 1位成员都愿意降低自己的个人影响。人们通常不愿意这样做。即使他们这样做了,所产生的独裁统治仍然是有条件的:团队推举了BD,团队也可以罢免BD。因此,一个项目的领导权一旦从某个魅力个人转移为更正式的团队为基础的系统,就很少会走回头路。 这类系统的工作细节有很大的区别,但是有两个共同的元素:首先,团队大多数时候在达成共识的情况下工作,其次,在无法达成共识时有一个正式的表决机制。 共识仅仅意味着每个人都能够接受的一种协议。它不是一种含混的状态:当有人提出某个共识已经达成,而且没有人提出反对意见,我们说一个团队对某个问题达成了共识。当然,提出共识的人应当详细说明共识的内容,如果不是显而易见的话,还要说明后续的动作。 一个项目的大多数对话是关于技术主题的,例如修正bug的正确方法、是否添加某个特性、以及文档接口有多严格等等。共识为基础的管理之所以可以工作正常,是因为它无缝的混入了技术讨论当中。在一个讨论的最后,通常是确定方向的协定。某些人会创建一个结论帖,作为所作决定的总结,同时也是隐含的共识提议。这也给了某人最后一次机会说“等等,我对此并不同意。我们应该再讨论一下。” 对于小的有争议的决议,这种共识的提议是隐含的。例如,当一个开发者本能的提交了一个bug修正,提交本身就是一个共识提议:“我料定我们都认可这个bug需要修正,而这就是我做的修正。”当然,开发者不会真的这么说;她只是提交修正,而项目中的其他人无需表明立场,因为沉默代表了认可。如果有人提交的结果没有导致共识,结果就是项目会象这个变更没有提交一样进行讨论。这个方法可以正常工作的原因请看下一个小节。 版本控制意味着你可以放轻松 如果项目源代码已经纳入版本控制,这意味着大多数决定都可以轻易的取消。一个常见的情况是某人自以为提交了一个别人会喜欢的变更,但实际上并不如此。通常始于反对者对于遗漏某个预先讨论的道歉开始,当然,如果反对者在邮件列表归档中没有发现此类讨论的纪录,可以省略这一步。另一个方法是,变更是否已经提交没有理由影响我们讨论的基调。所有的变更都可以回退,至少在引入依赖的变更之前都没有问题(例如,在移除原来的变更后会破坏新代码)。版本控制系统让项目有能力收回错误或仓促判断的后果。这也释放了人们,使他们对于做任何事情之前所需要的反馈可以相信自己的直觉。 这也意味着达成共识的过程不需要非常正式。许多项目跟着感觉处理。小的变更可以直接引入,而无需讨论,或者只需要通过最少的讨论来点头确认。对于重要的变更,特别是有可能造成大量代码不稳定的变更,人们应当需要等待一两天才能达成共识,不应当因为某人没有足够频繁的检查邮件,而将其排斥在对话之外。 因此,当某人相信他知道应该做什么,他应当继续前进和完成它。这不仅仅适用于软件修正,也可以用于网站更新、文档变更和其他任何不会引起争议的事情。通常情况下,需要进行回退操作的情况很少,应当根据实际情况处理。当然,不应当鼓励人们刚愎自用。正在讨论和已经生效的决定会造成一定的心理差异,即使它在技术上是可逆的。人们一直认为动力等同于行动,相对于回退变更,人们更情愿在开始的时候阻止它。如果开发者滥用这个事实,过于快速的提交有争议的变更,不管怎样,人们可以也必然会抱怨,会将开发者置于更严格的标准,直到事情改进。 如果无法达成共识,那么表决! 不可避免的,一些争论无法达成共识。当打破死锁的所有其他方法都已经失效,最后的方案就是表决。但是,在表决之前,一定要理清表决的选项。这里一切又重演了,技术讨论的正常过程会混合项目决策程序的偶然发现。此类需要表决的问题通常会很复杂,具有多方面的问题。在所有此类复杂讨论中,需要有一两个人扮演诚实的中间人的角色:定期发布各种论点的摘要,并保持对于分歧(和一致意见)核心论点的跟踪。这些摘要可以帮助每个人评估所做工作的进展,并提醒每个人还需要解决什么问题。如果需要表决,这些摘要也可以作为表决表格的原形。如果诚实中间人的任务完成的好,当时机成熟就可以发布表决的可信请求,而团队会希望使用以他们对于此问题的摘要为基础的表决表格。中间人自己也可以参与辩论;只要他们可以理解并公平的表示其他人的观点,不会因党派观点而影响以中立地态度总结辩论的状态,就没必要让他们脱离争论。 表决的实际内容通常不应当是有争议的。当表决时刻到来,分歧通常会归纳为一些包含可识别的标签和简短描述的关键问题。偶尔某个开发者会反对表决本身的形式。有时候他的考虑是有道理的,例如,一个选项被遗漏了或描述的不够精确。但是还有一些时候,开发者仅仅希望避开这个表决,因为他知道表决不会得到自己期望的结果。如何处理此类蓄意阻挠可以看 要记住指明表决系统,因为有许多不同的类型,人们很容易错误的假定使用某个步骤。大多数情况下的较好选择是同意表决(approval voting),也就是每个表决者可以选择多个中意的选项。同意表决易于解释和统计,也不会像其他方法那样,它只有一轮表决。关于同意表决和其他表决系统的更多细节可以看,但是要避免陷入使用何种表决系统的长期辩论(因为,当然你会发现你陷入了使用何种表决系统选择表决系统的辩论!)。同意表决是正确选择的一个原因是任何人都很难反对—作为表决系统它足够公平。 最后,公开引导表决。没有必要对公开讨论的事务进行秘密或匿名的表决。让每个参与者在项目邮件列表中发布自己的表决,这样每个观察者都可以自己检查结果,而且所有的内容都会记录到归档中。 何时表决 最难的事情是决定何时开始表决。通常情况下,很少会进行表决—是其他方法都失败后的补救方法。不要将表决当作解决争辩的重要方法。它不是。它可以终结讨论,也会结束关于此问题的创造性思考。只要讨论还会继续,就有可能会有人得出所有人满意的解决方案。这经常令人吃惊:活跃的争论可以产生关于问题的新方法,也会得出使每个人都满意的提议。即使没有出现新的提议,通常采纳某种妥协也比举行表决要好。经过妥协,每个人都或许会有点不高兴,但是表决过后,有些人会开心,还有些人会失望。从政治视角,前一种状态更可取:至少每个人都会感到为自己的不快萃取了一定的价值。他会不满意,但其他人也一样。 表决的主要优点是最终可以解决问题,这样每个人都可以继续前进。但是通过数人头,而不是通过有理性的对话解决问题,导致每个人得出相同的结论。开源项目中的人越有经验,就会越发现他们越不会急于用表决解决问题。相反,他们会尝试考察以前未考虑的解决方案,或者对以前计划的方法进行较大的妥协。有许多技术手段可以防止过早的表决。最明显的方法是说“我觉得还没有准备好开始表决,”然后解释为什么还不行。另一个方法是要求进行非正式(无约束力的)的举手表决。如果结果明确倾向到一边,就会让某些人立刻更希望进行妥协,以避免正式的表决。但是最有效率的方法是简单的提供一个新的方案,或者一个较早建议的新视点,所以人们可以重新审视问题,而不是简单的不断重复同样的论点。 在某些很罕见的情况中,每个人都认为所有折中的解决方案都比任何一个非折中方案要差。当这种情况发生时,表决就会有较少的异议,不仅仅因为它能够得到一个高人一等的解决方案,而且是因为这样不会导致所有人对结果感到不高兴。尽管那样,表决也不应该匆忙进行。导致表决的讨论可以教育全体选民,所以过早的结束讨论会降低结果的质量。 (要注意前面所说的表决建议不适用于中描述的变更包含表决。此时,表决更像是一种交流机制,一种在变更评审过程注册某人参与的方法,这样每个人都可以说出对于一个变更收到了多少评审。) 谁进行表决? 有了表决系统就会出现一个全民选举的问题:谁应该表决?这有可能成为敏感的问题,因为它强制项目正式识别出一些更应该参与的人,也就是比其他人更有判断力的人。 最好的方法是采用已存在的划分,提交访问,并为他们附加表决特权。在提供完全和部分提交访问的项目中,部分提交者是否可以表决的问题,很大程度上取决于部分提交访问被赋予的过程。 如果项目自由处理,例如,在版本库中维护许多第三方贡献工具的方法,那时就应当澄清部分提交访问只是关于提交,而不是表决。相反的暗示自然也成立:因为完全提交者有提交特权,他们应当不仅仅是程序员,而且是全民选举的成员。如果某人在邮件列表中有分裂或破坏倾向,那么要小心将其加为提交者,即使这个人在技术上非常娴熟。 表决系统本身应当用来选择新的提交者,包括完全和部分提交者。但这是一个不太常见的需要注意保密性的情况。你不能为一个潜在的提交者在公共邮件列表表决,因为不能伤害候选者的感情(和荣誉)。相反,通常的方法是某个现有的提交者在只包含提交者的私有邮件列表中发布一个私有邮件,建议给某人附加提交权限。其他提交者可以自由发表意见,他们清楚讨论是私下进行的。通常没有异议,因而没有表决的必要。在等待几天之后,确保每个提交者有机会回应之后,提议者通知候选者并赋予其提交权限。如果存在异议,因而出现其他问题的讨论,可能会导致表决。因为这个过程需要开放和坦白,所以发生讨论的事实应当完全保密。如果被考虑的人知道事情的进展,然后没有提供提交权限,他可能认为他已经在表决中失败,会感到受到伤害。当然,如果某人明确的要求提交权限,没有其他的选择,要么同意,要么拒绝。如果是后者,应当尽量的有礼貌,并使用清晰的解释:“我们喜欢你的补丁,但是还没有看到足够的补丁,”或者“我们感谢你的补丁,但是在实际使用之前需要相当大的调整,所以我们觉得现在还不能放心给你提交权限。我们希望下一次会有些改观。”请记住,你所说的会是一个打击,这要看个人的自信心水平。应当从他们的角度想想如果你看到那些邮件的感觉。 因为添加新提交者不是那种一次性决定,会有后续的结果,某些项目会有表决的特殊要求。例如,他们会要求提议至少获得n个肯定的表决,而且没有否定的表决,或半数以上的赞同票。精确的参数并不重要;主要的思想是在添加提交者时需要让团队小心处理。类似的,或更严格的,特别的需求也可以应用到选举移除提交者上,尽管很希望那永远没有必要发生。关于添加和移除提交者的非表决方面的信息可以看 民意调查与表决 对于特定类型的表决,有时候扩展选民会很有用。例如,如果开发者只是不能确定哪种界面符合人们实际使用软件的方式,一个方法就是询问项目邮件列表中的所有人进行表决。这更应该叫做民意调查而不是表决,但是开发者可能将结果视为有约束力的。在任何民调中,要确保参与者可以附加选项:如果某人对于民调问题想到了更好的选项,她的回应会成为最重要的民调结果。 否决权 某些项目允许一种特殊的表决类型,称为否决权。否决权是一种开发者停止仓促或考虑不够充分变更的方法,至少希望每个人能够再进行一些讨论。考虑到否决权介乎于强烈反对和阻挠之间。它确切的含义对于每个项目都不尽相同。有些项目让否决很难被逾越;有些则允许经过强制的更多讨论延迟后,被普通的多数投票替代。任何否决必须伴随完整的解释;任何没有这类解释的否决都应当被认为是无效的。 否决权会带来对其的滥用。有时候开发者会急迫的通过否决权来为自己的论点加重砝码,而真正需要的是更多的讨论。你可以通过自己对于否决权的勉强使用来防止对于否决的滥用,并有礼貌的警告某人太过频繁的使用否决权。如果必要,你可以提醒团队,否决权只在团队也认可的时候有效—毕竟,如果很明显大多数开发者希望X,那么就应该采纳X。否决的开发者要么自己让步,要么让团队决定削弱否决权的作用。 你可能会看到人们写了一个“-1”来表示否决。这种方法来自拥有高度复杂表决和否决过程的Apache软件基金会,具体内容可以看。Apache标准也传播到了其他项目,你可以看到他们的习惯在开源世界的许多地方以不同的面貌出现。从技术上讲,即使根据Apache标准,“-1”也不是表示正式的否决,而只是一种表达否决或强烈反对的非正式方法。 类似于表决,否决权也可以是追加的。如果有问题的变更已经提交,行动已经执行(除了一些不可挽回的事情,例如新闻发布),不应该以此为理由反对一个否决。另一方面,如果否决在事情发生几周后才出现,它也不会被重视,而且这种情况根本不应该发生。 写下所有的内容 有时,项目中的许多广为流传的惯例和协定变得非常重要,你需要记录下来。为了保证这种文档的正统性,要清楚的表明这些内容基于邮件列表的讨论,并已经形成协定开始生效。随着你的编写,应当引用邮件列表归档中的相关讨论,对于任何不能确定的要点,要重新询问并确认。文档中不应当包含任何出其不意的东西:它不应当是协议的来源,而只是对于协议的描述。当然,如果它足够成功,人们会开始引用它来作为自己权利的来源,但是这只是说明它精确的反映了团队的整体意愿。 这是暗示的文档。当然,当项目还非常年轻时,你无法依靠项目的历史来规划指导方针。但是随着开发社区的成熟,你可以调整这些语言以反映实际的内容。 不要尝试全面。没有文档能够涵盖参与一个项目所需的所有事情。许多项目演进出的习惯是永远不会说出来的,永远不会明确提出来,即使是所有人遵循的。还有一些内容则明显太过简单,无需提及,只会分散人们对于重要内容的注意力。例如,没有必要写下指导方针如“在邮件列表中要有礼貌,要互相尊重,不要激烈的争论”或“要写清楚的、可读的和无bug的代码。”当然,这些事情都是人们希望的,但是因为没有想像到他们可能不会渴望得到的东西,所以没有价值去提及。如果人们在邮件列表中过于粗暴,或编写了充满bug的代码,不会因为项目指导方针没有说,他们就会继续下去。这种情形出现时就会需要被处理,不会因为预先的劝诫就会好起来。另一方面,如果项目有关于如何写好代码的指导方针,例如关于使用何种格式记录API的规则,那么这个指导方针就应该尽可能的写完整。 决定将什么内容纳入文档的最好方法是以新来者所经常询问的问题,以及资深开发者最经常的抱怨为基础。这不是说一定要变成一个FAQ表单—很可能需要一个比FAQ所能提供的更连贯的叙述结构。但是它必须遵循事实为根据的原理,记录问题实际发生的地址,而不是好像你预期会出现。 如果项目是一个慈善独裁者所有,或者有拥有特殊权利的官员(总裁、主席或其他),那么继任程序也应当制定成法律形成文档。有时候,这仅仅是BD因故突然离开项目并简单的指定继任者。通常情况下,如果有一个BD,那么只有BD可以离开并提名继任者。如果有竞选的成员,那么文档就应该描述从中取出第一名的提名和选举程序。如果原来没有程序,那么在编写应该在邮件列表中达成共识。人们有时候可能对于等级结构十分敏感,所以主题应当敏感的达到这个目标。 可能最重要的事情是表明规则是可以商量的。如果文档中规定的习惯变得束缚了项目,要让每个人想到这是一种对于团队意愿的生动反映,而不是挫折和堵塞的来源。如果某人养成了每当遇到妨碍自己的规则都要求重新考虑规则的习惯时,你不需要一直与其辩论—有时候沉默是最好的策略。如果其他人认可这种抱怨,他们会插话,也就是意味着某些事情很明显需要改变了。如果没有其他人认可,人们就不太会响应,那规则还是会保持不变。 两个指导方针的好例子是Subversion的hacking.html文件,在,以及Apache软件基金会管理的文档,在。ASF是真正的一组软件项目,合法的组织成一个非盈利公司,所以它的文档倾向于描述管理程序,而不是开发惯例。他们也值得阅读,因为他们代表了许多开源项目积累的经验。