管理志愿者 让人们认可项目所需要的,并一同努力实现,不仅仅需要友好的氛围和避免明显的功能异常。需要某个人或一些人有意识的管理所有参与的人。管理志愿者可能不像计算机编程具有同样的技术技巧,但它是一种可以通过学习和实践改进的技艺。 本章是管理志愿者技术的摸彩袋。可能描绘的分量远重于之前的章节,会以Subversion项目作为案例研究,一方面因为我在这个项目工作,所有主要的资源就在手边,也因为砸自家的玻璃总比砸别人更能让人能接受吧。但是我也看到许多其他的项目因为应用这些建议而获益,以及未能应用的后果;当在政治上适合给出这些项目的案例时,我就会这样做。 说到政治,这是在近距离观察以抛弃那些恶毒语言的好时机。许多工程师认为政治只是其他人参与的东西。 “我只是提出对于这个项目最好的过程,但是出于政治原因提出反对。”我相信政治(以及那些认为是政治的事情)的灾难在工程师中特别强大,因为工程师带来的思想中总有些解决方案是客观的优于其他方案。因此,当有人被思考之外的方式激发—例如维护自己的影响,削弱其他人的影响,草率的讨价还价或避免伤害某人的情绪—项目中的其他参与者就会感到恼怒。当然,当关系到他们自己的关键利益时他们也很难避免这样做。 如果你认为”政治“是一句肮脏的词汇,希望你的项目远离它,请放弃吧。当人们需要合作的管理共享资源时,政治是不可避免的。每个人在作出决策时,都会很自然的考虑到决策的结果对自己在项目中影响力的影响。毕竟,如果你像其他程序员一样相信自己的判断和技能,那么未来影响力的降低也可以看作是技术的结果。同样的远离可以应用于其他的行为,从表面上看就是”纯粹的“政治。事实上,没有纯粹的政治:这是因为如果人们把政治作为首要考虑的因素,则行动在实际上会有多重的后果。最终,政治只是决策所要考虑的所有后果的一种承认。如果某个决策的结果可以让绝大多数参与者在技术上感到满意,但是会导致力量对比发生变化,使关键人物感觉自己被孤立,那么后者与前者同样重要。忽略它并不是高尚,只是短视。 就像你后面将要读到的建议,以及你自己工作的项目,请牢记没有人是高于政治的。对于高于政治的企图仅仅是一种特别的政治策略,有时非常有用,但并不现实。当某人有分歧时政治已经出现,成功的项目能够将政治机制建设性的用于管理分歧。 从志愿者中获取最多 志愿者为什么要为自由软件项目工作?这个问题已经被详细研究,Karim Lakhani和Robert G. Wolf的一篇论文有非常有趣的结果,题目为Why Hackers Do What They Do: Understanding Motivation and Effort in Free/Open Source Software Projects。见 当被询问时,许多人声称自己只是因为希望制作好软件,或希望自己修复所需要的bug。但是这些原因并不是完整的故事。毕竟,你能想象如果没有人欣赏他的工作或倾听他的讨论,这个志愿者还会呆在这个项目吗?当然不会。很明显,人们在自由软件上花费时间的原因不仅仅是单纯的对生产良好代码的渴望。理解志愿者的真实动机将会帮助你能够合理的安排,以确保吸引和保持他们。对生产优秀软件的渴望、在复杂问题上获取的挑战和学习价值也许都是动机。但是人们有与其他人一起工作的内在期望,并在合作活动中提供和获取尊重。从事合作活动的团队必须进化出行为的标准,能够通过帮助团队的活动获取并保持那种地位。 这些标准并不总能自己出现。例如,在一些项目中—资深的开源开发者可以从顶级人员中去除几个人—人们明确的感觉到是通过频繁并详细的发布取得的这种地位。他们并不是偶然得到这个结论;这是因为他们曾经因进行长时间的,复杂的辩论中而得到尊重的回报,即使对项目没有实际的帮助。下面是一些创建氛围的技术,可以让获取地位的活动与建设性活动一致起来。 委派 委派并不仅仅是将工作分散的方法;它也是政治和社会工具。考虑你要求某人做什么事情的所有效应。最明显的效应是如果他接受,就是他完成任务不是你。但是另一个效应则是他意识到你信任他能够处理这个任务。此外,如果你是在公共论坛发起这样的请求,那么他也知道团队中的其他人也表明了对他的信任。他也能感受到需要接受一些压力,这意味着你询问时要使用一种允许他拒绝的方式,如果他确实不想做这个工作的话。如果这个任务需要在项目中协调,你这样做可以有效的提议他更深入的参与进来,形成其他方式无法形成的契约,而且也有可能成为项目某个子领域权威的起源。增加的参与或许令人畏惧,也或者会导致他以其他方式参与进来,例如对于整体承诺的更多感觉。 因为所有这些效应,所以即使你认为你可以完成的更好更快,让其他人来完成也很有意义。当然,也有一个严谨的经济学效率作为论据:或许你自己完成的机会成本太高—在同一时间里你可以完成许多更重要的事情。但即使机会成本的论据并不适应,你还是会希望其他人完成这个任务,因为从长期来看你希望人们更深入的参与到项目当中,即使一开始需要花费更多的时间关注他们。相反的技术也适应:如果你偶然志愿完成其他人不喜欢或没时间完成的工作,你会得到他的友好关系和尊敬。委派和代理并不仅仅是要完成单个任务;他们也是将人们引入到项目核心的方法。 明确区分调查和指派 有时可以很明确的期待某人会接受特定的任务。例如,如果某人编写的代码带来了bug,或者提交的代码明显未能符合项目的指导方针,那么直接指出问题,那么之后你可以认为他会小心避免此类问题。但是在一些情况下,没有明确的方法可以确保你获得期望的行动。这个人可以听你的,也可以不听。因为没有人喜欢被熟视无睹,你需要敏感的察觉到这两种情形的区别,并以此为依据调整你的请求。 你让某人做某事,如果你采用的方式让人感觉这是他理所当然的责任,而实际上他并不是这么想的时,几乎一定会立刻让他们感到非常的厌恶。例如,分配的问题可能会带来很多讨厌的事。项目的参与者通常知道谁是某个领域的专家,所以当出现了bug报告,通常会有大家都知道的一两个人可以立刻快速的修正它。然而,如果你没有得到先前的许可就将问题分配给她,她会感觉自己处于一个不舒服的地位。她会感受到这种被期望的压力,而且感觉她是由于其专业技能而被惩罚了。毕竟,获取技能的方法就是通过修正bug,所以某人会接受这个问题!(请注意,在问题跟踪系统中根据bug报告的信息自动分配的问题通常并不太冒犯,因为每个人知道分配是自动的过程,并不代表人们的预期。) 虽然应该尽可能将负担均匀的分配,但有时你需要鼓励能够以最快速度修正bug的 人。考虑到你可能无法承受为每个这种分配进行这种交流的负担(“你愿意看一下这个bug吗?” “可以。” “好的,一会儿吧这个问题分配给你。” “好的。”),你应当以询问的形式进行分配,不要传递出任何压力。事实上所有的问题跟踪系统都允许为任务分配的问题作出评论。在那个评论中,你可以这样说:
把这个分配给你,jrandom,因为你可能是最熟悉这些代码的。如果没时间,尽管踢回来。(如果你想在以后接受这中请求,请让我们知道。)
请求完成工作与某人接受工作有明显的区别。在这里观众不仅仅是被分配工作的,而是所有人:整个团队可以看到被安排工作的人的专业技能得到了公开的确认,但是这些信息也明确的表明他可以自由的接受或者拒绝这种责任。
指派后要继续跟踪 当你要求某人做一些事情时,请牢记所做的,并无论如何要继续跟踪他。大多数请求是在公共论坛中做出的,形式大体上类似“你能处理一下X吗?我们只是要获知;如果你不行,那么没问题,我们只需要知道。 ”不一定会得到回应。如果你得到的回应是负面的,则环路可以关闭—你需要尝试其他的策略来处理X。如果有正面的回应,那就需要继续关注这个问题的进展,并为可见和不可见的进展作出评论(当知道其他人会欣赏他的作品时,每个人都会做的更好)。如果几天内没有回应,可以再次询问,或者发表文章说明你没有得到回应,希望找其他人做这件事。或者直接自己完成,但也要说明最初的询问未能获得回应。 公开提示缺乏回应的目的并不是要羞辱任何人,你的评论一定不要造成这种效果。目的仅仅是说明你还在跟踪自己征求的问题,而且你已经注意到了一些反应。这样做可以增大人们在下一次说同意的机会,因为他们会知道(即使只是无意的)你会注意到他们所做的任何工作,包括许多不太起眼的,人们会忽略的事件。 通知感兴趣的人 另一件可以让人们高兴的事情就是通知他们所感兴趣的事情—通常情况下,你注意到并记住某人的个性方面越多,他会越觉得舒适,他也就越会希望参与你的团队一起工作。 例如,在Subversion项目有一个非常有明显区别的划分,期望达到决定性的1.0发布的人,和那些主要希望添加新特性,并完成感兴趣的问题,但对1.0并不太关心的人。两者的地位相当;他们只是不同类型的开发者,都在项目中完成了大量工作。但是很快认识到我们绝不能假设所有的人都是由1.0发布的喜悦所驱动的。电子媒介可能很有迷惑性:在你感觉到共同目标的氛围中,实际上只是你与谈过话的人有共同的目标,而其他人则有完全不同的优先级。 你对人们对于项目的期望了解越多,你就越能有效发出请求。即使仅仅是描述一下他们所期望目标的理解,甚至不必发出任何相关的请求,也非常有用,这样可以确保所有人不仅仅是无差别群众中的粒子。
赞扬和批评 赞扬和批评并不矛盾;在大多数情况下,是类似的。都是关注的形式,越是明确就越有效。二者必须在牢记实在目标的情况下实施。两者都有可能因为夸大而削弱:赞扬过多或太频繁会使赞扬贬值;对批评也是同样,尽管在实践中,批评通常会有反作用,因而更加不容易贬值。 一个重要的技术文化特性是将详细的,不带偏见的批评当作一种赞扬(正如在中所讨论的),因为这隐含了接收者的工作值得花时间去分析。然而,两种条件—详细的不带偏见的—必须同时满足。例如,如果某人对代码做了些马虎的修改,如果只是说“很马虎”是毫无用处(而且通常是有害的)的。马虎最终是的一种特性,而不是作品的,应该将反应集中到作品上。更有效的方法是描述变更中所有错误的地方,巧妙而无恶意。如果这是某人连续第3,或者第4次作出疏忽的修改,则可以再说一次这些事—不必发怒—批评的最后,要清楚的说明同样的模式早已经被注意到了。 如果某人对于批评不做任何改进,解决办法不应该是更多或更强的批评。对于团队来说,解决方法是将这个人从不能胜任的位置删除,并尽可能使用一种不会造成情绪伤害的方法;见本章后面的例子。但实际上,这种情况通常很少发生。大多数人可以很好的回应批评,当然批评必须要特定,详细并有明确的(即使没有说出来)改进预期。 赞扬不会伤害任何人的感情,但并不意味着使用时可以不像批评那样小心。赞扬是一种工具:在使用之前,要问自己为什么你希望使用它。作为一条戒律,不应该因为人们经常做的事情,或正常的和参与到团队中应当要做的行动赞扬他。如果你这样做,估计就停不下来了:你因为普通的事情而赞扬每个人?毕竟,如果你漏掉了某人,他们会问为什么。如果能珍惜你的赞扬和感激会更好,要针对不寻常或意料之外的努力,以鼓励此类努力为目的。当某个参与者永久的进入了更高生产力的状态,要根据此人调整赞扬的阀值。对普通的行为进行反复的赞扬会变得毫无意义。相反,这个人也应该感觉到自己较高的生产力水平已经是正常和自然的,只有超出这个范围的才会被特别关注。 当然,这并不是说不应该感谢某人的贡献。但是请牢记,如果项目设置正确,这个人做的任何事情都会看到,所以这个团队会知道(这个人也会知道团队中的其他人所知道的)所有她所做的。除了直接的赞扬,我们也有其他的方法感谢某人的工作。你也可以采用曲折战术,在讨论相关主题时,她已经给定领域做了许多工作,成为了领域专家;你可以公开的向她咨询代码的问题;或者更有效的,你可以大张旗鼓的进一步利用她的工作,这样她就会为别人依赖于她的工作结果而感到舒服。通常不必在这些问题上精打细算。那些有规律的为项目作出贡献的人知道自己会自然的得到有影响的地位。通常没有必要为此采取明确的步骤,除非你感觉到无论出于什么原因,贡献者都无法得到正确的评价时。 防止割据 请留意那些试图在项目中独占某一领域,或希望完成某一领域所有工作的参与者。此类行为已开始看起来很健康。毕竟,在表面上似乎是某人在肩负更多的责任,并展示在特定领域增长的活动。但从长期来看,则并没有建设性。当人们感觉到“禁止入内”的标志时,他们就会离开。这种结果会减少这个领域的检查,会使之更加脆弱,因为孤单的开发者成为失败的单独一点。更严重的,它会削弱项目的合作,平等精神。理论上应该欢迎任何开发者在任何时间帮助完成任何任务。当然,在实践中会有些不同:人们在不同领域的影响总有差别,非专家通常与项目特定领域的专家不同。但关键是这都是自愿的:非正式的权威是根据竞争性和证明的判断能力赋予的,而不可以主动的获取到。即使某人期望的权威是能够胜任的,仍然需要她非正式的保持权威,通过团队的共识和那种永远不会将其他人排除在该领域之外的权威。 当然,因为技术原因反对或编辑某人的工作则是完全另外一回事。决策因素是工作的内容,而不应该是谁恰好是守门人。也许也是同一个人完成恰好完成了最多的工作,但只要他没有阻止其他人完成这个工作,就没有问题。 为了对抗地方主义的萌芽,许多项目采用禁止在源代码文件中包含作者名或维护者签名的方法。我完全认可这种实践:我们在Subversion项目中也遵循这个方法,这也算是Apache基金会的一种正式政策。ASF成员Sander Striker是这样做的:
在Apache软件基金会中我们不鼓励在源代码中使用作者标签。除了法律分歧以外,还有多方面的原因。协作开发是以一个团队一起工作,将整个项目看作一个团队。给予信誉非常好,必须有人这么做,但是必须使用不会允许错误归因的方式,即使是通过暗示的方式。何时添加或删除作者标签没有明确的标准。在你修改注释后添加你的名字?或者是添加了一行的修正?在你重构了代码,改变了95%时就可以删除其他作者的标签?当人们去接触每一个文件,修改足够多的内容以达到名字标签的限额,这样他们的名字就会出现在每个地方时,你会怎么做? 提供信誉可以有更好的办法,我们推荐这些。从技术观点上讲,作者标签并不是必需的;如果你希望知道哪个人写了某段代码,版本控制工具可以提供。作者标签也经常失去时效性。你希望被私下咨询5年前编写,而且已经希望遗忘的代码?
软件项目的源代码文件时身份的核心。必须要反映整个开发社区为此负责,而不仅仅是简单的各自的封地。 人们有时会为源代码中作者或维护者标签的风格而争论,他们认为这些东西是所做工作的可见信誉。这种论点有两个问题。首先,不可避免的要面对多少工作量才可以进入这个列表的尴尬问题。其次,这样会将信誉的问题与权威合并了:过去曾经完成了工作并不意味着对于曾经工作区域的所有权,但是如果单个人的名字出现在源文件的顶部,想避免这种暗示就变得几乎不可能。在任何情况下,信誉信息都可以从版本控制日志和其他诸如邮件列表归档等外带机制中获取,所以在源代码文件中禁止其出现不会损失任何信息。但是邮件列表中链接为“having authors names in .py files”的这篇文章是一个很好的抗辩,作者是William Stein。我认为关键在于许多作者来自一种将信誉直接取自源代码视为标准并高度评价的文化。在那种环境中,可能有必要将作者的名字置于源代码中,并精确的描述每个作者的贡献,因而大多数潜在的贡献者会希望有这种样式的承认。 如果你的项目禁止在源代码文件中包含姓名,请务必不要过分执着。例如,许多项目会有一个保存小工具和辅助脚本的contrib/区域,通常由与本项目不相关的人编写。这些文件可以包含作者姓名,因为他们完全不是由项目维护的。另一方面,如果贡献的工具被项目的其他人修改了,最终你希望将其从孤立的位置移出,如果原始作者许可,就可以删除作者名称,这样代码就像其他社区维护的资源一样了。如果作者对此有些敏感,折衷的方案也是可以接受的,例如:
# indexclean.py: 从Scanley索引删除旧数据。 # # 原始作者: K. Maru <kobayashi@yetanotheremailservice.com> # 现在维护者: Scanley项目组<http://www.scanley.org/> # 和K. Maru。 # # ...
但是最好避免此类折衷,如果可能,大多数作者会被说服,因为他们都会乐于自己的贡献更紧密的成为项目的一部分。 重要的是请牢记项目的核心和外围是一个连续体。项目的主要源代码文件显然是核心部分,会被认为应当是由社区维护的。在另一方面,伙伴工具或一些文档则可能是单独某个人的作品,始终独自维护,即使这些作品是与项目关联,甚至是与项目一起分发的。没有必要应用一个适用于所有文件的规则,只要坚持社区维护的资源不允许成为个人领土的原理就可以了。
自动化率 努力不让人做机器可以做的事情。作为一种经验法则,将一项工作自动化花费的工作量即使十倍于手工执行也是值得的。对于非常频繁或复杂的任务,这个比率可以轻松的达到20倍或更高。 将自己想象为“项目管理员”,而不仅仅是开发者,可能是一个有效的态度。有时,单个开发者会过于沉溺于较底层次的工作,而无法看到全局图并意识到每个人都在手工执行自动化任务上浪费了大量精力。即使那些意识到的人也可能不会花时间解决问题:因为每个个体都不会感觉此类任务是一个巨大的负担,没有人已经厌烦到要为此做些什么。使自动化如此引人注目的是每个很小的负担需要乘上每个开发者执行的次数,然后还要乘上开发者的数量 这里,我广泛的使用的术语“自动化”,并不仅仅是重复每次只需要修改1到2个变量的动作,而且包括任何辅助人们的技术基础架构。最低标准的自动化需要按照中描述的方式运行一个现在的项目,但是每个项目也都有自己的特殊问题。例如,一组编写文档的人会希望有一个网站能够在任何时间都显示最新版本的文档。因为文档通常由如XML的标记语言编写,会有一个编译步骤,通常非常复杂,包括创建可显示或可下载的文档。组织这种会在每次提交时进行此类编译的网站可能会有点复杂和花费时间—但是这样很值得,即使这要花费你一天或更多的时间。拥有最新网页的整体收益是巨大的,即使没有的代价仅仅是每个开发者需要每次多一些很小的烦恼。 进行这种步骤不仅仅可以消除时间的浪费,也可以确保消除在执行手工操作时步骤出错(不可避免的会发生)时的痛苦和沮丧。多步的,确定的操作恰好是发明计算机的目的;将人们拯救出来可以做更有意义的事情。 自动测试 自动测试对任何软件项目都有用,特别是开源软件项目,因为自动测试(特别是回归测试)可以让开发者舒服的修改自己不熟悉的代码,因而鼓励了探索性的开发。因为手工检测损坏是这样困难—需要从本质上猜测可能损坏的事情,而且必须尝试多种实验证明其没有损坏—通过自动化方法检测这种损坏为项目节省了大量时间。它也可以让人们可以更放松的大幅度重构代码,从而对软件的长期可维护性贡献良多。 回归测试 回归测试指的是判断已修正bug是否重新出现的测试。回归测试的目的是减少代码变更以不可预料的方式破坏软件的机会。随着软件项目的增大和复杂,这种不可预料的副作用会急剧增长。好的设计可以减少随着变更增长带来的这种比率,但是不能完全消除这种问题。 结果就是许多项目都有了一个测试套,一个单独的可以按照过去模仿bug发生的方式进行调用的程序。如果测试套成功的使某个bug出现,这被称作回归,意味着某人的变更意外的将以前修正的bug又修正回来了。 请看 回归测试并不是万能药。首先,它非常适于批量样式界面的程序。对于主要使用图形用户界面操作的软件很难程序化驱动。回归测试的另一个问题是测试套框架本身可能非常复杂,自己有一定的学习曲线和维护负担。减少这种复杂性是你可以做的一件非常有用的事,即使这需要花费相当多的时间。将新测试添加到测试套越简单,就会有越多的开发者这样做,发布中漏网的bug也就会越少。在使测试更简单上的努力将会在项目的生命周期中得到成倍的回报。 许多项目有一个“不要破坏构建!”的规则,意思是:不要提交会使软件不能编译或运行的变更。成为破坏构建的人通常会导致温和的窘迫和取笑。拥有回归测试套的项目通常有一个推论的规则:不要提交会导致测试失败的任何变更。如果整个测试套会自动每夜运行,随着结果发送到开发列表或专门的测试套列表,这类失败可以轻松定位;这是自动化价值所在的另一个实例。 大多数志愿开发者会愿意用额外的时间编写回归测试,只要测试系统是可理解的并易于使用。变更搭配测试可以理解为一种责任,也是协作的一种简单的机会:通常要由两个开发者分担bug修正的工作,其中一个编写修正本身,另外一个编写测试。后一个开发者通常要以更多的工作结束任务,因为编写测试并没有实际的修正那样让人愉悦,测试套不应当使测试体验超出本来应有的痛苦。 一些项目走的更远,每个bug修正或新特性都要伴随新的测试。这是否是个好主意取决于许多因素:软件的特性,开发团队的组成和编写新测试的难度。CVS()团队一直有这样一个规则。在理论上这是一个好政策,因为CVS是版本控制软件,所以非常希望规避处理或误处理用户数据可能性的风险。问题是在实践中CVS的回归测试套是一个单独的巨大shell脚本(好笑的是叫做sanity.sh),难于阅读,也难于修改或扩展。增加新测试的难度,以及对于新增补丁必须包含测试的要求,决定了CVS有效的阻碍了补丁。当我在CVS上工作时,我见过有人着手,甚至完成了一个CVS自己代码的补丁,但是当被告知需要在sanity.sh增加新测试时则放弃了。 编写新的回归测试比修正原来的bug花费更多的时间非常正常。但是CVS将这种现象发挥到了极致:一个人需要花费数小时才能正确的设计自己的测试,但仍然得到错误的结果,因为修改这样一个35000行的Bourne shell脚本有太多不可预测的复杂情况。即使是长期的CVS开发者也会为增加新测试而感到郁闷。 这种情况源于我们对于自动化比率考虑的失败。转换到一个真正的测试框架—无论是自定义的还是成品的—都会成为一种主要的动力。请注意,没有必要将所有已存在的测试转化到新框架;二者可以和平共处,只需要转化需要改变的测试。随着时间的推移,这种忽视给项目带来更多的代价。有多少bug修正和新特性未能进入现在的CVS,仅仅因为这尴尬的测试套的阻碍?我们不知道精确的数量,但是一定远大于开发者为了开发新测试系统(或集成一个成品的系统)而会放弃的bug修正或新特性数量。这个任务只会耗费有限的时间,但如果无动于衷,则使用现有测试套的惩罚将会永远持续下去。 重点不在于强制编写测试是错误的,也不是说编写Bourne shell脚本的测试系统必然是不好的。它可能工作的很好,这取决于你的设计和测试的需要。重点仅仅是说当测试系统成为开发的明显障碍时,必须要有行动。同样的道理适用于所有成为障碍或瓶颈的常规过程。 将每个用户当作潜在的志愿者 与用户的每次交流都是发展新志愿者的好机会。当一个用户花时间在项目邮件列表上发表文章或报告bug时,他已经认为自己比大多数用户(那些项目永远听不到回音的人)有更大参与的可能。紧跟这种潜力:如果他描述了一个bug,感谢他的报告,并询问他是否有兴趣自己修正它。如果他说FAQ中漏掉了一项重要问题,或者程序的文档有些不足,请坦率的承认问题(假定确实存在),并询问他是否有兴趣自己编写遗失的材料。很自然,大多数时候这个用户不会同意。但是多问一句也不累,而且只要你每次都这么问,也会提醒论坛中的其他听众参与到项目当中是每个人都可以做的。 不要将你的目标限制在新开发者和文档编写者上。例如从长期来看,即使训练人们编写优秀的bug报告也是值得的,如果你没有在每个人身上花费多时间,而且如果在将来继续提交更多的bug—如果第一次报告时能获得建设性的互动,以后更有可能这么做。建设性的互动不必是对于bug的修正,尽管那样是理想的;它可以仅仅是一种要求更多信息的恳请,或仅仅是那种行为bug的确认。人们希望被倾听。其次,他们希望自己的bug被修正。你可能无法一直及时的给予后者,但你(或者说整个团队)可以给他们前者。 一个推论就是开发者不能向出于好意提出含糊bug报告的人们表现出愤怒。这是我个人很气恼的事情。我在许多不同的开源邮件列表中看到许多开发者一直这样做,危害是显而易见的。一些倒霉的新手会发布无用的报告:
嗨,我没法运行Scanley。每当我启动它,就会报错。有人遇到过这个问题吗?
一些开发者—可能已经遇到此类报告几千次了,但丝毫不考虑这个新手从未遇到过—会这样回复:
这么点信息我们能怎么做?天呐。请给点细节,例如Scanley的版本、你的操作系统和错误信息。
开发者无法从用户的角度看待事物,也未能考虑到这种反应对于观看这种交互的其他人的效果。很自然,对于没有编程经验的用户,之前没有报告bug的经验,当然不知道如何编写bug报告。对于这种人该怎样正确处理呢?教育他们!要使用会促使他们回来获取更多信息的方式:
很遗憾你遇到了困难。我们需要更多信息才能找出发生的问题。请告诉我们Scanley的版本,您的操作系统和错误的精确文本。最好能提供一份你所运行命令的脚本,以及对应的输出。更多信息请看http://www.scanley.org/how_to_report_a_bug.html。
这种从用户那里榨取信息的响应方法远谈不上有效率,因为它是从用户的角度编写的。首先,它展示了同情:你遇到了问题;我们也感到痛。(即使在bug报告回应中也不是必须的;这取决于问题的严重程度以及感觉到的用户的伤心程度。)其次,没有对她不知如何报告bug表示轻视,而是告诉她如何,以及怎样的详细程度才会实际有效—例如,许多用户并不理解“请给些细节”的意思是“展示错误的精确文本”,不要遗漏或删节。当你第一次与这样一个用户工作时,你需要说明这些。最后,应该提供到更加详细和完整的报告bug指导的链接。如果你成功的让用户感觉在为她考虑,她通常会花时间阅读该文档并按照你所说的去做。当然,这通常意味着你需要预先就准备好文档。必须说清楚哪种类型的信息是开发团队在每个bug报告中希望看到的。理想情况下,可能需要通过回应多个这样的用户,逐渐的查漏补缺,使之更好地为项目服务。 Subversion项目的bug报告指导可以说是这类形式的标准案例(见)。请注意他们是如何以请求提供一个bug的补丁或修正结束的。这不是因为这种请求将会导致更高的补丁。报告率—大多数能够修正bug的用户都知道如果能提供补丁会受到欢迎,无需告知他们。请求的真实目的是为了向所有读者,特别是刚来到项目,或者刚来到自由软件的人强调,这个项目是通过志愿者的贡献运营的。这是许多新用户通常不熟悉的一个关键点。一旦他们意识到这一点,他们就更有可能在发生时帮助完成修正,即使不能提供代码,也会提供更完整的重现步骤,甚至是为其他人发布的内容测试修正。目标是让每个用户认识到他们和为项目工作的人没有天生的区别—问题只是他们能投入多少时间和力量,而不在于是谁。 对于愤怒回应的告诫不能适用于粗暴的用户。偶尔会有一些人会发送毫无信息量的bug报告或投诉,表现对项目某些失误的蔑视。通常此类人会在轻蔑与谄媚之间转换,例如Subversion邮件列表的这个人:
为什么几乎6天了还没有Windows平台的二进制程序?!?每次都是同样的故事,确实让人灰心。为什么这类工作就不能自动化,可以立刻出现。??当你发布“RC”构建时,我想你们的意思的是让用户测试构建,但是你们没为此事做任何事。如果你们没提供测试方法,又何必搞一个浸润期??
对于这种激动文章的最初回应是令人吃惊的克制:人们指出该项目有自己的发布政策,不会提供官方的二进制文件,并告诉他如果要改变恼人的程度,他应该志愿自己编译代码,如果真的对他很重要的话。相信与否,这段话属于他的下一次发布:
首先,我要说我认为Subversion很彪悍,很感谢每个参与者的努力。 [...]
...然后他再次继续为项目没有提供二进制,现在仍然没有志愿者做这件事而斥责项目。之后,大约50人跳了出来,我必须说我确实注意到这一点了。在提出的,针对粗鲁行为的“零容忍”政策,已经潜移默化的应用到每个人的交互中。但是,当人们认清他一开始就要当一个喷子时,没人能给他好脸色。 很幸运,这些情形非常罕见,很少需要被项目特别关注,并投入力量去保持用户建设性的和有礼貌的交互。
像分担技术任务一样分担管理任务 运行项目时要像分担技术负担那样分担管理负担。随着项目的成长,就会有更多关于管理人员和信息流程的工作。没有道理不分担这些负担,这并不一定需要一种自顶向下的阶级组织—实践中更多是同级的网络拓扑结构,而不是军队式的命令结构。 有时管理角色是正式的,有时则是自然发生的。在Subversion项目中,我们有一个补丁管理员,一个翻译管理员,文档管理员和问题管理员(尽管是非正式的)以及一个发布管理员。有时这些角色是经过认真考虑才开始的,而有些则完全是自发的;随着项目的成长,我相信会增加更多的角色。下面我们会详细审视这些角色,以及一些其他的角色(除了在本章前面中介绍的发布管理员)。 就像你看到的角色描述,请注意没有人独占控制其所在领域。问题管理员并没有防止其他人在问题数据库中做出修改,FAQ管理员也不必是编辑FAQ的唯一人选。他们的角色都是非垄断的责任。每个领域管理员所作工作的重要组成部分是提醒在该领域工作的人,训练他们按照管理员的方式工作,这样多种力量就可以互相加强,而不是发生冲突。领域管理员必须记录他们工作的过程,这样当他们离开时,别人就可以立刻接班。 有时会发生一种冲突:两个或更多的人希望同一个角色。现在没有人处理这件事。你可以建议每个志愿者写一个计划(一个“申请”),让所有的提交者选出最佳。不过这样有些笨拙,而且可能有些尴尬。我发现最好的方法只是告诉多个候选者自己处理。他们通常能够,也会更满意自己得出的结果,而不是别人施加的结果。 补丁管理员 在一个接收许多补丁的自由软件项目,跟踪到达的补丁以及所做的决定会成为一场噩梦,特别当通过非集中方式完成时。大多数补丁是以邮件的形式出现在项目开发列表(尽管可能有些最早出现在问题跟踪系统,或外部站点)的,在补丁到达时有许多不同的处理补丁的例程可以选择。 有时,某人评审了补丁,发现了问题,然后踢回给原作者整理。这通常会导致一个交互过程—都在邮件列表中可见—原始的作者一直发布修正的补丁版本,直到评审者无法找到更多的问题。有时很难说清楚这个过程已经结束:如果评审者提交了补丁,则可以说整个周期已经结束。但是如果她没有,或许仅仅因为她没有时间,或者没有提交权限,而且无法拉其他开发者做这件事。 另一个对补丁的常见回应是轻快的讨论,不必是针对补丁本身,而是关于补丁之后的概念。例如,补丁可能修正了一个bug,但项目希望用另一种方式修正这个bug,作为解决一个更普通类型问题的一部分。通常一开始这都是未知的,只是补丁激发了探索。 偶然情况下,发布的补丁可能会遇到完全的沉默。通常是因为没有开发者有时间在那个时刻去评审这个补丁,都希望其他人能去做这件事。因为每个人等待其他人捡起这个球的时间并不一定,而其他优先的事情不断出现,很容易会造成补丁被漏掉的情况,但这是任何人都不会希望发生的事情。项目可能以这种方式错误可用的的补丁,也有其他有害的副作用:会打击作者,他为补丁做了许多工作,让他觉得整个项目难以靠近,特别是对于其他考虑编写补丁的人。 补丁管理员的工作就是确保补丁不会漏掉。这是通过跟踪每个补丁的稳定状态实现的。补丁管理员观察邮件列表中每个由提出补丁引发的线索。如果最终以补丁的提交完成,他不需要做任何事。如果进入了评审/修正迭代,以补丁的最终版本结束,但是没有提交,他发起一个指向最终版本以及相关邮件列表的问题,这样之后跟进的所有开发者都有了一个永久的记录。如果补丁定位了一个现有的问题,他会将相关信息注释到该问题,而不会开一个新事物。 如果某个补丁没有回应,补丁管理员应该等待几天,然后询问是否有人会去评审它。通常会有响应:某个开发者会解释她认为该补丁不必应用,然后给出原因,或者她会去评审它,。如果还是没有回应,补丁管理员可以发起,也可以不发起一个补丁的问题,要根据他自己的判断,但至少最初的提交者得到了一些回应。 拥有一个补丁管理员为Subversion开发团队节省了大量时间和心力。如果没有指定的人负责,每个开发者需要一直担心“如果我没有时间现在回应补丁,我能指望别人做吗?我是否要一直盯着? 但如果有别人盯着,同样的原因,这样是否是没必要的重复。” 每个开发者在第一次看到这个补丁的时候都要做这样的决定。如果她希望跟进评审,她就可以这样做—补丁管理员会根据情况调整他的行为方式。如果她希望完全忽略这个补丁,也没问题;补丁管理员会确保它没有被遗忘。 因为这个系统只有在补丁管理员不发生失误的情况下才能运作正常,所以这个角色必须正式任命。在Subversion,我们在开发和用户邮件列表中广而告之,得到了许多志愿者,并选了第一个回复的。当那个人请辞后(本章后面的),我们重复了这个步骤。我们一直没有试图让多个人分担这个角色,因为他们之间会需要交流的负担;但是如果补丁提交的规模更大,则一个多头的补丁管理员就会有意义。 翻译管理员 在软件项目中,“翻译”可能指的是两件完全不同的事。它可能指的是将软件文档翻译为其他语言,或者指的是翻译软件本身—也就是让程序使用用户选中的语言显示错误和帮助信息。两者都是复杂的任务,不过一旦建立了正确的基础架构,则可以很大程度上与其他开发分离。因为这些任务非常类似,所以设置一个单独的翻译管理员处理两部分任务就非常有意义(取决于你的项目),亦或者更好的方式是设置两个不同的管理员。 在Subversion项目,我们有一个处理两部分的翻译管理员。他自己并不编写翻译,当然—他可以帮助一两个,但是在写这些话时,如果他希望与他们所有人一起工作,他需要讲10种语言(12种方言)。因而,他管理志愿翻译者:他帮助他们互相协调,以及他们团队与项目其余部分的协调。 设置翻译管理员的一个原因是翻译者是与开发者不同的人。他们有时只有有限的甚至没有任何在版本控制版本库中工作的经验,也没有与分布式志愿团队一起工作的经验。但在另一方面,他们通常是最好的一类志愿者:拥有特定领域知识,可以看到需求,选择参与进来。他们也通常愿意学习,对工作充满热情。所需要只是有人告诉他们如何做。翻译管理员确保翻译不会没必要的干扰日常的开发。每当开发者必须被告知需要为支持翻译工作提供技术变更时,他也要作为翻译者作为一个统一整体的代表。 因此,这个位置最重要的技能是外交能力,而不是技术能力。例如,在Subversion我们有一个政策,每种语言的翻译都必须至少有两个人正在参与,否则,就没有人可以检查文本。譬如说,有新的志愿者请求提供Subversion马达加斯加语翻译时,翻译管理员必须提示他去与六个月前某个表达过马达加斯加语翻译意向的人建立联系,或者有礼貌的询问志愿者去寻找另一个马达加斯加翻译者与其搭档工作。当有了足够的人手,管理员就可以为他们设置正确的提交访问权限,告知他们项目的惯例(例如如何编写日志文件),然后紧盯他们是否遵循了这些惯例。 翻译管理员和开发者之间,以及翻译管理和翻译团队之间的对话通常使用项目原先的语言—也就是所以翻译的源语言。对于大多数自由软件项目,就是英语,但是是什么语言并不重要,只要项目认可即可。(对于希望吸引广泛国际开发社区的项目,英语可能是最好的语言。) 在特定翻译小组中的对话通常使用它们共享的语言,然而翻译管理员的另一个任务就是为了每个团队设定一个专门的邮件列表。通过这种方式,翻译者可以自由的讨论他们的工作,而不会打扰项目邮件列表中的人,他们可能根本不理解他们的翻译语言。 国际化还是本地化 国际化(I18N)和本地化(L10N)都指的是采用非原软件编写的语言和环境使用程序的过程。这两个术语通常是可以互相替换的,但是实际上他们并不是同一回事。就像所说的:
它们之间的区别是微小的,但是非常重要:国际化指的是为潜在的用于所有地方的产品改造,而本地化是为用于特定地域的特别特性附加。
例如,将您的软件修改为实现对Unicode()文本编码无损处理是一种国际化行动,因为它并不是关于特定的语言,而是关于接受来自任意数量语言的文本。另一方面,当检测到软件是运行于斯洛文尼亚语环境时,便以斯洛文尼亚语打印错误信息,则是本地化的行动。 因此,翻译管理员的任务从原理上是关于本地化的,而不是国际化。
文档管理员 保持软件文档的实效性是一项无法结束的任务。每个进入代码的新特性或改进都可能会导致文档的变更。另外,一旦项目文档达到了一定级别的完整性,就会发现许多人发来的补丁是针对文档的,而不是代码。这是因为许多人是在文章中修正了bug,而不是在代码中:所有的用户都是读者,但仅有少数是程序员。 文档补丁通常比代码补丁更易于检查和应用。仅需要少许或无需测试,而且可以快速的通过检查评价变更的质量。因为数量很多,但是检查的负担相对较低,文档补丁中有效工作的管理负担比率远比代码补丁高。此外,大多数补丁需要一些调整,才能保持文档中作者语气的一致性。在大多数情况下,补丁通常会覆盖或影响其他补丁,在提交之前需要根据之间的关系进行调整。 出于处理文档补丁的紧迫性,以及需要持续监控代码基以便保持文档的实效性,有必要让某个人或一个小组专门从事这项任务。他们需要精确的保存文档在何处滞后于软件的记录,而且他们可以用一种整体方式的实践步骤来处理大量的补丁。 当然,这样不会阻碍项目中的其他人在工作中应用文档补丁,特别是时间允许时一些小的补丁。同一个补丁管理员(见本章前面提到的)可以同时跟踪代码和文档补丁,当开发和文档团队希望时完成它们。(如果补丁的总数已经超出了单个人可以跟踪的容量,最好的一个步骤可能就是将补丁管理员分为代码和文档。)文档团队的关键是使人们把保持文档组织性、实效性和一致性当作自己的责任。在实践中,这意味着对于文档的熟悉,关注其他人提交给文档的变更,关注到来的文档补丁,并使用所有这些信息源完成保持文档健康的所有必要工作。 问题管理员 项目bug跟踪系统中问题的数量是随着使用产品的人数同比例增加的。因而,即使你在一个快速成长的健壮程序中修正bug并装运,您还是会看到大量开放的问题漫无边际的产生。重复问题,以及不完整或描述糟糕的问题也会频繁发生。 问题管理员通过关注进入数据库的信息,定期的清除特定问题有助于缓和这种问题。他们的大多数常见行为可以修正进入的问题,一方面因为报告者未能正确的处理部分字段,另一方面也因为问题与数据库中的一个问题已经重复。很明显,问题管理员对项目bug数据库越熟悉,他就越能有效率的检测到重复问题—这也是设置一小部分人专门关注bug数据库,而不是让每个人都特别参与其中的原因。当团队试图按照非集中式的方式完成这项任务时,就不会有任何一个人具备对于数据库内容的深入专业知识。 问题管理员可以帮助我们映射问题和个别开发者。当有大量bug报告进入时,不是每个开发者会以平等的态度读取问题通知邮件列表。然而,如果某人知道开发团队紧盯着所有进入的问题,她可以将注意力放到特定合适的bug上。当然,这需要对项目所有开发的事情,接受者期望和性情都很敏感。因而,问题管理员最好也是开发者的一分子。 取决于你的项目如何使用问题跟踪系统,问题管理员也可以调整该数据库以反映项目的优先级。例如,在Subversion我们将问题排入未来的特定发布,这样每当有人询问“某个bug X何时可以修复时?”我们可以说“之后的两个发布,”即使我们不能说出确切的日期。这个发布在问题跟踪系统中以目标里程碑的形式展示,也就是IssueZilla中的一个字段。IssueZilla就是我们使用的问题跟踪系统;它是BugZilla的后继。作为一个规则,每个Subversion发布都有一个新的特性和一组特定的bug修正。我们为该发布的所有问题赋予一个合适的目标里程碑(包括新特性—它也会得到一个问题),这样人们就可以通过发布计划查看bug数据库。这些目标很少情况下会保持静止。随着新bug的到来,等级会发生切换,而且有些bug必须移到另一个里程碑,以保证每个发布的可管理性。再次,最好由对项目数据库的内容以及问题之间的关系有着整体意识的人完成。 问题管理员的另一项值得关注的任务是管理废弃的问题。有时,某个bug会因为软件一个不相关变更而意外的修正,或者有时项目对于特定行为是否为bug的意见发生改变。寻找废弃的问题并不简单:唯一的系统方法是清理数据库中的所有问题。随着问题数量的增长,完全的清理会变得越来越不可行。在达到某个点时,保持数据库健康的唯一方法就是分而治之:根据进入数据库的情况将问题分类,并直接分配给合适的开发者或团队。然后接受者负责问题余下的工作,根据需要决定是解决还是废弃。如果数据库足够大,问题管理员的工作就更倾向于协调,将会花费较少的时间用于自己查找问题,而是花更多的时间使之到达正确的人手中。 FAQ管理员 FAQ维护是一项出人意料的困难工作。项目中其他文档的内容都是由作者预先计划得到的,而FAQ则完全是被动的文档(见)。无论它变得如何巨大,你永远不知道何时会再一次添加。而且因为它总是零零散散的添加,它很容易变得不够一致并缺乏组织,甚至会包含重复的或半重复的条目。即使它没有任何此类的明显问题,项目之间也通常会有不引人注目的互相依赖—必须有链接,但是没有—因为与关联的项目添加的时间相差一年。 FAQ管理员的角色是双重的。首先,通过至少对所有问题的标题保持熟悉,她维护了FAQ的整体质量,这样每当有人添加的新条目与原来的条目重复或者相关,可以作出合适的调整。其次,她关注着项目的邮件列表和其他论坛中重复发生的问题或疑问,并根据这些输入编写新的FAQ条目。后一项工作可能非常复杂:必须能紧跟线索,识别出其中的核心问题,发表一个提议FAQ条目,组合来自其他人的评论(因为FAQ管理员不可能是FAQ包含的所有主题的专家),并感知何时结束这个过程并将其添加到FAQ。 FAQ管理员通常也会成为FAQ格式的默认专家。有许多保持FAQ结构的小细节(见);当某人编辑了FAQ,他们可能会忘记这些细节。但只要FAQ管理员能够在之后查漏补缺,这样便没有任何问题。 许多自由软件可以用于辅助维护FAQ的过程。只要能够保证FAQ的质量,就可以选一个来使用,但是要避免过度自动化。一些项目试图完全自动化FAQ维护的过程,使用类似wiki的模式允许每个人贡献和编辑FAQ条目(见)。我曾经遇到过在Faq-O-Matic上发生的这种情况(),尽管我看到原因仅仅是对Faq-O-Matic超出本来目的的滥用。在任何情况下,虽然完全的分布式FAQ维护可以减少项目的负担,但也会导致较差的FAQ。没有人具备整个FAQ的广泛视野,没有人注意到了哪个条目需要更新或变得完全不可用,每个人看到的都是孤立的条目。结果是FAQ经常会无法为用户提供他们所需要查找的东西,甚至会误导他们。您可以使用任何必须的工具维护项目FAQ,但是不要因为工具便利性的诱惑而损害FAQ的质量。 见Sean Michael Kerner在的文章The FAQs on FAQs,描述和评估了开源FAQ维护工具。
转化 一次又一次,某个位置上承担责任的志愿者(例如补丁管理员,翻译管理员等)无法执行该位置的责任。这可能是因为出现了超出他预期的工作,或者完全因为是许多外部因素:结婚、孩子出世、新的老板等等之类的。 当一个志愿者陷入这种境地,他通常不会立刻注意到。可能以很小的程度发生着变化,而且没有一个时刻可以自觉的认识到他已经无法完成这个角色的任务。相反,项目中的其他部分只是发现有一段时间未能听到他的消息了。然后他们会会立刻匆忙行动,而他则觉得长时间对项目的怠慢是有愧的,并立刻连夜赶工。然后就有更长的一段时间你无法听到他的消息,然后可能是或可能不是另一场慌乱。但是,很少有主动提出的正式辞职。志愿者用自己的业余时间工作,辞职意味着公开承认他的业余时间被永久的减少了。人们通常不愿意这样做。 因而,需要你和项目中的其他人发现发生的事情—或者说发现没有发生—,并能够询问哪个志愿者可以继续。这种询问必须是友好和100%无内疚的。你的目的只是找出真相,而不是让人难过。通常情况下,这个询问应当对项目的其他人可见,但是如果你知道一些必须私下进行的原因,也没有问题。公开进行的主要原因是如果志愿者回复说无法完成工作时,就可以为你的下一次公开发布提供一个上下文环境:请求一个新的志愿者完成该角色。 有时,一个志愿者无法完成其接受的工作,但是没有意识到或不希望承认这个事实。当然,任何人在一开始都会遇到困难,特别是当责任很复杂时。然而,如果某人不努力完成他接受的任务,即使所有人都给出全部的帮助和建议,最后唯一的解决方法只能是他放弃并让其他人来尝试。而且如果这个人没能看到这一点,需要有人告诉他。基本上来讲,我认为只有一种处理方法,但是需要一个多步骤的过程,每个步骤都很重要。 首先,确保你自己没有发疯。在私下与项目的其他人讨论,看看他们是不是和你一样认为问题很严重。即使你们已经肯定,这样也实现了让其他人知晓你们正考虑让这个人退出的目的。通常不会有人反对—他们会很高兴你肩负这个尴尬的任务,这样他们就不必动手了! 下一步,私下联系有问题的志愿者并友好和直接的告知他,你所发现的问题。为了效果,要尽可能提供多的实例。确保能够指出人们是如何不愿继续帮助的,而问题一直存在得不到改善。请确保花较长的时间编写该邮件,对于此类邮件,如果你无法支持你所说的,最好就什么都不要说。要说明你会找一个新的志愿者充当这个角色,但也要指出有许多方法可以支持这个项目。在这个阶段,不要说你已经为此与其他人进行了谈话;没有人希望被告知有人在准备接替他。 之后,可以有许多其他不同的方法。最可能的反应是他们可能会认可你,或者在某种程度上会争论,并愿意退出。如果是这个情况,建议他自己作出声明,然后你可以跟从他的文章寻找一个替代者。 或者,他可能认可自己的问题,但是请求多一点的时间(或者再多一次机会,例如离散任务角色的发布管理员)。如何响应这个情况需要您的判断,但是无论您如何做,不要仅仅因为感到无法拒绝这种请求而表示同意。这样会延续痛苦,但不会有所减轻。这通常是拒绝这种请求的好原因,换句话说就是已经给了足够多的机会,而现在就是得到的结果。这是我告知某人无法肩负发布管理员角色的邮件:
>如果您希望别人替代我,我会有好的将这个角色交给下个人。我有个 >不情之请。我希望再尝试一次发布来证明我。 > 我完全能够体会您的想法,但是在这种情况下 ,我们无法“再试一次”。 这不是第一次或第二次发布,而是第6或第7次... 我知道你也对结果 不够满意(因为我们之前已经讨论过)。所以我们已经有效的完成了 再次尝试的程序。最终,总有一次是最后一次... 我认为[上一次发布]就是 了。
在最坏的情况下,志愿者可能完全不同意。然后你需要接受事情变得尴尬并预先准备。现在是与其他人讨论此事了(但在得到他们的允许前,还是不能说是谁,因为这些对话是机密的)的时候了,也是你认为项目不应该这样继续下去的时候了。坚持,但不要威胁。请注意,大多数角色的转换可能始于某个新人已经开始了它的工作,而不是老人结束了他的工作。例如,如果争论事关角色,譬如说问题管理员,在任何时刻你和其他有影响的人可以请求一个新的问题管理员。可以不必是之前做这些事的人停止了工作,只要他没有妨害(故意或其他原因)新志愿者的努力。 有一个充满诱惑力的想法:为何不去尝试不必告知人们辞职,而仅仅是为他寻找一些帮助?为什么不可以有两个问题管理员、补丁管理员或任何角色? 尽管理论上听起来很不错,但通常不是一个好方法。是什么让管理员角色可以工作—是什么使之发挥作用,实际上—应该是非集中化。能够以非集中式完成的工作通常已经这样做了。有两个人肩负管理员角色会带来两个人的交流负担,也可能会带来不可靠的互相依赖(“我以为你带了急救箱!” “我?我以为带了急救箱”)。当然,也有例外。有时两个人可以配合的极好,或者任务本身就可以轻松的分散给多个人。但当你见到某人挣扎于某个他不适合的角色时,通常并不会起太大作用。如果他一开始就能够重视这些问题,之前就会寻求此类帮助。在任何情况下,让一个人持续做一件不会让人关注的事情都是失礼的。 让某个人隐退的重要因素是隐私:给他空间作出决定,而不要让他感觉大家都在关注和等待。我曾经犯过这种错误—非常明显的错误,回想起来—也就是同时向所有的三方当事人发送邮件,征求Subversion发布管理员,接替另外两个志愿者。我已经与两个人私下有所交流,也知道他们希望肩负这个责任。所以我认为,有些天真有些迟钝,通过向他们同时发送邮件开始了转换过程,省去了时间和争辩。我设想现在的发布管理员已经完全意识到了问题,也会立刻理解我的用意。 我错了。当前的发布管理员被冒犯了,完完全全的冒犯了。被人要求交出工作是一回事,而在大庭广众之下被要求交出工作则是另外一回事。当我意识到我的行为有些冒犯,我做出了道歉。他最终有礼貌的退出,并继续参与这个项目。但是他的感情受到了伤害,无需再说,对新志愿者来说也不是一个吉利的开始。
提交者 作为所有开源项目中唯一正式的明确阶层,需要对提交者格外关注。提交者是系统中不可避免的对鉴别的让步,而其他角色则是尽可能的非鉴别。但是“鉴别”这里绝无轻视的含义。提交者发挥的功能是绝不可少的,我不相信一个项目会在没有这个角色的情况下取得成功。我们需要质量控制,是的,控制。总会有许多人觉得自己具备对某个程序修改的能力,但实际上只有少数人确实具备。项目不能依赖人们自己的判断,必须设置标准并为达到标准的人赋予提交权限请注意,在非集中式的版本控制系统中,提交权限的含义有些区别,在非集中式系统中,任何人可以建立与项目关联的版本库,并为自己设置到该库的访问权限。然而,提交权限的概念依然适用:“提交权限”是“改变软件下一次发布中输送代码的权利”的缩写。在集中式版本控制系统中,这意味着直接的提交权限;在非集中式系统中,这表示了将某人的变更默认拖入主发布。其实是相同的含义;其实现的机制并不重要。。 另一方面,要让可以直接提交变更的人与不能设置明显权利变化的人一起工作。这种变化必须是受管理的,这样才不会损害项目。 ,我们已经讨论考虑过新提交者的机制。这里我们会讨论潜在的新志愿者必须被判断的标准,以及在一个大的社区中如何展示这个过程。 选择提交者 在Subversion项目,我们主要根据希波克拉底原理选择提交者:首先,不要伤害。我们的主要标准不是技术技巧或对代码的认识,仅仅是提交者展示出好的判断。判断仅意味着知道不要做什么。一个人可以只发布小的补丁,修正代码中的小问题;但只要这个补丁能够干净的应用,不会带来新的bug,能够最大程度的符合项目的日志信息和代码习惯,而且有足够多的补丁可以展示明显的模式,则现有的提交者通常会提议为该人赋予提交权限。如果至少三个人赞成,且没有人反对,则提议通过。诚然,也许我们没有证据证明这个人有能力解决代码基所有部分的复杂问题,但这并不重要:他所做的已经证明他至少能对自己的能力有正确的判断。技术技巧可以习得(和讲授),但无法获得最重要的判断。然而,在赋予一个人提交权限之前,这是你需要确保某人所具备的能力。 当一个新的提交者提议引起了讨论,通常不会是关于技术能力,而是关于该人在邮件列表或IRC中的行为方式。有时,某人展示了技术能力和按照项目正式方针工作的能力,以及在公共论坛中一致的好战或不合作性。这需要认真的关注;如果即使经过了回复的提示,这个人也一直未能改变,我们不会将其添加为提交者,无论其技巧怎样高。在一个志愿者团队中,社会技巧,或者说在“沙盒中玩耍的”能力,与原始的技术能力同样重要。因为任何东西都会进入版本控制,添加一个不该添加的提交者不会在代码层面带来太多的问题(评审可以迅速定位这些问题),但那样会导致最终强制项目收回该人的提交权限—这绝不是一项让人愉快的行为,有时会让人失望。 许多项目坚持潜在的提交者展示了特定级别的技术专业技能和持久性,通过提交一定数量的非琐碎补丁—也就是项目不仅仅希望知道他不会伤害项目,而且希望知道他会使项目在代码基上获益。这样很好,但是要小心,不要将提交权变为一个排他俱乐部的身份。每个人的脑子中都应该有一个问题:“怎样做才会为代码带来最好的结果?”而不是“认可这个人是否会降低提交权关联的社会状态的价值?”如果您有100个提交者,10个进行常规的较大的变更,而其他90个则仅仅是每年修正几个拼写和小的bug,依然比只有10个提交者更好。 收回提交权限 关于收回提交权限首先要做到:尝试不要一开始就进入这种情况。取决于谁的权限将会被收回,以及收回的原因,相关的讨论将会显著不同。即使没有不同,这也将会是有效率工作的一项费时的分心的工作。 然而,如果您必须如此,一定要确保讨论必须处于将会为该人赋予权限进行投票的人之间,无论他们拥有怎样的投票风味。一定不要包含本人。这似乎否定了针对保密性的禁令,但在这种情况下这是必要的。首先,没有人能够以别的方式自由言论。其次,如果行动失败,你不会希望让此人知道这被考虑过,因为这会带来一些问题(“谁站在我这边? 谁反对我?”),会导致最坏类型的党派主义。在一些罕见的情形下,团队会希望某人知道收回提交权限的过程正在进行中,作为警告提示,但一定要确保这种公开是团队决策的结果。任何人不应当擅自行动,将别人认为是秘密的讨论信息和表决透漏出去。 一旦收回了某人的权限,结果必然要公开(见本章后面的),你需要尝试尽可能谨慎的公布于众。 部分提交权限 有些项目提供细粒度的提交权限。例如,有些贡献者的提交权限限于文档,而不能是代码。常见的部分提交权限包括文档、翻译、其他语言的绑定代码,打包的特定文件(例如RedHat RPM规范文件等等),以及其他即使发生错误也不会导致核心项目问题的地方。 因为提交权限不仅仅关于提交,而且事关选举资格(见),自然回带来另一个问题:部分提交者能够为何投票?没有一个正确的答案;这取决于你的项目有何种部分提交领域。在Subversion中,我们尽可能让事情简单:一个部分提交者只可以参加提交者领域的部分投票,其他地方则不行。更重要的,我们有一个可以覆盖建议投票的机制(其实质在于,表决时提交者可以写"+0"或"+1 (非绑定)",而不仅仅是"+1")。...................... 完全提交者可以为任何事情投票,就像他们可以任意提交一样,只有完全提交者可以为添加所有类型的提交者投票。在实践中,通常这种添加新部分提交者的能力通常会被代理:任意完全提交者可以“发起”一个新的部分提交者,而且某个领域的部分提交者通常会为同一领域选择新的提交者(这在保证翻译工作正常运行时特别有益)。 你的项目可能有些许不同的安排,这取决于你所作工作的特性,但相同的原理适用于所有的项目。每个提交者必须能为她提交权限相关的事物进行投票,不相关的则不能,而且程序上的问题默认由完全提交者表决,除非有原因(要由完全提交者决定)来扩大投票范围。 关于部分提交权限的强制性:最好不要让版本控制系统约束提交领域,即使技术上可行。原因请见 休眠提交者 一些项目会在提交者在一定时间(例如一年)内未能提交任何东西时,自动删除其提交权限。我认为这样没有太大帮助,甚至有不良的后果,有以下两个原因。 首先,这会诱使人们提交可接受但不必要的变更,仅仅为了保住将要过期的提交权限。其次,这样没有意义。如果赋予提交权限的主要标准是判断力,为何仅仅因为他离开了项目就认为其判断力的下降?即使他完全的消失了几年,没有看任何代码或跟踪开发讨论,但当他重新出现时,他会知道他已经多久未从联系,并以此行动。你原来相信他的判断,为何不永远相信他?如果高校的文凭不会过期,那么提交权限也不应该。 有时,一个提交者会要求将其删除,或在提交者列表中明确的标记为休眠状态(关于该列表的更多信息见后面的)。在这种情况下,项目当然必须答应个人的意愿。 避免神秘 尽管围绕添加特定新提交者的讨论必须保持机密,其规则和步骤本身不应该保密。实际上,最好公开,这样人们可以意识到提交者并不是什么神秘的秘密法庭,也不是凡人免进,而是任何人可以参与,仅需要发布一些好的补丁,并指导如何在社区中交流。在Subversion项目中,我们将信息放在开发指南文档中,因为那些希望为项目贡献代码的人们对如何赋予提交权限最有兴趣。 除了发布步骤,也要发布提交者列表。该文件的传统位置是项目代码树顶级目录中叫做MAINTAINERSCOMMITTERS的文件。它首先必须列出所有的提交者,紧跟是多个部分提交域以及其中的提交者。要列出每个人的名字,如果该人愿意,也包括邮件地址,地址可以为防止垃圾邮件进行编码(见)。 因为完全提交者和部分提交者访问权限有着明显的区别,也做出了明确的定义,所以这个列表也应该列出这种区别。除此以外,该列表不应当试图表明项目中不可避免会出现的非正式的区别,例如谁更具影响力。它是公共记录,不是致谢文件。请使用字母顺序或其出现顺序列出提交者。 荣誉 荣誉是自由软件世界的主要货币。无论人们怎样说他参与项目的动机,我不知道有哪个开发者会乐于匿名,或以其他人的名义的做这些事。有一些有形的原因:一个人在一个项目的名声大体上决定了他的影响力,参与一个开源项目也会间接的带来金钱,因为某些雇主希望寻找简历。也有一些无形的原因,或许更加强大:人们只希望被赏识,本能的寻找被别人识别的标志。荣誉的希望是项目一个最重要的动机。当小的贡献被认可,人们会返回作出更多。 协作开发软件的一项重要特性是(见)保持何人何时做了何事的精确记录。如果存在,请尽可能使用现有的机制确保荣誉精确的分配,要根据贡献的本性特别处理。不要仅仅写下"感谢J. Random <jrandom@example.com>",作为替代可以在日志信息中写为"感谢J. Random jrandom@example.com>的bug报告以及对于重现bug的描述"。 在Subversion中,对于bug报告者的荣誉,我们有一个非正式的但是一致的政策,如果有发起的问题,则在问题中记录,如果没有发起问题,则在修正该bug的提交日志信息中记录。对于提交编号14525之前的Subversion日志进行了一个快速调查,发现10%的提交包含了某人名字和邮件地址的荣誉信息,通常是报告或分析该提交的bug修正的人。请注意,这些人与实际作出提交的开发者不同,这些开发者的名字已经自动记录到了版本控制系统。在目前Subversion的80位完全和部分提交者中,有55位在他们成为提交者之前,曾经在提交日志(通常多次)中被记录过荣誉。当然这并不是说,被记录荣誉是继续参与的一个因素,但至少给了人们知道自己的贡献如何被认可的氛围。 很重要的一点是区分常规的感谢和特别感谢。当讨论特定代码片段或其它某人的贡献时,最好能够感谢他们的工作。例如,假设“Daniel最近对于增量代码的变更意味着我们现在可以实现特性X”,需要同时帮助人们识别你所谈论的变更并感谢Daniel的工作。另一方面,仅仅单独感谢Daniel对于增量代码的变更无法达到即刻的实践目的。它不会增加任何信息,因为版本控制系统和其他机制已经记录了他所做的变更。感谢所有人的所有工作则会分散最终的信息,因为感谢的内容是他与所有默认的、背景的评论级别相比的突出程度。当然这并不意味着你不需要感谢大家。只需要确保不会陷入荣誉通货膨胀。遵循下面的指导会有所帮助: 这个论坛越是短暂,越应该对在这里自由表达感谢感到自由。例如, 在IRC对话中感谢某人传来的bug修正很好,在邮件中旁敲侧隐也很不错。但是最好不要单独发一个感谢某人的邮件,除非是真的不同寻常的壮举。很有可能,不要因为表达感激弄乱项目的网页。一旦你开始这样做,便会永远无法清理,也无法停止。而且绝不要将感谢置于代码的注释之中;这将会分散注释主要目的的注意力,注释本来的作用是帮助读者理解代码。 一个人参与项目越少,就更应该对她的所作所为提出感谢。这似乎与直觉并不一致,但是表示感谢的态度适用与某人作出的贡献,超出了你对他的预期。因此,一直感谢常规贡献者的日常工作表现了对他们所做工作的较低的预期。如果说有效果,可能是反效果! 这个规则有一些偶尔的例外。如果感谢某人完成了预期角色,而这个角色反复包含了许多临时的、紧张的努力,则这是可以接受的。一个标准的例子是发布管理员,他在每次发布时都会投入紧张的工作,但其他时间则陷入休眠(作为发布管理员休眠,在有些情况下—它还可以是活跃的开发者,但那是另外一回事了)。 就像批评和荣誉,感谢必须是特定的。不要因为伟大而感谢,即使确实如此。要为他们所做的超出寻常的事情表示感谢,如果能恰当的说出他们的伟大之处也能额外加分。 通常情况下,在确保某个人的贡献已经被识别出来,和确保整个项目是一个团队,而不是一些荣耀的个体时,总会有些紧张。只要意识到这种紧张,并且强调表现团队,以及未能掌握的事物。 分叉 ,我们说了潜在的分叉能力对于项目管理的重要影响。但是当分叉确实发生时,我们应该怎么做?你应该如何处理,会发生怎样的情况?与之对应,何时你应当开始一个分叉。 答案取决于你选择的分叉类型。有一些分叉源于对于项目方向的友善但不可调和的异议;也有一些由于技术分歧和个人冲突。当然,很难说清楚二者之间的区别,因为技术争论也会包含个人元素。所有分叉的共同之处是有一队开发者(有时仅仅是一个开发者)认为与某些人或所有其他人一起工作的成本已经大于收益。 一旦项目分叉,对于分叉与“原”项目谁是谁非,没有明确的答案。人们会通俗的说分叉F来自于项目P,好像P继续沿着自然路径保持不变,而F则进入新的领域,但这实际上是一个观察者的声明。但这纯属个人感觉:当足够高百分比的观察者认可,这个断言便成为真。并不是说一开始就有一个客观事实,而只是一开始的一个不太完美的感觉。此外,感觉客观事实,因为最终一个项目—或一个分叉—仅仅是存在于人们思想中的一个实体。 如果开始分叉的人们感觉自己是在建立主项目的一个分支,则感知问题可以立刻轻易的解决。每个人,开发者和用户会将分叉视为新的项目,有新的名称(或许基于旧有的名称,但容易与之区分),一个单独的网页以及单独的哲学或目标。当双方都认为自己是原项目遗产的守卫者,理所当然继续使用原来的名称时,事情会变的复杂。如果某个组织拥有这个名称的商标权,或对于域名或网页有法律控制,通常可以平滑的解决这个问题:这个组织可以决定谁是这个项目,谁是分叉,因为它拥有公共关系战争中的所有卡片。很自然,一般不会如此过分:因为每个人都知道权利动力学,他们会避免一场结局已定的战斗,会直接跳到结局。 幸运的是,大多数情况下可以轻松的区分哪个是项目,哪个是分叉,因为分叉从本质上是一个自信的投票。如果过半的开发者倾向于采纳分叉的过程,通常意味着没有必要分叉—这个项目可以自己走这条路,除非它有一个顽固的独裁者,按照独裁方式运行。另一方面,如果支持者少于一半,则分叉则明显是少数派的反叛,根据礼貌和常识,它应当认为自己是分叉,而不是主线。 处理分叉 如果某人在项目中威胁进行分叉,请保持冷静并牢记你的长期目标。分叉的存在不是对项目的伤害,而是开发者和用户的损失。你真正的目标,不是为了镇压分叉,而是最小化其损害。也许你会生气,你或许感到分叉是不公正和不请自来的,但如果这样公开表示则是对未决定用户的疏远。相反,不要强制人们做出唯一的选择,要与分叉实行可行的合作。首先,不要因为某人决定在分叉上工作,而删除其在你的项目中的提交权限。在分叉上工作并不意味着他立刻失去了在原项目工作的资格;之前的提交者之后还是提交者。此外,你应当展示与分叉保持兼容的愿望,并表达你希望开发者能够在二者之间搬运合适的变更。如果你对项目服务器有管理权限,一开始就公开提供分叉的基础架构帮助。例如,如果他们无法通过其他方法获得,可以为他们提供一个完整的,版本控制库的深度历史副本,这样他们就不必以无历史数据作为开始(必要性取决于版本控制系统)。询问他们是否有其他的需要,并尽你所能提供。这种支持表明了你不会阻挠他们,而且希望该分叉以自己价值成功或者失败,仅此而已。 这样做—以及公开这样做的—原因实际上并不会帮助分叉,但是通过尽可能的展示非报复心态,会使开发者相信你这边是安全带。战争中有时强制人们选择一边非常有意义(战略意义,而不是人的感觉),但是自由软件几乎从不这样做。实际上,分叉后一些开发者会公开的在两个项目同时工作,并尽可能保持二者兼容。这些开发者保持了分叉之后的交流。他们允许您的项目从分叉中有趣的新特征中获益(是的,分支也有你想要的),另外也会增长在未来合并的可能。 有时,某个分支变得异常成功,即使他最初的煽动者也认为他们开始于一次分叉,但成为人人都喜欢的版本,最终由于其流行性取代了最初的版本。一个著名的实例是GCC/EGCS分叉,GNU Compiler CollectionGCC,以前称为GNU C Compiler)是最著名的开源本代码编译器,也是世界上最便于移植的编译器。源于对GCC官方维护者和Cygnus软件的分歧。现在是RedHat()的一部分。GCC的一个最活跃的开发团队,Cygnus创建了一个GCC的分叉,称为EGCS。该分叉谨慎保持非敌对位置:从任何角度看,EGCS开发者从没有试图把他们版本的GCC描绘成新的官方版本。相反,他们集中精力使EGCS尽可能的好,比官方的GCC维护者以更快的频率整合补丁。EGCS受到了欢迎,最终一些主流的操作系统发布商决定将EGCS而不是GCC作为打包产品的默认编译器。此刻,对于GCC的维护者很清楚,坚持“GCC”的名称,而让所有人切换到EGCS分叉上需要每个人承受毫无必要的名称修改负担,对防止切换毫无意义。所以GCC采用了EGCS的代码基,再一次只有一个GCC,但因为分叉获得了极大的改进。 这个例子向我们展示了为什么不能单纯的将分叉视为一件坏事。分叉时可能充满痛苦和不受欢迎,但你不能必然知道它是否会成功。因而,你和项目的余下部分要一直留意它,不仅仅要准备好吸收可能的特性和代码,在极端情况下,如果分叉获得了项目的精神占有率,甚至需要加入分叉。当然,通过观察谁加入了分叉你也能预测到其成功的可能性。如果分叉由项目最大的抱怨者开启,并有少数不满的看起来起不到建设作用的开发者加入,他们将无法通过分叉解决问题,你也无须担心分叉会将原项目的动力带走。但是如果你看到有影响和令人尊敬的开发者支持这个分叉,你必须问自己这是为什么。或许整个项目被限制了,最好的方案是在主线项目采纳一些分叉打算的行动—从本质上,通过变成它而避免分叉。 初始一个分叉 这里的所有建议假设你将分叉作为最后的依靠。初始分叉前耗尽了所有的可能性。分叉总是意味着丢失开发者,只留下一个不确定的在以后获得新产品的承诺。它也意味着开始了对用户注意力的竞赛:每个下载这个软件的人都会问自己:“哦,这个还是那个? ” 无论你是哪个,情况也是肮脏的,因为出现了原本不存在的问题。一些维护分叉的人们会维护软件的整体生态系统的健康,通过标准的自然选择论点:适者生存,意味着最终每个人得到更好的软件。从生态学的角度这或许是正确的,但对于单个项目来说则并不正确。大多数分叉并不成功,大多数项目不喜欢被分叉。 一个推论就是不要使用分叉的威胁作为极端的辩论技巧—“按照我的方式,否则我要将项目分叉! ”—因为每个人都会意识到如果是无法吸引开发者离开原项目的分叉,不太可能长久存活。所有的观察者—不仅是开发者,还有用户和操作系统打包者—会对选择哪一方做出自己的判断。你不必表现出极端不情愿分叉,这样如果你最终这样做了,你可以光荣的宣布这是最后一条路。 在评估你的分叉成功可能性时,不要忽视所有的因素。例如,如果项目的许多开发者都有同一个雇主,那么即使他们不满且私下里倾向于分叉,也不太会大声说出他们的雇主是赞成还是反对。许多自由软件程序员以为如果代码有自由许可证,那么没有哪个公司可以控制开发。许可证确实如此,是一种终极意识,自由的保障—如果其他人强烈的希望分叉项目,并有足够的资源,它可以这样做。但是在实践中,一些项目开发团队大多由一个实体资助,没有证据说明这些实体的支持无关紧要。如果他们反对分叉,他们的开发者不会离开,即使私下里希望如此。 如果你还是确认必须分叉,最好首先私下联络好支持,然后使用不含敌意的语调宣布分叉。即使你对当前的维护者感到愤怒,或者失望,不要在这些信息中写出来。只需要不露声色的陈述导致你决定分叉的动机,以及你对所分叉原项目并无敌意。假定你考虑一次分叉(相对于对原项目的紧急保存),强调你分叉的是代码而不是名称,并选择一个与原项目不会冲突的名称。你可以使用一个包含或引用原名称的名称,只要不会造成识别上的混淆。当然,在分叉的主页上也可以突出解释其来自的原始程序,甚至对于替代它的期望。但是不要迫使用户解开识别争议,给他们带来额外的麻烦。 最终,通过为原项目的所有提交者,包括那些公开反对分叉的提交者赋予提交权限,就可以自动让事情开始运转。即使他们不会访问,但你的信息是明确的:这里存在争议,但是没有敌人,你欢迎来自所有竞争源的代码贡献。