制造开源软件

如何成功运营自由软件项目

Karl Fogel


Dedication

这本书献给我的两位好朋友,我不可能忘掉他们:Karen Underhill和Jim Blandy。

Table of Contents

前言
为什么写这本书?
谁应该读本书?
资料来源
致谢
写给第一版(2005)
写给第二版(2017)
免责声明
1. 介绍
历史
私有软件和自由软件的兴起
有意识的反抗
意外的反抗
“自由”还是“开源”
现状
2. 起步
从你所拥有的开始
选择一个好名字
有一份清楚的使命陈述
声明项目是自由软件
特性和需求列表
开发状态
下载
版本控制和Bug跟踪访问
沟通渠道
开发者指南
文档
文档的可用性
开发者文档
输出和屏幕截图实例
包装主机
选择许可证并应用
“可以做任何事情的”许可证
GPL
如何为你的软件应用许可证
设置风格
避免私下讨论
防无礼于未然
实践明显的代码评审
将一个封闭项目开放时,对于改变的影响要格外敏感
通告
3. 技术基础设施
一个项目需要什么
邮件列表
垃圾邮件防护
过滤邮件
归档中的地址隐藏
身份和头管理
伟大的Reply-to辩论
两个幻想
归档
软件
版本控制
版本控制词汇表
选择一个版本控制系统
使用版本控制系统
版本化所有的东西
可浏览性
提交邮件
使用分支来避免瓶颈
信息单一性
授权
Bug跟踪
与邮件列表交互
Bug跟踪的预过滤
IRC / 实时聊天系统
机器人(Bots)
归档IRC
RSS供稿
Wikis
网站
包装主机
选择一个包装站点
匿名和参与
4. 社会和政治的基础架构
慈善独裁者
谁可以成为一个慈善独裁者?
共识为基础的民主(Consensus-based Democracy)
版本控制意味着你可以放轻松
如果无法达成共识,那么表决!
何时表决
谁进行表决?
民意调查与表决
否决权
写下所有的内容
5. 金钱
参与的类型
长期雇佣
作为一些个体出现,而不是一个整体
公开你的动机
钱不能让你可爱
契约
评审和接受变更
案例研究:CVS密码认证协议
资助非编程活动
质量保证(也成为专业测试)
法律建议和保护
文档和可用性
提供主机/带宽
市场营销
记住你正在被注视着
不要痛击竞争开源产品
6. 交流
人如其文
结构和格式
内容
基调
识别无礼
面容
避免常见的陷阱
不要发表无目的的文章
多产VS非多产的线索
主题越软,辩论越长
避免圣战
“吵闹的少数派”效应
刺儿头
处理刺儿头
案例学习
处理成长
归档的显著使用
将所有的资源视为归档
编制法律的传统
Bug跟踪系统中无对话
公开性
声明安全漏洞
接收报告
默默的开发修正
CAN/CVE号码
预通知
公开分发修正
7. 打包、发布和日常开发
版本号
版本号组成部分
简单策略
奇偶数策略
发布分支
发布分支的技巧
稳定发布版本
发布所有者独裁
变更表决
管理协作发布稳定化
发布经理
打包
格式
命名和布局
大写还是不大写
预发布
编译和安装
二进制包
测试和发布
候选发布
宣告发布
维护多发布线
安全发布
发布和日常开发
计划发布
8. 管理志愿者
从志愿者中获取最多
委派
明确区分调查和指派
指派后要继续跟踪
通知感兴趣的人
赞扬和批评
防止割据
自动化率
自动测试
将每个用户当作潜在的志愿者
像分担技术任务一样分担管理任务
补丁管理员
翻译管理员
文档管理员
问题管理员
FAQ管理员
转化
提交者
选择提交者
收回提交权限
部分提交权限
休眠提交者
避免神秘
荣誉
分叉
处理分叉
初始一个分叉
9. 许可证,版权和专利
术语
许可证的方面
GPL和许可证兼容性
选择一个许可证
MIT / X Window System License
GNU General Public License
GPL是自由还是不自由?
那BSD许可证呢?
版权分配和所有权
无为而治
贡献者许可证协议
版权转移
双许可证模式
专利
深入资源
A. 自由版本控制系统
B. 自由Bug跟踪系统
C. 为什么我要关注车棚的颜色?
D. 报告bug的样例指导
E. 版权

前言

为什么写这本书?

在聚会上,当我告诉别人我写自由软件时,人们不再是一副茫然的表情。他们会说,“哦,开源软件—就像linux?”我使劲地点头:"对!我就是做那个的。"不再被凉在一边的感觉真好。要在过去,下面的一个问题通常会是这个:“你靠那个怎么挣钱?”为了回答他们,我必须概述开源软件的经济学:有一些组织对某个特定软件的存在感兴趣,但他们不需要卖拷贝,而是确保这些软件能够免费获得并且有人维护,能够作为工具而不是商品使用。

然而之后的问题不再总是同钱有关。开源软件[1]的商业案例不再是如此神秘,许多的非编程人士已经了解到—或至少不再惊奇—确实有一些人被雇佣全职做开源。于是,我越来越频繁地被问到的第二个问题是:“那么,开源软件是怎么运作的?

我手头没有现成的满意的答案,更困难之处在于当我试图给出一个时,我意识到它是一个多么复杂的题目。运行一个自由软件项目完全不同于商业运作(想像一下必须时常同大部分你从未谋面的志愿者们商讨产品的特性的情景! )。由于某些原因,也和传统的非盈利组织不同,也不同于一个政府。与上述事物有许多相似性,但我渐渐得出了一个结论,自由软件是独一无二的。有许多事情可以与之比较,但没有一个与之完全等同。实际上,即使对于自由软件项目可以“运行”的假设也是一种引申。一个自由软件项目能被开启,并且会受到对此感兴趣的团体的强烈影响,而且它的资产不属于任何一个个人或团体,会源源不断从某些地方冒出对此感兴趣的人,所以它不会被—任何人—单方面地终止。每个人都有无限的权利,每个人又都没有权利。它形成了这样一种有趣的动态平衡。

这就是我要写此书的原因。自由软件运动已经进化出了一种独特的文化,一种信奉个人能够让软件做任何事情、自由为中心信条的思想,这种自由的结果并不是让每个人对代码各行其事,而是是狂热的合作。实际上,在合作中竞争也是自由软件运动中最有价值的技巧之一。管理这样的项目就是处理一堆庞大的合作关系,在这里个人能力不仅是和他人一起工作,而且包括通过一条崭新的合作方式对软件做出实际的贡献。这本书试图描述实行这种方式所需要的技术。它不会包含全部,但却是重要的起步。

优秀的自由软件本身就是极有价值的目标,我希望那些在本书中寻找创造成功软件方法的读者能够得到满意的答案。除此之外,我想传达那种纯粹的快乐,来自同充满活力的开源软件开发团队的合作,来自通过开源软件所鼓励的直接方式与用户的交流。成为一个成功的自由软件项目的一分子是有趣的,这才是驱动整个系统运转的终极动力。

谁应该读本书?

这本书是为那些着手开始一个开源软件项目,或已经开始但想知道现在该做什么的软件开发人员和经理们准备的。对那些打算加入一个开源软件项目,但是又没有经验的人,此书也是有所裨益的。

读者不必是程序员,但应该知道软件工程的一些基本概念,比如源代码、编译器和补丁。

无论是作为用户还是开发者,都不必具备开源软件的经验。那些之前在自由软件项目中工作过的人也许会发现这本书中的某些部分太浅显了,可能会想跳过这些章节。由于读者群的背景各有不同,我特别对各章节作了清楚的标示,以便读者可以适时跳过那些他们已经熟悉的内容。

资料来源

此书中的很多原始材料都是来自Subversion项目(http://subversion.tigris.org/)的五年工作。Subversion是一个从零开始的开源版本控制系统,目的在于替代CVS成为开源社区版本控制系统事实上的选择。这个项目由我的雇主CollabNet公司(http://www.collab.net/)在2000年初发起,感谢上帝CollaNet从一开始就正确理解如何将它作为一个分布广泛的合作性项目来运作。从一开始我们就吸收了很多的志愿者,现在这个项目有50多名开发者,其中只有少数是CollabNet的雇员。

在很多方面Subversion都是开源软件项目的一个典型例子,最终我在上面花费的精力远超出我最初的预想。另一方面也是出于便利:无论何时我需要一个现象的样本,我的脑海里便会立即浮现出Subversion中的一个实例。但这也事关验证。虽然我不同程度地参与了其他几个开源项目,并且会和很多的朋友和相关的人交谈,但我很快就发现,当写成文字时,所有的断言都需要经过事实的检验。我不想仅仅根据我读到的它们公开邮件列表上列出的文档而对事件发表意见。如果有人想用以上的方式尝试Subversion,我知道,她大约只有50%的正确率,而另外50%是错误的。因此,当需要从一个我没有直接参与的项目找寻灵感或者实例时,我会找一个我信任并且了解内情的人,让他来说明项目的真实情况。

虽然过去5年我一直在做Subversion,但我从事自由软件行业已有12个年头了。因而,其它一些项目也对本书有所影响:

  • 自由软件基金会(Free Software Foundation)的GNU Emacs文本编辑器项目,我在其中维护了几个小的软件包。

  • Concurrent Versions System (CVS)版本控制系统是我在1994–1995期间与Jim Blandy全力投入的一个项目,此后,我只是断断续续地参与这个项目的工作。

  • Apache软件基金会(Apache Software Foundation)的开源软件项目集,尤其是Apache可移植运行库(Apache Portable Runtime (APR)和Apache HTTP服务器。

  • OpenOffice.org 办公软件项目,Sleepycat软件公司的Berkeley Database项目,以及MySQL数据库项目;我个人并未参与这些项目的开发,但曾经对其进行关注,并在一些案例中与其开发人员进行过交谈。

  • GNU Debugger(GDB)项目(同上)。

  • Debian项目(同上)。

当然,以上并不是一个完整的名单。正如多数的自由软件程序员一样,我不定期地追踪自由软件行业中许多不同的项目,以对行业的整体情况有全面的了解。在此,我不一一列举所有的项目,但在书中会适时提及。

致谢

写给第一版(2005)

写作本书所耗用的时间是我原来设想的四倍,而在写作期间,无论我身在何处,总感觉到脑袋上仿佛悬挂着一台大三角钢琴。没有以下众人的帮助,我便不可能完成本书的写作而仍然保持精神正常的状态。

本书的编辑,O'Reilly出版社的Andy Oram是一个作家梦寐以求的编辑。他不但谙熟自由软件行业(书中的许多题目是他建议的),而且具有一种非凡的才能,那就是知道对方想说什么,而且帮助对方找到最佳的表达方式。能与Andy合作是我的荣幸。在此,我也要感谢Chuck Toporek,是他将本书的写作提议及时传给了Andy。

Brian Fitzpatrick在我写作本书的时候审阅了全部的内容,这不但使本书更完善,而且在我只想从电脑屏幕前面逃走,躲到世界上任何一个其它角落时,是Brian鞭策我继续写作。Ben Collins-Sussman和Mike Pilato也经常询问写作的进程,而且总是乐于讨论那一周我正在写作的任何题目,有时候那样的讨论需要进行很长时间。在我写作稍有懈怠的时候,他们也会注意到,并善意地加以提醒。谢谢你们,伙计们。

在我撰写本书的同时,Biella Coleman正在完成她的博士论文。她了解每天坐下来写作意味着什么,她既是鼓舞我写作的榜样,又能倾听我写作的苦衷。更能以一双人类学家的慧眼观察自由软件运动,给我提供了一些想法和参考资料,用于本书的写作当中。另一位人类学家Alex Golub那时候也在完成他的博士论文,而且他本人涉足自由软件行业,他在本书刚开始写作时给我提供了大量的支持,对我有极大的帮助。

Micah Anderson似乎从未因自己写作大部头而有压迫感,这真是令人憎恨而又妒忌的鼓舞,与他的友谊和交谈给了我很大的帮助,而且(至少有一次)他为我提供了技术上的支持。多谢你,Micah!

Jon Trowbridge和Sander Striker既给予了我鼓励也提供了具体的帮助—他们在自由软件行业中丰富的经验为本书提供了我不可能在别处找到的素材。

我要感谢Greg Stein,不仅因为我们之间的友谊和他适时的鼓励,更因为他向Subversion项目表明定期地代码评审对建设一个编程社区是一项多么重要的工作。我也要感谢Brian Behlendorf,他巧妙地告诫我们进行公开讨论的重要性;我希望这一原则贯穿了本书的始终。

感谢Benjamin “Mako” Hill和Seth Schoen与我进行的有关自由软件及其政治方面的若干谈话;感谢Zack Urlocker和Louis Suarez-Potts在百忙之中抽空接受我的采访;感谢Slashcode名单上的Shane允许我引用他的帖子;感谢Haggen So提供的有关制作完成的主页之比较,那极其有帮助 。

感谢Alla Dekhtyar、Polina以及Sonya给予我永不倦怠及耐心的鼓励。我真高兴我不必在我们的晚间聚会上提早告辞(或更确切地说,恋恋不舍地告辞)而回家去写“那本书”。

感谢Jack Repenning给予我的友谊、交谈、以及他固执地拒绝接受不费力气的错误分析,而不遗余力找寻正确答案的决心。我希望他在自由软件开发以及自由软件行业中长期而丰富的经验在本书中得以体现。

在本书写作期间,CollabNet极其慷慨地允许我采用一个灵活的工作日程,而当我需要的时间远远超出原先预计的时候,他们没有抱怨。我并不完全了解管理层在做这样的决定时考虑的个中细节,但我猜想Sandhya Klute,而后是Mahesh Murthy,均参与了这项决定—我在此感谢他们两位。

整个Subversion开发团队在过去的五年是我灵感的源泉,本书中描述的绝大部分内容都是我与之共事所得。由于人数众多,我在此不能一一列举他们的姓名,但是我恳请各位读者, 假如你有一天偶遇一位Subversion的开发人员,请为他买一杯他最爱喝的酒—我本人肯定要那样做。

我曾多次与Rachel Scollon胡言乱语,叙说写书的进程,而她总是乐于倾听,并且能够设法使问题大而化小。那对我有很大的帮助—多谢。

(再次)感谢Noel Taylor,他一定十分不解,为何我在上次频频抱怨之后又决定写第二本书,然而,Noel给予我的友谊,以及他领导之下的Golosá合唱团使我的生活即使在最忙碌的时节依然有音乐和好友相伴。我还要感谢Matthew Dean和Dorothea Samtleben,我的好友以及因我而饱受折磨的音乐合作伙伴,在我多次无法与之排练的时候,他们总是给予我极大的理解。Megan Jennings总是给予最大的支持,并对一个她并不十分熟悉的题目表现出真诚的兴趣—这对一个缺乏信心的作家来说无异于一剂定心丸。多谢了,我的老友们!

本书有四位学识渊博而又兢兢业业的评审者:Yoav Shapira、Andrew Stellman、Dayanum Srinivas和Ben Hyde。假如我能全部采纳他们提出的极好的建议,本书无疑将更加完善。但由于时间的限制,我不得不有选择性地加以采纳。即便如此,本书的改进仍然十分显著,任何遗留下来的错误都应由我本人承担。

我的父母Frances和Henry一如既往地给予我大力的支持,与上一本书相比,这本书没有那么多技术专业名词,因而我希望他们觉得这本书读起来容易一些。

最后,我要感谢我的两位挚爱好友,Karen Underhill和Jim Blandy。在写作本书期间以及在过去的七年里,Karen给予我的友谊和理解对我来说意味着一切。没有她的帮助,我是不可能完成本书的写作的。Jim对我来说也是一样,一个真正的朋友,一个计算机行业中的王者之王,是Jim将我带入自由软件行业,正如一只鸟给予飞机飞行的灵感。

写给第二版(2017)

这本书的第二版得到了比第一版更多的人的帮助,当然,在致谢中也可能存在更多无心的遗漏。如果这里遗漏了您的名字,请接受我的歉意(也请您通知我,至少我们能把在线版本改一改)

来自O'Reilly Media公司的Andy Oram,他提供的帮助再一次远远超过他作为编辑应尽的职责。他读得很认真并提供了很多极好的建议,无论是他总体上的写作能力,或者是他开源方面的造诣,在他所有的评论中都显得淋漓尽致。这本书因为他的重视而得到很大提高,感激之情无以言表。

我和James Vasile已经是多年的好友和同事了,每周我都能在他身上学到新的东西。尽管他有一份忙碌的工作—我们是商业伙伴,所以我知道的很清楚—而且他还有家里的小孩儿要照顾,他仍然毫不犹豫的帮忙看手稿并提供意见。这些都是钱买不来的,就算要买,我也一定付不起。谢了,兄弟。

Cecilia Donnelly,她既是一个很棒的朋友,同时也是开源方面很厉害的专家,任职于芝加哥的Open Tech Strategies办公室。我和她共事很愉快,连我们的委托人都知道。她清晰的思维和敏锐的洞察力对本书的多个部分都有影响。

Karen Sandler一直不倦的帮助我。我们深入细致地就这本书中的很多话题讨论过(甚至是一些特殊的案例)。和与James聊天一样,当我们聊自由软件和其他一些事的时候,我通常也都能在Karen身上学到东西。

因为Bradley Kuhn多次提出十分专业的反馈意见,有一次他还自己写补丁,所以他的名字在这本书的commit日志里面出现过很多次。正如我在其中一个commit的日志消息里写的一样,”他对自由软件的贡献无可估量,他的参与为我们共同的事业提供了无限的灵感”

Karen和Bradley都为Software Freedom Conservancy(https://sfconservancy.org/)工作。如果你喜欢这本书并且想帮助自由软件,捐助这个组织可以是一个很好的开始,当然之后也可以捐助哦。

Ben Reser给第六章、第七章提供了很细致、专业的评论,这些评论让书增色不少。Ben,谢谢你了。

Michael Bernstein不仅在第一版和第二版的间隔期提供了许多细致的反馈,他还帮助组织了KickStarter活动,并使之成为可能。谢谢你,Michael。

Danese Cooper总是让我对项目保持专注,特别地,她为我带来消息(起初我不想听),消息说innersourcing(在组织内部采用开源开发模式)可以让组织了解学习开源的应用,最终自己也作出开源软件。我要为此和其他很多事情感谢你,Danese。

在这两个版本之间,我度过了很有收获的一段时期。我作为开放互联网工具项目研究员,在O'Reilly Media和Code for America / Civic Commons(我十分感谢他们热心提供的在纽约城的Open Plans办公室的办公区域)和New America Foundation工作。我在这项工作中学到的大部分东西都写在了书里,除了要感谢这些组织本身,我还要另外特别感谢Tim O'Reilly, Jen Pahlka, Andrew McLaughlin, Philip Ashlock, Abhi Nemani, Nick Grossman, Chris Holmes, Frank Hebbert, and Andrew Hoppin,我感谢他们和我分享他们宝贵的想法和观点。

多年来,Sumana Harihareswara和Leonard Richardson对开源软件的事情提供了坦率且有益的评论,他们的贡献让这本书日益完善,和他们做朋友也让我受益匪浅。

Software Freedom Law Center (https://softwarefreedom.org/)的Eben Moglen教会我如何将自由软件视为大规模的社会和经济现象。他还在一些情况下为我提供个人的办公地点,这非常有帮助。谢谢你,Eben。

David A. Wheeler博士每天要回答那么多人的提问,我也不知道他是如何抽出时间来回答我偶尔请教的问题的。但他做到了,每次的回答都如此正确和可靠。一直以来都多谢你了,David。

Breena Xie对开源的兴趣很快指引她发现了关于开源的深刻问题。在我推敲本书中一些特定主题的时候,这些问题对我很有帮助。同时我也要感谢她的耐心,特别是有时候占用她过多的时间(超过了我和她一开始说的时间)。谢谢你,Breena。

非常感谢Radhir Kothuri和其他HackIllinois 2017的成员,2017年2月,他们在伊利诺伊州的伊利诺伊大学香槟分校举办的活动中涉及到了印刷新版书,他们及时的鼓励了大家。我很感谢他们对这本书信任度进行的投票,同时希望HackIllinois的参与者们对投票结果满意。

我和http://neodoc.biz/的Camille Bégnis实时交流了一整天的时间。他提供的专业的DocBook帮助,让我们解决了一个长期以来我无法解决的有关书在线版本的技术问题。Merci beaucoup, Camille。

致谢中最难的一部分就是我认识到,人们在这本书第一版过后的十年来,大家分享的知识太多了,我怎么样在这里都写不完。自从第一版书以后,我一直在做开源的工作,在与许多客户、合作伙伴、受访者、专家顾问和其他旅行者的讨论中,我都很有启发。他们中有些人偶尔也会为书中的具体改进提供建议。如果没有这些集体智慧的话,我无法想象这本书的质量会怎样,所以我会试着把他们列出来,但是我很抱歉,因为我知道这名单肯定不完整。为了表示排名不分先后,在列出名单前,我用程序打乱了顺序,并取第一次输出的结果。名单如下:

Nithya Ruff, Jenn Brandel, Joseph Lorenzo Hall, Ben Wyss, Kit Plummer, Mark Atwood, Vivien Deparday, Sebastian Benthall, Martin Michlmayr, Derek Eder, Hyrum Wright, Stefano Zacchiroli, Dan Risacher, Stephen Walli, Simon Phipps, Francis Ghesquiere, Sanjay Patil, Tony Sebro, Matt Doar, Deb Nicholson, Jon Phillips, David Robinson, Nathan Toone, Alolita Sharma, Jim McGowan, Florian Effenberger, Brian Warner, Cathy Deng, Allison Randal, Ariel Núñez, Jeremy Allison, Thorsten Behrens, Deb Bryant, Holly St. Clair, Jeff Ubois, Dustin Mitchell, Dan Schultz, Luis Villa, Jon Scott, Dave Neary, Mike Milinkovich, Wolf Peuker, Paul Holland, Keith Casey, Christian Spanring, Bishwa Pandey, Scott Goodwin, Vivek Vaidya, David Eaves, Ed Sokolowski, Chris Aniszczyk, David Hemphill, Emma Jane Hogbin Westby, Ben Sheldon, Guy Martin, Michael Downey, Charles-H. Schulz, Vitorio Miliano, Paul Biondich, Richard Fontana, Philip Olson, Leslie Hawthorn, Harlan Yu, Gerard Braad, Daniel Shahaf, Matthew Turk, Mike Hostetler, Waldo Jaquith, Jeffrey Johnson, Eitan Adler, Mike Linksvayer, Smiljana Antonijevic, Brian Aker, Ben Balter, Conan Reis, Dave Crossland, Nicole Boone, Brandon Keepers, Leigh Honeywell, Tom "spot" Callaway, Andy Dearing, Scott Clark, Tina Coleman, William A Rowe Jr., Matthew McCullough, Stuart Gill, Robert Soden, Chris Tucker, Noel Hidalgo, Mark Galassi, Chris DiBona, Gerhard Poul, Christopher Whitaker, James Tauber, Justin Kestelyn, Nadia Eghbal, Mel Chua, Tony Wasserman, Robert Douglass, Simone Dalmasso, John O'Nolan, Tom Marble, Patrick Masson, Arfon Smith, Forest Gregg, and Molly de Blanc.

第二版书的改写受到一个Kickstarter项目的资金支持,该项目回应地迅速回应且慷慨帮助,我非常感谢他们所有参与的人。我希望他们会原谅我花了多于预计四倍的时间才得以完成。以下我要向该项目所有的支持者致谢,用的是他们提供给Kickstarter的名字。以下的排序是按照赞助数额(从高到低或者从低到高)进行的,但我认为这种事比较适合保持神秘吧,所以我不打算说是哪种排序了。名单如下:

Pablo, Cameron Colby Thomson, Bethany Sumner, Michael Lefevre, Maxim Novak, Adrian Smith, Jonathan Corwin, Laurie Voss, James Williams, Chris Knadler, Zael, Kieran Mathieson, Teresa Gonczy, Poramate Minsiri, j. faceless user, Michael, Isaac Davis aka Hedron A. Davis, James Dearing, Kyle Simpson, Laura Dragan, Hilary Mason, Tom Smith, Michael Massie, Erin Marchak, Micke Nordin, Xavier Antoviaque, Michael Dudley, Raisa, Paul Booker, Jack Moffitt, Aaron Shaw, maurine stenwick, Ivan Habunek, G. Carter Stokum, Barry Solow, mooware, Harish Pillay, Jim Randall, Holger S., Alan Joseph Williams, Erik Michaels-Ober, David Parker, Nick, Niko Felger, Fred Trotter, Dorai Thodla, William Theaker, Hans Bakker, Brad, Bastien Guerry, Miles Fidelman, Grant Landram, Michael Rogers, mostsignificantbit, Olivier Berger, Fernando Masanori Ashikaga, Naomi Goldenson, Brian Fitzpatrick, Eric Burns, Mark V. Albert, micah altman, Richard Valencia, Cody Bartlett Heisinger, Nick Grossman, cgoldberg, Mike Linksvayer, Simon Phipps, Yoshinari Takaoka, Christian Spanring, Ross M Karchner, Martin Karlsson, Kaia Dekker, Nóirín Plunkett, Emma Jane, Helior Colorado, Fred Benenson, George V. Reilly, Lydia Pintscher, Noel Hidalgo, Albert White, Keng Susumpow, Mattias Wingstedt, Chris Cornutt, Zak Greant, Jessy Kate Schingler, James Duncan Davidson, Chris DiBona, Daniel Latorre, Jeremiah Lee Cohick, Jannis Leidel, Chris Streeter, Leonard Richardson, Terry Suitor, Trevor Bramble, Bertrand Delacretaz, John Sykora, Bill Kendrick, Emmanuel Seyman, Paolo Mottadelli, Gabriel Burt, Adrian Warman, Steve Lee, Andrew Nacin, Chris Ballance, Ben Karel, Lance Pollard, richardj, Brian Land, Jonathan Markow, Kat Walsh, Jason Orendorff, Jim Garrison, Jared Smith, Sander van der Waal, Karen Sandler, Matt Lee, John Morton, Frank Warmerdam, Michael R. Bernstein, John Yuda, Jack Repenning, Jonathan Sick, Naser Sharifi, Cornelius Schumacher, Yao-Ting Wu, Camille Acey, Greg Grossmeier, Zooko Wilcox-O'Hearn, Joe, Anne Gentle, Mark Jaquith, Ted Gould, James Schumann, Falkvinge, Schuyler Erle, Gordon Fyodor Lyon, Tony Meyer, Salvador Torres, Dustin J. Mitchell, Lindy Klein, Dave Stanton, Floyd DCosta, Agog Labs, Adrià Mercader, KIMURA Wataru, Paul Cooper, alexML, Stefan Heinz, maiki, BjornW, Matt Soar, Mick Thompson, mfks, Sebastian Bergmann, Michael Haggerty, Stefan Eggers, Veronica Vergara, Bradley Kuhn, Justin Tallant, dietrich ayala, Nat Torkington, David Jeanmonod, Randy Metcalfe, Daniel Kahn Gillmor, George Chamales, Erik Möller, Tim Schumacher, Koichi Kimura, Vanessa Hurst, Daniel Shahaf, Stefan Sperling, Gunnar Hellekson, Denver Gingerich, Iliana Weller, adam820, Garance Drosehn, Philip Olson, Matt Doar, Brian Jepson, J Aaron Farr, Mike Nosal, Kevin Hall, Eric Sinclair, Alex Rudnick, Jim Brucker, PEI-HAN LEE, Michael Novak, Anthony Ferrara, Dan Scott, Russell Nelson, Frank Wiles, Alex Gaynor, Julian Krause, termie, Joel McGrady, Christian Fletcher Smith, Mel Chua, William Goff, Tom Liesenfeld, Roland Tanglao, Ross Gardler, Gervase Markham, Ingo Renner, Rochelle Lodder, Charles Adler, Dave Hylands, Daryn Nakhuda, Francois Marier, Kendric Evans, Greg Price, Carlos Martín Nieto, Greg Stein, Glen Ivey, Jason Ray, Ben Ubois, Landon Jones, Jason Sperber, Brian Ford, Todd Nienkerk, Keith Casey, Leigh Honeywell, Aaron Jorbin, Christoph Hochstrasser, Miguel Ponce de Leon, Dave Neary, Eric Lawrence, Dirk Haun, Brian Burg, Brandon Kraft, Praveen Sinha, ML Cohen, Christie Koehler, Ethan Jucovy, Lawrence S Kemp, Justin Sheehy, Jonathan Polirer, Ronan Barzic, Greg Dunlap, Darcy Casselman, Jeremy G Kahn, Sam Moffatt, James Vasile, Simon Fondrie-Teitler, Mario Peshev, Alison Foxall, Jim Blandy, Brandon Satrom, Viktor Ekmark, Tor Helmer, Jeff Ubois, Gabriela Rodriguez, James Tait, Michael Parker, Stacy Uden, Peter Martin, Amy Stephen, James Tauber, Cameron Goodale, Jessica, Ben Sheldon, Forest Gregg, Ken McAuliffe, Marta Rybczynska, Sean Taylor, John Genego, Meeuw, Mark MacLennan, Kennis Koldewyn, Igor Galić, Henrik Dahlström, Jorren Schauwaert, Masahiro Takagi, Ben Collins-Sussman, Decklin Foster, Étienne Savard, Fabio Kon, Ole-Morten Duesund, Michael Downey, Jacob Kaplan-Moss, Nicola Jordan, Ian Sullivan, Roger W Turner, Justin Erenkrantz, Isaac Christoffersen, Deborah Bryant, Christopher Manning, Luis Villa, Judicaël Courant, Leslie Hawthorn, Mark R. Hinkle, Danese Cooper, Michael Tiemann, Robert M. Lefkowitz, Todd Larsen, T Foote, Ben Reser, Dave Camp, Scott Berkun, Garrett Rooney, Dinyar Rabady, Damien Wyart, Seth Schoen, Rob Brackett, Aisha, Winnie Fung, Donald A. Lobo, Dan Robles, Django Software Foundation, Mark Atwood, Krux Digital, Stephen Walli, Dave Crossland, Tina, and Thorsten Behrens.

再次对你们所有人表示感谢!

免责声明

本书中所表达的想法和观点均属我本人。它们并不一定代表CollabNet或是Subversion项目的看法。



[1] 术语“开源”和“自由软件”在此处的上下文中本质上是同义词。有关他们的更多讨论参见Chapter 1, 介绍中的the section called ““自由”还是“开源””

Chapter 1. 介绍

大部分自由软件项目是失败的。

人们总不太喜欢听太多失败的故事,只有成功的项目才能吸引我们的注意力。林林总总的自由软件的总数是惊人的[2],尽管只有一小部分的项目成功了,但这仍然只是那些广为人知的项目的一部分。有太多的项目由于不为人知,即使失败了我们也不会听到。我们无法用一个确定的时间点来宣判一个项目的死刑,人们只是停止工作无所事事。即使我们知道一个项目的最后一个变动是何时添加的,但是在当时那些做这些工作的人通常并不知道这会是最后的晚餐。我们甚至无法明确地定义何时一个项目才算是断气了。是停止活动6个月之后?是用户数量停止增长并且人数还少于开发者的数量时?当一个项目的开发者发现他们只是在重复别人的工作,而决定放弃项目,然后他们决定加入另一个项目,并且在项目中使用之前的一些工作成果?原先的项目死亡了,或者只是搬了一次家?

因为是如此复杂,得出一个精确的失败率是不可能的。但是十多年以来流传于SourceForge.net或是用Google搜索得到的开源运动传闻,都指向同一个结论:这个比率是非常高的,也许能达到90–95%。如果把那些虽然存活但是内忧外患的项目算在内,这个比率还将更高,这些项目通常仍然生产可执行的代码,但已不再是开发者的乐园了,要么是无法尽其所能的快速和互相依赖的作出进展了。

这本书的目的旨在说明如何避免失败。它不仅演示了如何才是正确的做事方法,而且告诉你错误出在何处,以便你及时发现和纠正错误。我希望在读过此书之后,你不仅能对如何避免开发过程中的常见陷阱有丰富的技术储备,而且对如何使一个成功的项目得到成长和维护有深入的了解。成功不是一场零和游戏,此书也不是教你如何在竞争中获胜或是领先的。相反,运作一个开源项目的重要部分就是流畅地同关联项目合作。在更高的层次上,每一个成功的项目都为在世界范围内自由软件的成长作出一份贡献。

如果说导致自由软件项目失败的原因类型与私有软件是相同的,那是令人诱惑的。实际上,在自由软件内不会有诸如建立在不切实际的需求上的垄断,含混不清的规范,可怜的代码管理,设计阶段不足等等笼罩在传统软件工业上的幽灵。有关这些主题的书已经是汗牛充栋,我不打算重复。我想做的是描述自由软件独有的问题。当一个自由软件项目开始运转,最常见的问题是开发者(或是经理)难以识别开源软件开发过程中的独特问题,尽管他们可能已经在那些闭源软件的常见问题上摔打了多年。

一个最常见的错误就是急于从开源的形式本身获得好处,但这是不切实际的。一纸开放许可证不会一下子让成群的活跃开发者自愿地把他们的时间交给你的项目,将一个原本问题多多的项目开源也不能自动地修正这些问题。实际上很可能相反,与不开源相比,开放一个项目短期内会带来一系列全新的复杂问题和代价。开放意味着要让完全陌生的人读懂代码,建立一个开发网站和邮件列表,通常还会第一次需要写文档。这些事情的工作量是相当大的。当然如果有开发者表示出了兴趣,在他们为你的项目带来好处之前回答他们的问题也是一个额外的负担。如同开发者Jamie Zawinski回忆Mozilla项目早期的混乱状况所说地:

开源的确行,但它绝不是万能药。我对你的忠告是:你不能指望在一个垂死项目上洒一点"开源的精灵魔粉"就能让所有事情奇迹般地运转起来。做软件是困难的。问题不会那么简单。

(来自http://www.jwz.org/gruntle/nomo.html

一个相关的错误是对展示和打包的轻视,特别是当一个项目顺利运转时总认为这些以后再做不迟。展示和打包有很多的目的,所有的一切都是为了减低进入的门槛。使项目对那些后来者有吸引力意味着编写用户和开发者文档,建立为新来者提供信息的网站,尽可能自动化软件的编译和安装工作,以及其他。很不幸,很多程序员认为与编码相比,这些工作都是次要的。导致这种情况的原因有很多。首先,他们感觉这些都是附加作业,因为对熟悉项目的这部分少数人来说,它的益处是显而易见的,反之亦然。毕竟这些编写代码的人并不真需要打包。他们知道如何安装,管理和使用这些软件,因为代码就是他们编写的。其次,展示和打包所需要的技术通常和写代码完全不同。人们总是倾向于专注自己所擅长的,即使另外的工作能对整个项目起到事半功倍的作用。 Chapter 2, 起步将详细讨论展示和打包,并且解释从项目的一开始就确定这些工作的优先地位的重要性。

接下来的一个谬误是认为开源几乎或完全不需要项目管理,或者照搬商业开发的那一套管理模式也能在开源中做得很好。在一个开源项目中,管理总是不起眼的,但在成功的项目中,它通常在幕后起到推动的作用。一个简单的心理试验就足够显示其原因。一个开源项目由来自四面八方的程序员组成—一群臭名昭著的自由独立思想者—他们中的大部分人从来没有互相见过面,为这个项目工作只是出于他们的个人目标。心理试验能很简单地预测如果没有管理,在这样一个团体中会发生什么。除非发生奇迹,否则他们很快就会四分五裂。事情不会如我们希望的那样自己运转。管理偶尔会相当活跃,但是大部分时候是非正式的,微妙的,低调的。只有一件事情能把开发者团结在一起,就是他们相信团队合作比单干能做得更多。因此最重要的管理目标是确保他们继续相信这一点,做到这点需要设定交流的标准,需要让能干的开发者不会因为个性而受到排斥,总之要使项目成为开发者的留恋之地。我们将在后面讨论这些工作需要的具体技术。

最后还有一种类型的问题也许我们可以称之为“文化引导失败”。十年之前,甚至五年之前,谈论自由软件运动的整体文化都还为时过早,但现在不是了。一种清晰的文化正在慢慢浮现,虽然它不是一个整体—如同很多地域约束的文化,易于产生内在的异议和派别—但它有一个基本的一致的核心。大部分成功的开源项目展示了这个核心中的部分或全部特质。他们奖励符合这种文化的行为,惩罚相反的;他们创造了一种鼓励计划外的参与氛围,甚至不惜中心协调时间的代价;他们对粗野和礼貌的概念与流行观念有本质上的区别。最重要的是,长期的参与已经内化了这些标准,所以他们能够对将要发生的举动能大体上取得共识。失败的项目通常显著的背离了这个核心,尽管并非本意,但通常是因为没有对建立合理默认行为方式达成共识。这意味着一旦问题出现,由于参与者缺乏通过弥补分歧而对问题做出反馈的现成文化储备,形势会迅速恶化。

此书是一本实用的指南,而不是一篇人类学论文或是史书。然而了解今天的自由软件文化的起源对任何一个实际的建议都是必要的基础。一个理解这种文化的人能在开源世界任意驰骋,即使遇到很多的各地风俗和方言,仍然可以自信和有效地参与。相反,一个没能很好理解这种文化的人将会在组织或是参与一个项目的过程中处处遇到困难和意外。由于自由软件的开发人员的数量仍然在飞速增长,其中有很多人属于后一种情况—这多半是一种新近加入的文化,并且会持续一段时间。如果你自认为是其中的一员,下一节为你在以后将在本书或是互联网上遇到的讨论提供了背景材料。(另一方面,如果你已经在开源中工作了一段时间,你也许早已了解了这段历史,你可以选择跳过这一节。)

历史

软件分享自从软件诞生的那一天起就出现了。在计算机工业的早期,厂商认为竞争的优势在于对硬件的创新,因此并不太认真把软件当成商业资产看待。这些早期机器用户许多都是科学家或是技术人员,他们有能力自己修改和扩展随机附送的软件。有时用户不仅将补丁反馈给厂商,而且分发给相似机器的其他用户。厂商经常允许甚至鼓励这么做:在他们眼里,无论是哪一种渠道,对软件的改进都使得机器对其他的潜在消费者更有吸引力。

虽然今天的自由软件文化在很多方面都和早期相似,但是有两点重要的不同。首先,当时几乎没有硬件的标准—那是一个计算机设计创新的黄金时代,但是繁多的计算机架构也意味着所有的事情都无法同其他的兼通。因此,为一台机器编写的软件一般无法在另一台上工作。在一种特定的架构或是架构族上程序员需要专门的知识(今天程序员更多的是学习一种编程语言或是语言类型的专门知识,他们对他们的专业知识能移植任何一台遇到的机器上非常自信)。因为个人的专门知识总是针对一种特定类型的计算机,这些专门知识的积累能让计算机对他们以及同事变得越来越有趣。这就是为什么厂商对让特定机器的代码和知识尽可能广的得到传播感兴趣的原因。

其次,当时没有互联网。虽然当时对分享的法律约束比今天少,但却有更多的技术约束:也就是说,和说话相比,把数据从一个地方移到另一个地方是笨重不便的。在一些公司和实验室里员工之间,可以通过一些不错的小型的局域网共享信息。但当一个人想同不限地点的所有人分享时,问题依然存在。克服这些问题的途径很多。有时独立的团体之间会互相联系,通过邮局寄送磁盘或是磁带,有时厂商扮演了补丁的中心情报交换所的角色。厂商还会帮助在大学里的早期计算机开发者,那里的气氛是鼓励知识传播的。但是数据传输所必须的物理媒体意味着分享总会遇到阻力,和(实际上的或是组织上的)距离成正比的阻力。现在这种广泛的,几乎没有阻力的分享,在那时还是不可能的。

私有软件和自由软件的兴起

随着工业的成熟,接连发生了一系列相关的变化。众多硬件设计中的赢家逐渐清晰起来—有技术优势的赢家,有行销优势的赢家,或是两者结合的赢家。与此同时,被称为“高级”语言的编程语言的发展意味着一个用某种语言写成的程序能够转移到(“编译”)另一种类型的计算机上运行。硬件厂商不会忽视这其中的含义:现在客户无须再把自己捆绑在一种特定的计算机架构上就可以开展一个大型的软件工程项目。随着各类计算机的性能差异日益变小,以及低效率设计的消失,硬件成了厂商为未来利润率下降的唯一指望。原始的计算能力成了一种可替代的产品,而软件成为差异化优势。销售软件或至少将它视为硬件销售不可分割的一部分,看起来是一种不错的策略。

这意味着厂商必须开始更严格地在他们的代码上强制执行版权。如果用户之间继续简单地分享和修改代码,他们可能会独立完成一些改进,现在被供应商当成“附加价值”用来销售。更糟的是,分享代码可以落入竞争对手的手里。讽刺的是,这一切都发生在互联网即将破壳而出之时。就在无障碍的软件分享在技术是终于成为可能时,计算机行业内发生的变化则使它在经济上无法受到欢迎,至少计算机公司的观点是如此。供应商手段强硬,要么拒绝客户访问自己机器上的源代码,要么是通过保密协议使方便的共享成为不可能。

有意识的反抗

虽然无障碍代码分享的世界正在慢慢凋零,但至少有一名程序员的心中保持着清醒。理查德·斯塔尓曼(Richard Stallman)在70年代和80年代早期一直为麻省理工学院的人工智能实验室工作,那里是代码分享黄金时代的黄金圣地。人工智能实验室有很强的“黑客精神”,[3]那里的人对分享为系统做出的任何改进有狂热的爱好。正如斯塔尓曼后来写到的:

我们没有把我们的软件称为“自由软件”,因为那时这个术语还不存在,但它确实是。无论外面的大学或是公司来的人来索要程序,我们都很高兴这么做。如果你看到在用的一个少见还有趣的程序,你总可以要求看源代码,所以你能读它,修改它,或者用拆取部分写一个新程序。

(来自http://www.gnu.org/gnu/thegnuproject.html

1980年之后不久工业界发生的变化最终影响到了人工智能实验室,斯塔尓曼周围伊甸园式的社区坍塌了。一家创业公司挖走了很多实验室的程序员去开发一个操作系统,这个系统同实验室正在开发的非常相似,但使用了独占许可证。与此同时,人工智能实验室购买了带有私有操作系统的新设备。

斯塔尓曼见一叶落而知秋:

那个时代的现代化计算机,比如VAX或68020都有自己的操作系统,但都不是自由软件:为了得到一份能运行的拷贝,你甚至得签署一份保密协议。

这就是说使用一台计算机的第一步是承诺不帮你的邻居。一个互助的社区是被禁止的。私有软件的拥有者定下了规矩,“如果你和你的邻居分享了,你就是强盗。如果你想要改变,来祈求我们做吧。”

此时,他性格中的怪僻萌动了,他决定反抗这种趋势。他既不想继续留在人去楼空的人工智能实验室,也不想在一家新公司里写代码,因为他写出的代码会被锁在保密箱里,最终他从实验室辞职,随后创建了GNU项目和自由软件基金会(FSF)。GNU[4]的目标是开发一个完全自由和开放的操作系统和配套的应用软件,它们的用户永远不会阻止去破解或是分享它们的修改。本质上他是要重建人工实验室内被摧毁的那些东西,但是这一次是在全世界的规模上,并且还要避免导致人工实验室的文化被动摇破裂的那些弱点。

除了新操作系统的工作,斯塔尓曼还设计了一套确保他的代码无限自由的版权许可证。GNU通用公共许可证(GPL)是法律博弈中的奇招:它声明允许无限制地复制和修改代码,同时拷贝和派生产物(即修改版本)必须在原始版本的相同许可证下发布,不得附加限制。实际上,它用版权法去达到一个同传统版权法相反的目的:取消对软件分发的限制,它阻止任何人,甚至是作者本人对此的限制。对斯塔尓曼来说,这要比简单地把他的代码分发到公共领域好得多。因为在公共领域,一份实际的拷贝有可能被包含在一个私有程序中(这样的事情我们在使用宽松的版权许可证的代码中听到很多了)。虽然这种包含不会在任何方面减弱原始代码的持续可用性,但它意味着斯塔尓曼的努力可能会帮助敌人—私有软件。GPL为自由软件提供了一套保护机制,因为它阻止了非自由软件利用GPL许可证下代码的优势。GPL同其他自由软件许可证关系的详细讨论在Chapter 9, 许可证,版权和专利

在很多程序员的帮助下──其中有些是认同斯塔尓曼的思想体系,有些只是为了能看到自由软件的代码──GNU项目开始发布操作系统中最重要组成部分的自由替代品。因为计算机硬件和软件已经高度的标准化了,使用GNU替代其他的非自由操作系统成为可能,许多人也这么做了。GNU文字编辑器(Emacs)和C编译器(GCC)特别的成功,它们获得大量忠实的拥护者,这不是因为其理想主义的基础,而是因为其技术价值。约在1990年GNU已经生产了一个自由操作系统的大部分,除了内核—实际负责引导计算机、管理内存、磁盘和系统其他资源的部分。

不幸的是,GNU项目选择的内核设计要比预想的更难实现。随后的延期使得自由软件基金会没能及时地发布一个彻底的自由操作系统。这缺失的部分最终由一个芬兰的计算机科学系的大学生Linus Torvalds补完,在遍布全世界的志愿者的帮助下他用更加保守的设计完成了一个自由内核。他将其命名为Linux,当把内核同GNU项目的现存软件组合在一起,结果就是一个完全自由的操作系统诞生了。第一次,你不再需要任何的私有软件来启动和使用你的计算机。[5]

这个操作系统上的很多软件都不是GNU项目的产物。实际上,GNU不是唯一的开发自由操作系统的团体(例如,当时最终发展为NetBSD和FreeBSD的代码已经开始编写)。重要的不仅仅是自由软件基金会产出的代码,而且是它们的政治修辞。把自由软件当成一个目标而并非一种手段讨论,让那些对此并没有政治意识的程序员们很为难。即使那些并不认同自由软件基金会的程序员也不得不面对这些问题,只要他们处于不同的位置。自由软件基金会通过在他们的代码上附带有关GPL和其他文字的信息,成功地扮演了鼓动家的角色。随着他们的代码广泛地被分发,思想也随之流传。

意外的反抗

在自由软件运动的早期还发生了很多其他事情,其中很少有如斯塔尓曼的GNU项目般清晰的思想体系。其中一个最重要的是伯克利软件发行版(Berkeley Software Distribution,BSD)一个Unix操作系统的重新实现—这个项目可以一直追溯到1970年代晚期AT&T公司内由加州大学伯克利分校负责的一个松散的私有研究项目。BSD并没有什么要程序员们联合起来并且共同认可的政治信条,他们通过高度分散地开发方式从零开始重写了Unix命令行工具和代码库,最终是操作系统内核本身,这一切的大部分都是由志愿者完成的,用天才和热情实践了这个信念。BSD项目成了非意识形态的自由软件开发的主要例子,并且他们为那些在开源世界继续保持活动的开发者提供了训练场地。

另一个合作开发的重镇是X Window System,一个由MIT联合其他有兴趣为客户提供窗口系统的硬件厂商在80年代中期开发的自由的网络透明的图形计算环境。和私有软件恰恰相反,X许可证故意允许在自由核心之上建立私有扩展—每一个成员都需要机会加强默认的X发布,这样就会获得了超越其他成员的竞争优势。X Windows[6]自身是自由软件,但其主要目的是为了平衡商业利益竞争中的差距,对终结私有软件的统治没有丝毫的诉求。还有一个早于GNU项目很多年的例子是TeX,Donald Knuth的自由排版系统。他使用的许可证允许任何人修改和分发代码,但如果未能通过一个非常严格的兼容性测试,则不允许冠以"TeX"的名称(这是自由许可证的“商标保护”的一个例子,更多的讨论在Chapter 9, 许可证,版权和专利)。Knuth并非对软件应该是自由还是私有的问题有什么意见或是其他诸如此类的目的,他需要一个更好的排版系统是为了完成他真正的目标—一本计算机编程的书—当书完成了,没有理由不把他的系统公之于众。

虽然没有列出每一个项目和每种许可证,但还是可以确信,在1980年代末,出现了许多基于各类许可证的项目。许可证的多样性反映了动机的多样性。即使是一些选择GNU GPL的程序员也没有和GNU项目同样强烈的意识形态动机。尽管他们很享受为自由软件工作,但是许多开发者并不把私有软件视作社会恶魔。确实有些人是受到道德冲动的驱使要去消灭“囤积软件”(斯塔尓曼对非自由软件的称呼)的世界,但其他人更多的是出于对技术的狂热,或对能和志同道合者合作感到愉悦,甚至简单地出于人类对荣耀的渴望。大体上说,这些不同的动机并没有造成冲突。部分原因是和其他的创造性活动如散文和视觉艺术不同,软件必须通过半客观测试才能成功:它必须能运行,去除绝大部分的bug。这自动地给了一个项目的全部参与者一个共同的背景,一个理由,一个无需为除了技术以外的问题担心的协同工作的框架。

开发者们还有另一个团结互助的原因:自由软件世界生产了很多质量非常高的代码。要么是令最接近的非自由对手都望尘莫及,要么是可以匹敌,或至少价廉物美。虽然也许会有一些人是出于严格的意识形态的背景才使用自由软件,但绝大部分人是因为它更出色才使用自由软件的。在这些人中,总有一定比例的人乐意将自己的时间和技术贡献出来帮助维护和改进软件。

这种产出优秀代码的趋势并非是普遍的,但在全球的自由软件项目出现的频率越来越高。这引起高度依赖软件质量的商业公司的关注。其中的许多发觉他们其实早已经在日常的操作中使用自由软件,只是并没有意识到(管理层并不总是能意识到IT部门做的每件事)。公司开始在自由软件项目中扮演越来活跃和公开的角色,他们向自由软件的发展捐助时间和设备,有时甚至是直接的资助。在最好的情形下,这些投资能获得数倍的回报。这些赞助商只需要为少数全职投入的专家级程序员支付工资,获得的回报却包括了无偿的志愿者和领取其他公司薪水的程序员的全部工作成果。

“自由”还是“开源”

随着商业世界越来越多的关注自由软件,程序员们面临新出现的问题。首先是单词“自由”本身。第一次听说“自由软件”(free software,在英语中free既有自由的意思,也有免费的意思)这个词的时候,许多人都错把它理解成“免费软件”。确实大部分的自由软件都是免费的,[7] 但不是所有的免费软件都是自由的。例如在1990年代的浏览器大战中,为了抢占市场份额,网景和微软都无偿地发布他们的网络浏览器。这些浏览器都不是“自由软件”。你无法得到源代码,即使得到了也没有权利修改和再发布。[8]你唯一能做的是下载一个运行文件,然后运行。这些浏览器的自由不会比从商店里购买的盒装软件更多;它们只是有较低的价格。

围绕自由一词发生的混乱,很不幸地完全是由于英语本身的多义性造成的。大部分的其他语种对“免费”和“自由”明确地区别对待(例如在罗曼斯语中gratislibre的差别对听众而言是一清二楚的)。但英语是互联网事实上的桥梁语言,所以一个英语的问题在某种程度上来说即是每个人的问题。围绕自由一词的误解是如此之广,以至于最终自由软件程序员们发明了一个公式来应对:“It's free as in freedom—think free speech, not free beer。”但一遍又一遍的解释还是让人厌倦。许多程序员认为,即使加以解释,对自由的岐义正在阻碍公众对这种软件的理解。

但实际的问题更复杂。free一词承载了一个无可避免的道德内涵:如果自由是它自身的最终目标,它同自由软件是否被更多人接受,是否能从商业中赚取更多的利益无关。这个动机唯一的光明面从根本上说既不是技术也不是商业,而是道义。此外,“free as in freedom”的定位也迫使那些既想在生意的某一方面支持实用的自由程序,而另一方面又继续推销私有软件的公司陷入前后矛盾的境地。

本已陷入身份危机的社区又迎来了这些困境。如果说自由软件运动有一个总体目标的话,那些实际上写自由软件的程序员们并不都为了同一个目标而工作。甚至于从一个极端走向另外一个极端的观点会引起误解,因为我们会错误地以为只有两种极端的观点,而实际上存在着多层次的看法。然而,如果我们忽略其间的细微差别,他们都可以被归入两类信念。一个团体追随斯塔尓曼的观点,认为共享和修改的自由是最要的事,因此如果你不再谈论自由,你就忽略了核心问题。另一些人认为软件本身才是最重要的因素,并且对公开地宣布私有软件本质上是坏的而感到不舒服。部分的,但非全部自由软件程序员相信作者(或是雇主,如果是有偿工作)应该有权利控制分发的条款,选择何种条款不应该受到道德的审问。

在很长时间里这些分歧并不需要认真对待,但自由软件在商业世界里的快速成功使得这些问题无法再回避。1998年一群程序员结成一个团体,也就是后来的开源促进会(Open Source Initiative,OSI)[9]创造了开源一词来替代“自由”。OSI认为“自由软件”不仅有潜在的岐义,而且“自由”一词本身就是一系列问题的根源。运动本身需要一个在商业世界里的营销程序,而谈论道德和社会公益在公司董事会里是不受欢迎的。用他们自己的话说:

开源宣言是自由软件的一个营销程序。用务实的基础推动自由软件远比慷慨激昂大谈理想有用得多。成功的本质没有变,失败的象征和看法已经变了。 ...

需要告知大多数技术人的不是开源的概念,而是名字。为什么我们不再像从前那样称之为“自由软件”呢?

一个直接的原因是“自由软件”一词容易以一种导致冲突的方式被误解。 ...

但真正更名的原因是营销上的。我们现在想打入商业世界。我们有成功的产品,但在过去我们的定位是可怕的。自由软件一词被商人们误解了,他们把这种描述理解成反商业主义,甚至更糟,贼。

主流公司的CEO和CTO们绝不会买"自由软件"。但如果我们保持非常相似的传统,人还是那些,相同的自由软件许可证,只是换了一个“开源”标签的话?他们会买。

一些黑客觉得这很难相信,但那是因为他们的技术化思维已经僵化,被条款所束缚,不能理解当你推销某样东西时形象有多重要。

做营销时,外表是很现实的问题。我们打算用什么样的形象来消除同公司打交道的障碍,和我们的行为,我们的信念,我们的软件同样重要。

(来自http://opensource.feratech.com/advocacy/faq.phphttp://opensource.feratech.com/advocacy/case_for_hackers.php#marketing

通过上面的文字我们可以一窥争论的冰山一角。它提到了“我们的信念”,但是巧妙地回避了这些信念到底是什么。对有些人呢,这种信念也许是认为开放的开发过程将产出更好的代码,对其他人也许是认为所有的信息都应该共享。他们用到了“贼”一词(据推测是)影射非法的复制—许多人反对这一点,认为如果原持有人随后仍然保留原件就不能视作贼。这里有一个明显的暗示说自由软件运动被错误地划入了反商业主义,但它小心翼翼地回避了这种归类是否有现实依据的问题。

其中没有一条可以说明OSI的网站是自相矛盾或是误导的。确实没有。相反,这个例子表明了OSI所主张的,正是自由软件运动所缺少的,也就是好的营销,此处的“好”指的是“能在商业世界生存”。开源宣言给许多人带来他们一直寻找的—一套将自由软件作为开发的方法论和商业策略而不是道德圣战的语汇。

开源促进会的出现改变了自由软件的面貌。它将长久存在的矛盾摆上了桌面,迫使运动承认与外部一样,其自身内部同样有派系斗争。由于大部分的项目都包括了来自两个阵营的程序员,加上一些很难明确归类的参与者,如今二者都已经找到了共同的基础。这不意味着人们从不谈论道德动机—例如,有时人们会讨论传统的“黑客精神”的流失的问题。但是很少有自由软件/开源开发者在一个项目中公开地质疑他人的基本动机。作出贡献远比贡献者本身重要。如果有人代码写的不错,你不会问他们到底是出于道德原因还是因为雇主付给他们工资或是为了在推荐信上添加砝码,或其他什么原因。你从技术角度评估贡献,从技术角度反馈。甚至Debian这样毫不讳言政治的组织(他们的目标是提供一个100%自由的操作环境),也已经不再那么严格的对待集成非自由代码和同目标不一致的程序员共事了。

现状

当运作一个自由软件项目时,你不必在日常工作中谈论沉重的哲学命题。程序员不会要求项目中的其他人和自己在所有事情上能够看法一致(那些这一点上坚持的人很快就会发现他们无法在任何项目内工作)。但是你必须了解“自由还是开源”之争的存在,部分原因是避免谈论引起部分开发者抵触的事情,部分是因为理解开发者的动机是管理一个项目最好的方法—有时,是管理一个项目的唯一方法。

自由软件是一种有关选择的文化。你必须首先理解为什么人们会参与其中,才能成功地运作一个项目。强制是不管用的。如果一个项目让人不高兴了,他们会立刻转移到另一个项目。自由软件的独特之处还在于志愿者社区的投资强度。大部分内部的人从来没有和另一个参与者面对面地交流过,只是在高兴时捐助一点时间。通常人类用来互相结识并结成牢固的团体的渠道被压缩成了一条细管:在键盘上打字然后通过电缆传输。因此,形成一个有凝聚力和专注力的组织需要花上很长时间。相反,在首次接触的五分钟内流失一个潜在的开发者是非常容易的。如果对一个项目没有良好的第一印象,新来者很少会给予第二次机会。

关系的无常性,或者是潜在的无常性,也许是面对一个新项目时最让人畏惧的一点。如何才能使这些人尽可能长时间的呆在一起做一些有用的事?这个问题的答案足可以用本书剩余的篇幅来说明,但如果必须用一句话来回答,会是这样:

人们应该能感到他们同一个项目的联系和对它的影响力是直接同他们的贡献成正比的。

没有哪类开发者或是潜在的开发者应该感到自己由于非技术原因而被区别对待。特别是项目的赞助商或是领取报酬的开发者在这一点上要特别小心,这一点将在后面的Chapter 5, 金钱详细讨论。当然,这不是说如果没有公司赞助商的话就可以高枕无忧了。钱只是能影响项目成功的许多因素之一。还有诸如语言的选择、许可证的选择、何种开发过程、设立何种类型的基础架构之类的许多其他因素。在良好的基础上开始一个项目是下一章的主题。



[2] SourceForge.net,一个著名的代码存放站点,截至到2004年4月中旬,总共有79225个项目注册。虽然这只是选择使用SourceForge的项目数量,但已经非常接近互联网上全部自由软件项目的数量了。

[3] 斯塔尓曼的“黑客”指的是“喜欢程序并且喜欢用它炫耀聪明的人”,不是近些年来的新含义“非法进入计算机的人。”

[4] “GNU's Not Unix”的缩写,扩展后短语中的GNU其实是同一意思。

[5] 从技术上来说Linux不是第一个。在Linux之前不久已经有了一个能在IBM兼容机上运行的自由操作系统,386BSD。然而386BSD的启动和运行还不太稳定。Linux的飞速发展不仅因为它是自由软件,而是因为安装之后你有更大的几率能启动计算机 。

[6] 正式的称呼是“X Windows System”,但实际中人们通常称之为“X Windows”,因为三个单词太繁琐了。

[7] 发放自由软件的人可以收取一定的拷贝费用,但是由于他无法阻止受领者去免费地再发放,价格还是会很快接近于零。

[8] 网景Navigator浏览器的源代码最终1998年在一个开源许可证下发布,成为后来的Mozilla网络浏览器的基础。参见http://www.mozilla.org/

[9] OSI的主页http://www.opensource.org/

Chapter 2. 起步

有关自由软件是如何发起的经典模型是由Eric Raymond提出的,在一篇今天已广为人知的有关开源开发的论文《大教堂和集市》中,他写道:

每一个好的软件都始于挠到一个开发者的痒痒处。

(来自http://www.catb.org/~esr/writings/cathedral-bazaar/

注意Raymond并没有说只有当某些开发人员心里痒痒之后才会导致一个开源项目的诞生。相反,他是说只有当程序员对解决某个问题产生了个人兴趣之后,才能产生优秀的软件;这一点同自由软件的联系在于,大部分自由软件项目的最初动机都是始于一个人的痒痒处。

这仍然是大部分项目的动因,但自从1997年Raymond写下这些话之后这种现象正在慢慢减少。今天我们有了一些组织—包括盈利性的大企业—从零开始大型的,集中式管理的开源项目。单个的程序员为了解决一个个人问题敲出一些代码而最后意识到可以有更广泛地应用的例子仍然是许多新自由软件的源头,但不再是唯一的故事。

然而Raymond的观点仍然是真知灼见。关键在于软件的生产者对它的成功有直接的兴趣,因为是自己用。如果软件没能达到期望的目标,那些编写它的个人或是组织会在日常工作中感到不满。例如,OpenAdapter项目(http://www.openadapter.org/),这是一个由德累斯顿·克莱沃特投资银行(investment bank Dresdner Kleinwort Wasserstein)发起的一个用于集成不同财经信息系统的开源框架,就很难说是始于哪个程序员的个人痒痒处。它始于一个组织的痒痒处。这些痒痒处直接来自这个组织和他们的合伙人的经验,因此如果这个项目没能减轻这些痒痒症,他们立刻能够感觉到。这种情形产出了优秀的软件,因为形成了一个良性的循环。程序不是为了卖给其他人而编写的,不是为解决他人的问题。它是为解决某个自己的问题而编写的,之后再同其他的人分享,足可以把问题想像成疾病,而程序是分发的药物,用来彻底地消灭传染病。

本章是关于如何将一个自由软件项目介绍给全世界,但是其中的很多建议听起来会很像一个卫生组织在分发药物。两者的目标的确非常相似:你要弄清楚药品的作用,把它发放到需要的人手中,并确保那些人知道如何使用它。但对一个软件,你还需要诱使那些接受者加入研究计划来改进“药物”。

自由软件的发布是一项双重任务。软件既要满足使用者,也要满足开发者。这两种需求不一定是冲突的,但是会为项目初期的展示增加复杂度。其中有些信息对两者都有用,有些只是对其中一类有用。对两种信息都应该依照展示的比例原则:描述的详细程度应该同读者在该阶段所应该花费的时间和努力程度相对应。更多的努力应该带来更多的回报。当这种关系发生偏差时,人们有可能很快失去信任并且停止投入精力。

这一点的必然结果就是形象的重要性。程序员们对这一点总是嗤之以鼻。对本质超越形式的热爱成了他们职业自豪感的一部分。所以毫不意外,许多程序员表现出对营销和公关工作的厌恶,同样,职业图形设计师往往也对程序员们的产品感到惊恐万状。

这是一个遗憾,因为有时候形式就是本质,并且项目的展示就是这种情形之一。例如,浏览网页的人对一个项目的第一观感就是来自网站的外观。这种观感的形成要早于任何一种实际的内容之前—包括文字和链接。不管这看起来多么不公平,人们无法不形成一个即时的第一印象。网站的形象向读者传递了一个信号,即网站的展示是否经过了精心安排。人类对检测心思的投入有着极为敏锐的感觉。我们中的大多数人都能在一瞥间看出一个网站是随便拉起来的还是经过认真思考的。这是你的项目展现出信息的第一步,它所建立起来的印象将对整个项目的后续部分施加影响。

因此,尽管本章的大部分篇幅谈论的是你应该用什么样的内容开始你的项目,但别忘了外观和感觉同样重要。因为项目的网站同时为使用者和开发者两类人服务的,相应的投入也要透明和有针对性。虽然这不是一本讨论网页设计的专著,但是当网站是为多种类型的读者服务时,有一条重要原则是值得一提的,在点击一个链接之前用户应该对它的去处有一个大概的了解。例如,当看到“用户文档”的链接时,明显应该是链接到用户文档,而不是开发者文档。运作一个项目一方面是为了提供信息,但同时也是提供舒适。当用户和开发者们正在犹豫要不要加入时,你应该在预期的地方用一套肯定性的标准来使他们安心。它表明项目有统一的管理,已经预估到了人们可能提出的问题,并且致力于在只花费提问者最少的精力的前提下来解答这些问题。通过显现这种充分准备的氛围,该项目发出了一个信息:“如果加入,你的时间不会被白白浪费,”而这正是人们想听到的。

但首先环顾四周

开始一个开源项目之前,给你一个重要的告诫:

一定要找找看是否有一个现存的项目已经做了你想做的。有很大的几率有人早于你已经解决了你想解决的问题。如果他们已经解决了它,并且在一个自由许可证下发布了他们的代码,那今天你就没有必要重新发明轮子了。当然有例外:如果是为了练习才开始一个项目,那现有的代码对你没用;或者你脑中的计划非常特别,你肯定不会有其他人有同样的想法,那你也不妨试试看。但总的来说没有理由不先看一看,而收获总是很大。如果常见的互联网搜索引擎发现不了什么,试试在http://freshmeat.net/(一个开源项目的新闻站点,有关它的更多介绍将在后面提到)和http://www.sourceforge.net/上找找看,同时自由软件基金会有一个自由软件的目录在http://directory.fsf.org/

即使你找不到跟你的想法一模一样的项目,你也许能找到十分接近的,然后加入这个项目为它增加功能比你自己从零开始一个项目要更有意义。

从你所拥有的开始

你环顾了四周,没找到真正适合你的软件,因而决定开始一个新的项目。

现在应该做什么呢?

开始一个自由软件最难的部分是将个体的设想转化传达给公众。你或是你的团体也许对要做的事情已经十分明了,但是将这一目标清楚地传达给世界还需要付出一番努力。然而,那是必须花时间做的事情。你和其他的创建人必须决定你们项目的作用—也就是说,划定项目的范围,做什么,不做什么—然后撰写一份项目任务陈述。这部分通常不太难,但有时候能暴露出一些有关项目本质的臆想,甚至于分歧,那也没关系,现在解决这些问题总比拖到以后好。下一步就是将项目打包展示给公众, 而那纯粹是单调乏味的工作。

之所以这样说是因为打包的工作就是把大家都已经知道的东西组织和编辑成文件—这里所说的“大家”指的是到目前为止参与项目工作的人。因此,对于那些做这项工作的人来说,没有什么立竿见影的好处。他们并不需要一个README来了解整个项目的概况,也不需要一个设计文件或是用户手册。他们不需要仔细排列好的,与非正式而又普遍采用的软件源码发布方式相一致的代码树形图。对他们来说,无论代码怎么安排都没问题,因为他们已经对此十分熟悉,只要源码能够运行,他们就知道怎么用。甚至于,项目最根本的设计设想没有做成文件对他们来说也是无关紧要的;因为他们对那一方面也很熟悉了。

然而,新参与的人需要这些东西。好在他们并不是在一开始就需要全部的资料。在一个项目公之于众之前,你不必提供每一个有关的细节。在一个理想的世界里,每一个新的开源软件项目在开始的时候就具备了一个详细的设计文件,一套完整的用户手册(对已经计划好但还未实施的特性有特别的标识),漂亮地而又可移植地打好了包的代码,并且还可以在任何电脑系统平台上运行等等。然而在现实当中,做好上述各项工作是非常耗费时间的,可是一旦项目启动之后,这些工作可以指望一些自愿人员协助完成。

重要的必须做好展示这一步,以便新的参与者能够顺利通过开始时因对项目不熟悉而造成的障碍。设想自举过程中的第一步,就是将项目启动所需的能耗降到最低点。我听说过人们用切入能耗这个词来形容这一开端:即一个新的参与者在收获之前所必须付出的能量。一个项目的切入能耗控制得越低越好。你的首要任务就是将切入能耗降低到能够鼓励人参与项目工作的水平。

以下各小节分别描述了开始一个新项目的一个重要的方面。排列顺序大致是按照一个新的访问者将遇到的情形安排的,当然你在实际操作时可以不按照这个顺序进行。你可以将它们看作是一个检查列表。当你开始一个项目时,只要一一检查,确保每一步骤都做到了,或者在你省略某一部分时,至少你对将来可能出现的后果有把握就行了。

选择一个好名字

设想你是另外一个人,恰好听说过你的项目,或者是是在搜索一个软件来解决某个问题时碰巧看到了你的项目。他首先看到的是项目的名字。

一个好名字不会自然而然地使你的项目成功,而一个不好的名字也不会终结你的项目—当然了,一个真正糟糕的名字也许会,但是让我们首先假定谁也不会迫不及待地让自己的项目失败吧。确实,一个不好的名字会延缓他人接受该项目的速度,要么是因为人们不会认真对待它,要么是因为人们很难记住它的名字。

一个好名字:

  • 告诉人们有关项目性质,或至少名字与性质是明显相关联的一些概念,这样人们看到名字时就知道了项目能做什么,那么人们以后便很容易想起这个名字。

  • 便于记忆。在此,我们必须承认英语实际上已成为网络默认语言这一事实。“便于记忆”就意味着“便于能阅读英语的人记忆”。例如,某一非英语发音的双关语对于该语言之外的许多能阅读英语的人来说是很难理解的。要是这个双关语特别精彩并且令人难忘,那或许值得一试;但必须记住,这个名字在许多人的脑海里并不会产生在母语人士身上所有的效果。

  • 不与另一个项目重名,也不侵犯任何商标权。这既表现职业美德,也是良好的法律意识。你要避免制造身份混乱。即便没有不同的东西重名的现象,我们现在要搞清楚网络上已有的东西已经很不容易了。

    在前面the section called “但首先环顾四周”里提及的资料有助于你发现是否另一个项目已经采用了你正在考虑的名字。免费的商标搜索见http://www.nameprotect.org/http://www.uspto.gov/

  • 尽可能成为.com.net、以及.org顶级域中的一个域名。你应该选择其中的一个,或许是.org吧,作为项目正式的网址;而另外两个网址都转发到前一个,这还可以防止其他人用项目的名字制造身份混乱。即使你打算将项目放在其它的网站空间上,(见the section called “包装主机”),你仍然可以注册自己项目的域名,而转发至你存放项目的主页上。对用户来说,使用一个容易记忆的URL是十分有帮助的。

有一份清楚的使命陈述

人们找到了项目的网页之后,下一步就要看一份简短的项目描述,即使命陈述,以便(在30秒之内)决定他们是否对该项目有兴趣并获取更多信息。因此,这份使命陈述必须放在首页显著的位置,最好是紧贴着项目名字的下方。

使命陈述必须具体,紧凑;而最重要的是简短。以下是一个很好的例子,来自http://www.openoffice.org/

创建一个以社区为基础,领先的国际化办公室套件,能够在所有主要的平台上运行,并借基于API和XML文件格式的开放组件,提供对所有功能和数据的接入性。

这份使命陈述仅仅用了简短的几句话,通过大量依赖读者已有的知识明白无误地传达了所要传达的信息。 “以社区为基础”表明该软件不受任何一家大公司控制其开发;“国际化”指的是该软件允许人们在本地及多种语言环境下工作;“所有主要的平台”说的是该软件可移植到Unix,苹果和视窗操作系统。其余的文字则说明开放接口以及易读的文件格式都是该软件目标中重要的组成部分。这份使命陈述并没有在字面上告诉读者它旨在成为微软Office的开源替代品,但是人们从字里行间便能看出它的含义。乍一看,这份使命陈述似乎有些空泛,但实际上界定得相当明确:“办公室套件”对那些熟悉这个软件的人来说是非常具体的东西。在此,读者已有的知识(这里指的是读者有可能对微软Office软件的了解)又一次用来把使命陈述变得简洁明了了。

一份使命陈述的性质不单单是由它所描述的软件决定的,而在一定程度上得看是由谁来写的。例如,OpenOffice.org使用"以社区为基础"这个词是很有道理的,因为这个项目最初是由Sun Microsystems发起,而至今仍主要是由这家公司赞助的。在其使命陈述中使用"以社区为基础"这几个字,Sun表明它对一些担心该公司有可能试图垄断开发这一软件的忧虑是有敏感度的。这样的处理方法,即表明对一个有可能出现的潜在的问题有意识,就给将来完全避免这个问题的出现奠定了很好的基础。话又说回来,如果项目并非由一家大公司赞助,那或许根本不需要这样的词语;说到底,社区开发已经成为今天的模式了,因而没有理由要特别将那样的词语写在使命陈述中。

声明项目是自由软件

看过使命陈述之后仍对项目有兴趣的人自然想要了解更多的情况,或许要看一看用户文件和开发人员文件,最终可能下载一些东西。但在做这些事情以前,他们要确定这是一个开源项目。

网站的首页必须清清楚楚地写明这是一个开源项目。这看起来好像无需加以强调,但是你会惊讶有多少项目忽略了这一点。我见过不少自由软件网站,其首页不但没有说明该软件是在哪一个自由许可证下发布的,而且根本没在首页表明这是一个自由软件。有时候这一至关重要的信息被次要地放在了下载页,或是开发人员页,或是其它的一个需要多点击一次鼠标才能看到的一个地方。在一些极端的例子中,网页上哪儿都找不到自由许可证—只有下载软件打开之后才能看到。

别犯这个错误。这一忽略有可能让你失去许多潜在的开发人员和用户。务必在首页,也就是使命陈述的正下方,声明该项目是“自由软件”或是“开源软件”,并注明确切的许可证。有关选择许可证的快速指南,见本章后面的the section called “选择许可证并应用”,而有关许可证问题的详细讨论见Chapter 9, 许可证,版权和专利

至此,我们假想中的访问者已经决定—或许在随后的一分钟之内—他打算至少再花5分钟的时间研究一下这个项目。下面几个小节要描述他在之后的5分钟里将遇到的情形。

特性和需求列表

你应该列出一个简短的清单,说明软件支持的各种特性(如果某些特性还未完成,也可以列出,但是在旁边注明计划中”或“建设中”),以及运行该软件所要求的系统环境。列这份清单时,你只要设想一个人请你简短地介绍这个软件的特性/需求是什么。通常,那只是按照逻辑对使命陈述作进一步的扩充。例如,使命陈述可能写的是:

创建一个全文索引器并配备丰富API的搜索引擎,用于编程人员搜索大批量文本文件。

特性和需求清单将列出更详细的内容,对使命陈述的范围加以说明:

特性:

  • 搜索纯文本,HTML和XML文件

  • 字或词搜索

  • (计划中)模糊匹配

  • (计划中)增量更新索引

  • (计划中)索引远程站点

需求:

  • Python 2.2或更高版本

  • 足够的硬盘空间以储存索引(大约原文件大小的2倍)

有了这样的信息,读者便能很快地决定这个软件是否适用于他们,也可以考虑是否以开发人员的身份参与其中。

开发状态

人们总是希望了解一个项目的状况。对新的项目,他们想知道项目的承诺和现实之间存在着多大的距离。对成熟的项目,他们想知道维护得如何,新发布的频率怎样,以及对Bug报告反应的及时性等等。

要回答这些问题,你应该建立开发状态页,列出项目的近期目标和需求(例如,需要具备某方面专长的开发人员)。开发状态页也可以列出过去发布的记录,其中包含特性清单,以便访问者了解项目是如何定义“进展”的,并根据这一定义了解项目进展的速度。

别因为你的项目看起来没准备好而感到害怕,也不要向夸大开发状态的诱惑妥协。谁都清楚软件是分阶段开发的产品;你不必觉得难以开口说出:“这是仍带有Bug的alpha软件,它可以运行。而且至少有时候能正常工作,但你使用这个软件就得自己承担风险。”这类语言不会吓跑你在这个阶段需要的开发人员。然而,对于用户来说,最糟糕的事情莫过于在软件准备好之前就吸引用户。一旦冠上了稳定性差或是Bug多多的名声,软件就很难再正名了。采取保守的策略对长远的目标是非常有益的;软件的稳定性超出用户的预期总比达不到用户的期望好得多,而给用户惊喜就会给产品带来最佳口碑。

下载

应该可以以标准格式下载软件的源代码。在一个项目刚起步时,二进制(可执行的)软件包不是必要的,除非该软件的构建和依赖要求相当复杂,以至于仅仅运行该软件就需要大量的人力投入。 (如果情况是那样的话,该项目也将很难吸引开发人员的参与!)

发行机制应该尽量做到方便,标准化以及清楚无误。假如你要根除一种疾病,你分发的药物不会是需要一种非标准化的注射器来操作的吧。同样的道理,软件应该与标准化的构造和安装方法相一致;一个软件距离标准化越远,用户和开发人员放弃该软件并且一头雾水地离开的可能性就越大。

那听起来是显而易见的道理,但是许多项目往往等到很晚的时候才动手解决标准化安装程序,因为他们总是告诉自己这一步什么时候都可以做:“等到代码接近完工的时候再来解决这些所有的问题吧。”殊不知在拖延完成软件建设和安装程序这类枯燥工作的时候,他们实际上是在推迟完成代码的时间—因为他们让一些本来可以为软件编程做贡献的开发人员失去了兴趣。最糟糕的是,他们根本就不知道他们失去了那些开发人员,因为那是一连串无果而终的一个过程:某人拜访了一个网页,下载了软件,试图参与构建,失败了,放弃而离开了。除了拜访者本人以外,谁会知道发生了这一切?项目参与者中谁也不会意识到某位拜访者的兴趣和良好意愿在悄无声息中便被扼杀了。

枯燥但具有高回报的工作应该尽早完成,而通过良好包装便能够大大降低进入项目障碍的工作显然是具有很高的回报率的。

当你发布一个可以下载的软件包时,至关重要的一点是给予这一次发布一个独一无二的版本号码,以便人们对两次发布加以比较,从而了解哪些东西被替代了。有关版本编号的详细讨论见the section called “版本号”,而构建和安装程序标准化的详细内容见the section called “打包”以及Chapter 7, 打包、发布和日常开发

版本控制和Bug跟踪访问

下载源码软件包对于只想安装和使用软件的人来说足矣,但对于想要解决bug问题或增加新特性的那些人就不够了。尽管每夜源代码快照会有些帮助,但是对一个活跃的开发社区来说,仍然不够细致。人们需要实时进入最新的代码系统,而能够实现这一点的途径便是使用版本控制系统。如果一个人在匿名情况下便可以获取受版本控制的代码,那就意味着该软件对用户和开发人员昭示:项目正努力为人们的参与创造条件。要是你不能马上提供版本控制,也应该出一个声明,告知人们你会尽快那样做。有关版本控制的基础架构详见Chapter 3, 技术基础设施中的the section called “版本控制”

对于项目的Bug跟踪系统来说,也是同样的道理。Bug跟踪系统之所以重要不只因为它对开发人员十分有用,而且对关注项目的人来说是一种标志。在许多人看来,一个可以进入的Bug数据库是一个项目是否严肃认真的重要标志之一。再者,数据库中的Bug数量越多,项目看起来越好。这听起来似乎有悖常理,但是请记住Bug数量的记录实际上取决于三个因素:软件中存在的Bug绝对数量,使用该软件的用户人数,以及用户记录新发现的Bug的方便程度。在这三个因素当中,后两个比前一个重要得多。任何具有一定规模和复杂性的软件基本上都存在一定数量有待被发现的Bug。真正的问题是,一个项目在记录和优先解决Bug问题方面做得有多好?如果一个项目有一个较大而又维护得很好的Bug数据库(意思是bug问题得到及时地回应,重复bug被合并等等),那么这个项目就会比那些没有Bug数据库,或者Bug数据库里空空如也的项目给予人们更好的印象。

当然,如果你的项目刚刚起步,那么Bug数据库里就只有为数不多的Bug,而对此你也没有什么办法。但是如果在开发状况页强调项目仍处于初创期,且人们看到bug数据库里大多数的文档都是近期建立的,他们便可以由此推断出该项目仍然有良好的解决,也就不会因为看到相对较低的已经记录的Bug绝对数量而产生不适当的警觉。

请注意Bug跟踪系统的用途不止追踪软件的Bug,而且也用来跟踪扩展请求,文档变更,待解决的任务,以及其它一些问题。运行一个Bug跟踪系统的详细内容见Chapter 3, 技术基础设施中的the section called “Bug跟踪”,所以在此我就不赘述了。重要的是,Bug跟踪一定要显示出来,而且要确保项目的首页上便能看到这一点。

沟通渠道

项目的访客通常都希望知道如何能联系上参与项目的有关人员。提供邮件列表地址、聊天室、IRC频道、以及任何其它形式的论坛,以便其他参与项目的人同样可以联系上。告诉人们你和项目的其他有关人员都在邮件列表上,因而人们便知道他们有途径将回馈传递给开发人员。你在邮件列表上并不意味着你承诺回答所有的问题,也不等于你要满足所有人提出的有关特性的要求。长远来看,大多数用户或许根本从不参与论坛,然而,如果他们知道他们需要的时候可以那样做,那对他们就是一种欣慰。

在项目开发初期,没有必要将用户论坛与开发人员论坛分开。更好的办法是让所有与软件有关的人员在“同一间屋子”里进行交谈。在早期使用软件的人当中,开发人员与用户之间的界线通常很模糊;不是没有界线,但是开发人员与用户之间的比例在项目早期远远高于后面的阶段。尽管我们不能假设每一位早期与项目有关的人都是想要介入软件开发的编程人员,但是我们可以肯定他们至少很有兴趣地关注项目发展中进行的讨论,并了解项目发展的方向。

由于本章只讨论项目的初建,所以在此我们只要说明有必要建立以上所说的交流论坛就行了。稍后,在Chapter 6, 交流中的the section called “处理成长”,我们将讨论在什么地方以及如何建立这样的论坛,及可能需要的协调和其它方面的管理,另外,在时机成熟的时候,如何分离用户与开发人员的论坛而避免造成无法逾越的鸿沟。

开发者指南

如果有人考虑参与项目,她会寻找开发者指南。与社会性文档相比,开发者指南通常没有很多的技巧:只需要解释开发者之间,以及与用户之间如何交互,以及如何最终完成任务。

这部分的细节可以看Chapter 4, 社会和政治的基础架构中的the section called “写下所有的内容”,但开发指南的基本元素包括:

  • 与其它开发者交流论坛的链接

  • 报告Bug和提交补丁的指导

  • 说明进行开发的方法—项目是仁慈专制、还是民主的、还是其它。

对于“专制”这里没有任何轻蔑的含义。如果存在一个开发者对所有变更拥有否决权,这完全没有问题。许多成功的项目以这种方式进行。关键是项目能够说出来它的做法。一个假装民主的独裁会让人厌恶;如果独裁者只要有能力并被信任,一切都会很好。

完整的开发者指南实例可以看http://svn.collab.net/repos/svn/trunk/www/hacking.html,或者是更加关注管理和参与精神,而较少关注技术事务的http://www.openoffice.org/dev_docs/guidelines.html

为程序员提供单独的软件指导的问题会在本章后面的the section called “开发者文档”讨论。

文档

文档非常必要。需要有一些用户可以读的内容,即使它非常基本和不完整。在初期这样做确实是一件“苦差事”,经常成为新开源项目的第一个失败之处。提出使命声明和特性列表、选择一个许可证、概述开发状态—这都是相对的小任务,完成后通常可以不必返回继续工作。而另一方面,文档永远没有真正的结束,这可能也是人们总是延迟开始文档的一个原因。

一个隐伏的事实是,文档对于编写者的功用与阅读者的功用是相反的。对于初始用户来说最重要的是基础文档:如何快速配置软件,软件如何工作的概述以及一些常规操作的指导。而这些通常是编写者所非常熟悉的内容—以至于很难从读者的角度看问题,因而他们不会费力去表述一些非常明显而不值一提的步骤。

对这个问题没有神奇的解决办法。必须有人坐下来写好内容,然后交给普通的用户来验证它的质量。使用简单和容易编辑的格式,例如HTML、纯文本、Texinfo或一些XML的变种—便于在激励下可以轻型和快速的作出改进。这不仅是为了消除最初作者进行增量改进所带来的代价,也是为了希望修改文档的新加入者。

一个保证基本初始文档完成的方法是预先限制其范围。这种方法至少不会让我们感觉是在完成一个开放结尾的任务。一个经验是它必须达到下面的最低标准:

  • 告诉读者他们所需的技术技能。

  • 清楚和完整的描述如何配置软件,并在文档的开头部分告诉用户如何运行确认安装成功的诊断测试或简单命令。启动文档有时候比使用文档更重要。一个人投入到软件安装和开始的努力越多,她就越有可能持续的搞明白没有很好文档描述的高级功能。当人们放弃时,他们会很早就放弃;因此,在早期阶段,例如安装时,需要最多的支持。

  • 提供一个普通任务的教程式的实例。很显然,不同任务的例子越多越好,但是时间有限,最好还是选择一个任务并完整的完成它。一旦人们看到这个软件可以使用,他们会开始探索其他需要的功能—如果你足够幸运,他们会自己补充文档。这将会让我们到下一点...

  • 标示文档中未完成的部分。通过向读者展示这些不足,可以实现你与他们观点的联盟。你的移情作用可以使他们恢复信心,不必为确定什么是项目最重要的事情而挣扎。这些标示不需要承诺填补这些空白的期限—它等于是合情合理的公开征集志愿者。

最后一点更广泛重要,也更实际,并可以应用到整个项目中,而不仅仅是文档中。开源领域中一个都知道的问题就是项目规范。你不必夸大项目的这种短处,你只需小心冷静的识别出需要这种规范(说明文档、Bug跟踪数据库或邮件列表讨论中都可以)的场景。就项目而言,没有人会视其为失败主义,也不会认为这是对在特定日期完成的承诺,除非项目明确作出这种承诺。因为使用软件的所有人都会发现这种不足,他们最好能在心理上做好准备—然后项目就有了解决这些问题的坚实知识。

文档的可用性

在两个地方必须有文档:在线(直接在网站上),以及软件可下载分发版本(见Chapter 7, 打包、发布和日常开发the section called “打包”)中。它必须以可浏览的形式在线,因为通常人们会在第一次下载软件之前首先阅读文档,以决定是否下载。但是也必须和软件配套,因为原则上下载中必须包括使用软件包的所有必须内容。

对于在线文档,要确定有一个指向包含完整文档的(请在链接旁注明"monolithic"或"all-in-one"或"single large page",以提醒人们知道需要更长的下载时间)单独HTML页的链接。这是因为人们经常会在整个文档中寻找特定的词汇或短语。通常是他们已经知道他们在找什么;只是记不住具体的章节。对于此类人,最郁闷的就是遇到一个目录页面、然后是指导页面、然后是安装指导等等。当页面是如此琐碎时,浏览器的搜索功能将变得毫无作用。分页的样式适合那些知道他们所需章节,或是从头到尾阅读的人。但这不是访问文档的常规方式。通常是某人已经熟悉了软件,返回来搜索特定的词汇或短语。如果未能提供一个单独的、可搜索的文档会让他们活的很辛苦。

开发者文档

开发者文档主要为了帮助程序员理解代码,从而修改和扩展软件。这与更关注社交性而不是技术性的开发者指南有些许不同。开发者指南告诉程序员如何与代码本身打交道。为了方便,这两个文档通常会整理为一份文档(例如前面提到的http://svn.collab.net/repos/svn/trunk/www/hacking.html),但是这不是必须的。

尽管开发者文档可能很有用,但也没有为了它而影响发布。只要原始作者还在而且愿意,就可以回答关于代码的问题,一开始这就足够了。实际上,反复回答相同的问题是编写这个文档的动力所在。但即使文档还没有写,坚定地参与者也依然会设法以自己的方式处理代码。驱使人们花时间研究代码基的原因是他们发现这些代码对他们有用。如果人们相信这一点,他们就会花时间去搞明白;如果他们不相信,再多的开发者文档也留不住他们。

如果你有时间为一个读者写文档,那还是写给所有用户吧。所有用户的文档,和开发者文档有同样的效果;为软件工作的程序员一定对如何使用也非常熟悉。之后,当你看到程序员反复询问相同的问题时,你就应该为他们编写单独的文档。

一些项目使用wiki作为初始文档,甚至作为他们主要的文档。在我的经验里,只有文档是被少数认可文档的组织方式和包含内容的成员编辑时,才能正常工作。更多细节在Chapter 3, 技术基础设施the section called “Wikis”

输出和屏幕截图实例

如果一个项目包含图形化的用户界面,或者生成图形和其他特别的输出,那么就应该将这些样例放到项目网站上。如果是界面,那应该是截图;对于输出,可以是截图或只是文件。但是为了迎合人们立刻满足的需要:一个单独的截图比大段描述文字和邮件列表的唠叨更让人信服,因为截图是软件能正常工作的不容争辩的证据。它可能充满bug、可能难于安装、可能文档不全,但是截图是一个人投入足够的精力,可以使之运行的证据。

还有一些东西需要放置到网站中,如果你有时间,或者如果出于某种原因而显得特别合适:一个新闻页、一个项目历史页、一个相关链接页、站点搜索特性和捐赠页等等。开始时这些都不是必要的,但将来要一直留意。

包装主机

有一些站点为开源项目提供免费的主机和基础设施:web站点、版本控制、bug跟踪、下载区、讨论论坛和定期备份等等。具体细节站点之间各不相同,通过使用这些站点,你可以免费得到基础服务。但是很明显你也同时放弃了通过用户经验,来进行细化控制的能力。主机服务决定了站点运行的软件,也控制了或至少影响了项目站点的感观。

Chapter 3, 技术基础设施the section called “包装主机”是包装主机优缺点的详细讨论,也有提供这种服务的站点列表。

选择许可证并应用

这部分是关于选择许可证的快速粗糙指南。阅读Chapter 9, 许可证,版权和专利可以理解不同许可证的法律含义细节,以及这些许可证如何影响人们将你的软件与其他自由软件混合的能力。

确实有大量可供选择的许可证。其中大多数我们这里不必讨论,因为他们通常是为了满足公司或个人的特定法律需求,不会适合你的项目。我们会限制为大多数常见的许可证;大多数情况下,你会从其中选择一个。

“可以做任何事情的”许可证

如果你能够接受你的项目代码会潜在的使用到私有程序中去,可以选择MIT/X-样式的许可证。这是一些最小许可证中最简单的一种,只保留署名版权(实际没有限制拷贝)并指明代码没有任何保证。细节见the section called “MIT / X Window System License”

GPL

如果你不希望你的代码在私有程序中使用,可以使用GNU的通用公共许可证。GPL可能是当世最广泛公认得自由软件许可证。在本质上是一个巨大的优势,因为许多潜在的用户和贡献者已经对此许可证十分熟悉。更多细节看Chapter 9, 许可证,版权和专利the section called “GNU General Public License”

如何为你的软件应用许可证

一旦你选择了一个许可证,你必须在项目首页注明。你不必引入许可证的实际文本;只需要提供许可证的名称,并提供到完整许可证文本的链接。

这告知公众你希望软件按照何种许可证发布,但是对于法律目的还不足够。这个软件本身必须包含许可证。一个常见的做法是将许可证全文保存到一个叫做COPYING(或LICENSE)文件中,其中包含了许可证的全文,然后还要注意在每个源文件的开头,注明版权日期、所有者和许可证,以及何处可以找到版权全文。

这个模式也有许多变种,所以我们这里看一个实例。GNU的GPL说可以在每个源文件的开头放置如下的提醒:

Copyright (C) <year>  <name of author>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

并不是说随程序收到的许可证拷贝在文件COPYING中,而是它通常放置在那个地方(你可以在上面的声明中直接注明位置)。这个模板给了获取许可证版权的地理地址。另一个常见的方法是提供包含许可证的网页链接。只要使用你的判断并指出你认为版权能够永久保存的位置,也可以是你项目网站的某个位置。一般来说,你在每个源文件放置的通告不会和上面这个完全一样,只需要其包含版权持有者和日期,以及版权的名称,并明确指明完全许可证的位置即可。

设置风格

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

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

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

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

通过特定实例,你可以设置好的先例。这不必是一个完整的列表,但是通过尽早设置这样的协作情绪的方法,可以大大的帮助项目。从物理上讲,每个开发者都在自己的房间独立工作,但是你可以设法让他们感觉是在一个房间一起工作。他们这样的感觉越多,就会在项目上花费更多的时间。我选择了这些例子,因为这些实例来自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, 许可证,版权和专利讨论了当公开的私有代码基包含其它组织编写或“拥有的”软件时所必须承担的法律义务。

通告

一旦项目可以展示了—不必完美,只要能看—就可以将其通知给世界了。这是一个非常简单的过程:来到http://freshmeat.net/,在顶端的导航栏点Submit,然后输入你的新项目的通告。Freshmeat是一个大家关注新项目通告的地方。你只需要在那里用项目新闻抓住一些眼球,就会众口相传。

如果你知道某个邮件列表或新闻组会对你的项目合题或感兴趣,那么请在那里通告,但请注意,一个论坛只有一个通告,将人们引向项目本身的论坛,进行后续的讨论(通过设定Reply-to头)。这种发布一定要简短扼要:

To: discuss@lists.example.org
Subject: [ANN] Scanley全文索引项目
Reply-to: dev@scanley.org

这是关于Scanley项目的一次性公告,Scanley是一个包含丰富API的开源全
文索引和搜索引擎,主要为程序员提供对于大组文件的搜索服务。Scanley
现在是可运行的代码,正在进行活跃的开发,征集开发者和测试者。 

主页: http://www.scanley.org/

特性:
   - 查找纯文本、HTML和XML
   - 单词和短语查询
   - (计划) 模糊匹配
   - (计划) 增量更新索引
   - (计划) 索引远程网站

前提条件:
   - Python 2.2或更高
   - 包含索引的足够空间 (大约原始数据的2倍大小)

更多信息,请访问scanley.org。

谢谢,
-J. Random

(有关后续发布版本,以及项目其他事件的通告建议,请看Chapter 6, 交流the section called “公开性”。)

对自由软件世界是否应该以一个可执行的代码作为开始,以及在设计/讨论阶段就进行公开是否有益还存在着争议。我过去认为从一个可执行的代码开始是非常重要的因素,这是成功项目和玩具的重要区别,慎重的开发者只会加入有一定事实的软件。

但也有例外。在Subversion项目,我们从设计文档、一组核心的感兴趣和紧密联系的开发者、许多热闹的介绍和能运行的代码开始。完全出乎我的意料,项目从一开始就获得了活跃的参与者,当我们可以运行什么时,已经有不少志愿开发者已经深入参与进来。Subversion不是唯一的例子;Mozilla项目也是从不能运行的代码开始,现在成为了成功和流行的web浏览器。

面对这种证据,我必须回过头来看可运行代码是启动项目必要条件的断言。可运行程序仍然是成功的最重要基础,一个好的经验法则是直到可以运行再开始公告项目。然而,有一些环境下,尽早通告是有意义的。我想这时起码要有完成良好的设计文档,或其他代码框架—当然,这也许需要根据公共反馈调整,但是要有一些实际的东西,比好的意图更确切地东西,让人们可以动动牙齿。

无论你何时通告,不要指望立刻有一大堆志愿者会到来。通常情况下,通告的结果是得到很少随意的询问,以及一些人加入你的邮件列表,除此之外,一切如常。但随着时间的流逝,你会逐渐发现代码贡献者和用户参与的增加。通告仅仅是播下种子。消息的传递需要很长时间。如果项目持续回报参与者,这个新闻就会传播,因为人们喜欢分享他们所发现的好东西。如果一切都好,指数级交流网络的动力会慢慢将项目改变为复杂的社区,你不必再知道每个人的名字,也不必跟踪每一次对话。下一章我们将讨论在这个环境下如何工作。



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

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

Chapter 3. 技术基础设施

自由软件项目依赖于选择性捕获和信息集成的技术。对这些技术的使用越是熟练,并说服别人去使用这些技术,你的项目就越成功。随着项目的成长,这一点愈发正确。好的信息管理系统应该能够防止开源项目在布鲁克法则的重压下崩塌[12] ,也就是说向一个已经延期的项目增加人力,只能使项目延期更多。佛雷德·布鲁克观察到,项目的复杂性同参与人员数量的平方成正比。当项目中只有少数几个人时,大家可以容易的互相交谈,但当有上百人参与时,不可能让每个人都能知道别人正在做什么。如果说优秀的自由软件项目的管理是让每个人都感觉是在同一个屋子里共同工作,很明显问题在于:当在一间拥挤的房间内,在同一时刻每个人都想发出声音,会发生什么?

这不是一个新问题。在现实中的拥挤房间中,解决方案是会议程序:我们需要正式的指导规则:包括如何在一个大型团队中进行即时的讨论,如何保护重要的异议不会在一片“我也是”的回复中淹没,如何形成小组委员会,如何识别出何时作出决定等等。会议程序的一个重要组成部分是指明团队如何同它的信息管理系统互动。有些评论“为了被记录”而存在的,有些则不是。记录本身经常是被直接处理的,不能根据字面意义去理解,而是代表了团队已经确立达成共识。记录并非一成不变,为不同的目的会有不同的形式。它可以包括个人会议记录、每次会议的完整记录、摘要、议程及其注解、委员会报告,来自未出席通信者的报告,活动项目列表等等。

因为互联网并不是一个真实的房间,所以我们也无须担心去复印诸如让部分人在别人讲话时保持安静之类的议会程序。但当它和信息管理技术接合时,一个运作良好的开源项目就会是打了兴奋剂的会议程序。由于开源项目中的交流都是通过书写方式完成的,由此发展出了复杂的系统:为了恰当导向和标记数据;为了避免会造成误解的重复;为了储存和检索数据;为了纠正错误和废弃的信息;以及为了在发现不相关信息的新关系时进行关联。开源项目中的活跃参与者已经将掌握了其中的很多技术,并且经常为了确保信息被正确的导向而进行复杂的手工任务。但是所有的努力都是依赖于复杂的软件支持。交流媒体应该尽可能地依靠自身完成发送、标签和记录工作,应该确保人尽可能方便地得到这些信息。当然在实际中,在整个过程中的很多方面还是需要人的干预,并且重要之处在于软件使得这种干预也是方便的。但总得来说,如果人能确保首次进入系统时信息的导向和标签都是正确的,软件应该被配置成可以充分利用这些元数据。

此章中的建议都是非常务实的,都是基于明确的软件和使用模式的经验。但这里不仅仅是教授实用的技术。而是通过许多小范例来演示一种总体态度,这种态度可以最大程度的促进你项目中的好的信息管理。这种态度包含了技术技巧同人力技巧的结合。并且技术技巧是关键,因为当新的需求出现时,信息管理软件总需要配置,以及一定量的持续维护和调整(例如,关于如何处理项目成长的讨论参加本章后面的the section called “Bug跟踪的预过滤”)。人力技巧也是不可或缺的,因为人类社区也需要维护:如何利用这些工具的优势有时候不是立刻就很明显,在有些项目案例中甚至有冲突的习惯(例如,参见the section called “邮件列表”中的关于在外发的邮件列表通告中设置Reply-to头的讨论)。应该鼓励项目相关的每一个人在正确的时间、正确的地点尽自己的职责来保持项目信息组织的良好。贡献者参与的程度越深,就越能预期她能学习更复杂和专业的技术。

信息管理没有现成的解决方案。有着众多的不确定因素。你可能好不容易才把所有事情都按照自己的意愿完成配置,并且社区的大多数人参与进来,但随着项目的成长让某些实践不能扩展。或者本来你的项目正在稳步发展,技术基础架构也能使开发者和用户的社区关系融洽,但突然某些人出现,发明了一个全新的信息管理服务,很快新来的会质问为何你的项目不用它—例如很多在维基(参见http://en.wikipedia.org/wiki/Wiki)发明之前建立的自由软件项目就正面临这一问题。很多问题需要决断,比如权衡生产信息的方便性还是消费信息的方便性,或者权衡花在配置信息管理软件上的时间与其为项目带来的益处。

小心过度自动化的诱惑,请自动化那些真正需要人们关注的东西。技术基础架构是重要的,但推动一个自由软件项目运转的是参与的人的意愿—用智慧的方式表达的意愿—通过人的参与。技术基础架构只是为人门达到这个目标提供便利。

一个项目需要什么

大部分开源项目至少提供了最低限度的标准工具用于管理信息:

网站

主要是一个集中将项目信息发布给公共的单向渠道。网站也可以作为其他项目工具的管理界面使用。

邮件列表

通常会是项目中最活跃的通讯手段,是“可记录的媒介”。

版本控制

让开发者可以方便地管理代码的变更,包括回复和“变更转运”。让每一个人能看到代码的变化。

Bug跟踪

使开发者可以追踪他们正在工作的内容,互相协调,以及计划发布。让每个人都能查询Bug的状况并且记录特定Bug的信息(例如重现方法)。不仅能用于对bug的追踪,而且能用于任务、发布和新特性等等。

即时聊天

一个可以快速和方便的进行讨论和问答的地方,缺点是并不总是能完整地归档。

这个工具集中的每个工具满足了不同的需要,但它们的功能都是相关的,这些工具必须能协同工作。下面我们将检验它们怎样做到这一点,而最重要的是如何让人们使用它。网站将放在最后讨论,因为它更多的是扮演其他组件黏合剂的角色,而不是工具本身。

通过使用包装主机你也许能避免很多选择工具和配置的头疼事,包装主机是一个提供预包装,模板化的网页区域,以及可运行一个自由软件项目的所有工具的服务器。关于包装主机优缺点的讨论可以看本章后面的the section called “包装主机”

邮件列表

邮件列表有如项目交流的面包和黄油。如果用户在除了网页之外的地方浏览,最有可能是项目的某一个邮件列表。不过在体验邮件列表本身之前,他们将接触邮件列表的界面—也就是加入列表(“订阅到”)的机制。由此带来了邮件列表的#1法则:

不要试图手工管理邮件列表—让软件来做。

放弃这一点充满诱惑,开始时就设置软件来管理邮件列表看起来有些小题大做了。手动管理小型低流量的邮件列表似乎是理所当然的:你只需设置一个指向自己的订阅地址,然后当有人向其发送邮件,你把他们的邮件地址加入(或是删除)一个保存了所有地址的文本文件中。还能比这更简单的吗?

问题在于,人们所期望的好的列表管理并非是如此简单。它不仅只是按用户的需求订阅或是退订而已。还包括防止垃圾邮件,提供发送邮件列表摘要而不是每条信息都发送的的形式,通过自动应答机提供标准列表和项目信息,以及许多其他事情。一个由人监控的订阅地址只能支持最小数量的简陋功能,而且在可靠性和反应速度上也不如软件。

现代化的列表管理软件至少提供了以下这些特性:

同时通过邮件和网页订阅

当用户订阅一个列表时,她应当能立即收到一条表示欢迎的回复,告知她订阅了什么,下一步该如何使用邮件列表软件,并且(也是最重要的)告知如何退订。当然,这个回复还应该能被定制地加入诸如项目的站点,常见问题和回答等项目的特定信息。

可选择摘要或是每个信息单独发送的订阅模式

选择摘要模式,订阅者每天会收到一封包含当天所有列表活动的邮件。对那些并不紧跟列表,不会参与讨论的用户,摘要模式更合适他们,因为这允许他们在任何时刻一次检索所有的主题,避免了随机时间到来邮件的分神。

审核特性

在邮件发送到整个列表之前的“审核”是检查邮件以确保:a) 不是垃圾邮件,以及b) 符合主题。审核必须有人参与,但软件能很大程度的使之变得容易。后面还有关于审核的更多内容。

管理界面

不管一些其他的作用,这个特性至少能让管理员轻松地进入列表并删除一个废弃的地址。当一个订阅者的地址开始自动地对每一封列表邮件发出“我已不在这个地址”的回复时,情况就变得非常紧急了。 (有些邮件列表管理软件甚至能依靠自身捕获这种情况,并自动完成退订。)

邮件头处理

许多人在自己的电邮客户端中设置了精密的过滤和回复规则。为了利用这些优势,邮件列表管理软件能为这些人添加和处理某一种标准的邮件头(更多详细内容参阅下面)。

归档

发往被管理列表的所有邮件都会被保存,并且能够通过网页访问;有些邮件列表软件以可插入的形式提供外部归档工具如MHonArc(http://www.mhonarc.org/)的接口。就像Chapter 6, 交流the section called “归档的显著使用”所讨论的,归档很重要。

所有这些的要点是为了强调邮件列表管理是一个复杂的问题,已经耗费了许多思考,而且大多数已经被解决。你确实无须成为一个专家。但你应该知道,虽然其中大部分已被解决,但总还有进步的空间,在运作一个自由软件项目的过程中列表的管理将一次次地占据你的注意力。下面我们将回答几个有关邮件列表配置的最常见问题。

垃圾邮件防护

这些话从动笔到出版的这段时间里,因特网上的垃圾邮件问题很可能又严重了一倍—或至少给人的感觉是如此。有那么一段时间,就在不久之前,当时可以完全无须任何的垃圾邮件防护措就能运转一个邮件列表。偶尔会有那么几封,只能构成小小的烦恼。好日子已经一去不复返了。现在如果邮件列表没有垃圾防护措施,很快就会被乱七八糟的邮件淹没,以至于不可用。必须实施垃圾防护。

垃圾防护分为两种类型:防止垃圾邮件出现在你的邮件列表中,防止你的邮件列表成为垃圾制造者地址收割机获取新邮件地址的一个源。前者更重要,所以我们首先研究。

过滤邮件

垃圾邮件防护有三种最基本的技术,大部分的邮件列表软件都会提供,最好能串联使用:

  1. 只自动允许来自列表订阅者的邮件。

    只要使用就有效,因为通常只需要在邮件列表软件的配置中做一点小小的改动,所以只需要很少的管理投入。但注意,那些不能自动认可的邮件不能简单地销毁了事。相反,必须传递给审核程序,有两个原因。首先你希望允许非订阅者的邮件。仅仅想问一个问题或是提供建议的人,不应该只为了发一封邮件而需要订阅整个列表。其次,有时甚至订阅者都有可能从非订阅时用的地址发出一封邮件。邮件地址不是鉴别人的可靠方法,它不该被如此对待。

  2. 通过垃圾过滤软件过滤邮件。

    如果邮件列表软件允许(大部分是),你能用垃圾过滤软件来获得过滤后的邮件。由于在垃圾制造者和过滤器编写者之间进行着一场永不停息的军备竞赛,自动垃圾过滤从来不是也永远不会是完美的。然而,它可以大大减少进入审核队列的邮件数量,因为更长的列表需要更长的人工处理时间,一定程度的自动过滤总是有益的。

    这里没有空间来详细地介绍垃圾过滤的设置。你应该查阅你的邮件列表软件的文档(见本章后面的the section called “软件”)寻求答案。列表软件通常会有一些内置的垃圾防护功能,但也许你想要添加一些第三方的过滤器。推荐两个我有良好体验的软件:SpamAssassin (http://spamassassin.apache.org/) 和SpamProbe (http://spamprobe.sourceforge.net/)。这并非是对众多的其他开源垃圾过滤器的不敬,其中的一些显然也是非常好的。只是这两个是我曾经亲身使用过的,并且它们让我很满意。

  3. 审核。

    由于不是列表订阅者的原因而未能自动许可的邮件,就会根据设置进入垃圾过滤软件,最后一个阶段将是审核:邮件将被发送到一个特殊的地址,那里会有人来检查和决定是许可还是拒绝。

    许可一个邮件有两种形式:你可以只是这一次接受它,或你可以告诉列表软件为这一封邮件同一发送者以后的所有邮件开绿灯。为了减少以后的审核负担,你很可能会选择后者。具体如何许可在不同的系统之间有很大的差异,但是通常的形式是向一个特殊的地址发送一条带有命令“accept”(代表这一次许可)或是“allow”(允许这次以及以后的邮件)的回复。

    拒绝通常只需简单的忽略所审核的邮件即可。如果列表软件没有收到确认有效的邮件,它不会让邮件通过并出现在列表上,所以简单地扔掉审核邮件就能达到目的。有时你还有其他选择,返回“reject”或是“deny”命令来杜绝以后来自同一个发送者的邮件进入审核程序。但这么做通常没什么意义,因为大部分需要审核处理的都是垃圾邮件,而垃圾邮件制造者不太会从同一个地址两次发出垃圾邮件。

确保审核被用在过滤垃圾邮件和明显是和主题无关的消息上,比如有时会有人意外地在一个错误的邮件列表中发送了邮件。审核系统通常给你一个直接同发送者联系的途径,但是不要用这种方式来回答属于邮件列表本身的问题,即使那些答案就在你的头脑之中。如果这么做了,将会剥夺项目社区了解人们正在问那些类型问题的具体形式,剥夺它们自己回答问题或者获得答案的机会。邮件列表审核除了严格确保列表中没有垃圾和同主题无关的邮件,没有其他了。

归档中的地址隐藏

为了防止你的邮件列表成为垃圾邮件发送者的地址源,一个常见的技术是混淆用户的邮件地址,例如通过替换

jrandom@somedomain.com

jrandom_AT_somedomain.com

jrandomNOSPAM@somedomain.com

或一些类似的明显的(对人类来说)加密。因为垃圾邮件地址收割器通常会遍寻网络—包括你的邮件列表的网络归档—它们会查找包含“@”的字符串,对地址加密是为了让人们的邮件地址对垃圾邮件发送者来说不可见或不可用。这对防止垃圾邮件发送者将邮件直接发送到邮件列表本身无用,但它可以防止直接发送到用户个人地址的垃圾邮件的增加。

地址隐藏可能存在争议。许多人很喜欢,如果你的归档不能自动支持,他们会很惊讶。还有些人认为这样太不方便了(因为人们需要在使用之前转化地址)。有时候用户断定这样做不能产生预期的效果,因为收割器理论上可以弥补任何不变的加密模式。然而,有一个实验证据可以证明地址隐藏有效的,见http://www.cdt.org/speech/spam/030319spamreport.shtml

理想情况下,邮件列表软件为每个订阅者提供选择的机会,通过特别的yes/no头,或者通过订阅者列表帐户的参数选择设置。然而,我不知道有哪个软件提供了每订阅者或每邮件的选项,因此现在列表管理员必须为所有人作出决定(假定归档程序已经提供了这些特性,就不存在这个问题了)。我倾向于适度使用地址隐藏。一些人对于将自己的邮件发布到网页上或其他收割器可能会搜索的地方会非常小心,他们会因为邮件列表归档暴露它们关心的内容而感到失望,归档用户中的地址隐藏带来的不便是轻微的,因为如果你希望联系某个人,将混淆的邮件地址恢复非常容易。但是最后还是要牢记,这是一场军备竞赛:在你阅读到本文的事以后,收割器可能已经得到了进化,能够识别大多数常见的隐藏形式,我们可以想一些其他形式。

身份和头管理

列表订阅者经常希望将来自列表的邮件存放到特定的目录,能够和其他邮件区分开。他们的邮件阅读软件可以自动检查邮件的。这个头是在邮件的顶部,用来指明发送者、接收者、主题、日期和其他邮件相关的东西。某些头是众所周知的,而且是必须有的:

From: ...
To: ...
Subject: ...
Date: ...

还有一些是可选的,尽管也是标准的头。例如,邮件不必有

Reply-to: sender@email.address.here

头,但大多数情况下都有,因为这可以保证接收者(当作者必须从一个不能接收邮件的地址发送邮件的时候这特别有用)能够联系到原作者。

一些邮件阅读软件提供了基于主题头模式的易用界面,可以用来过滤邮件。这导致人们会要求邮件列表为所有的主题提供自动前缀,所以他们可以设置的阅读器查找前缀并自动将文件归入正确的文件夹。如果原来的作者是这样写:

Subject: Making the 2.5 release.

但是列表中显示的邮件会是:

Subject: [discuss@lists.example.org] Making the 2.5 release.

尽管大多数列表管理软件提供这个选项,但我强烈反对开启这个功能。因为这个问题可以通过更自然的方式轻松解决,而且主题字段消耗的空间也太多了。有经验的邮件列表用户通常会扫视每天的列表邮件的主题,然后决定阅读和/或回复哪些邮件。主题中前置的列表名称会使得主题的正式内容脱离屏幕,无法看到。这混淆了人们赖以决定是否打开邮件的信息,从而减弱了邮件列表的整体功能。

我们不会处理主题头,而是让你的用户利用其他标准的头,以To头说起,可以用来说明邮件列表名称:

To: <discuss@lists.example.org>

任何可以过滤主题的邮件阅读器一定也能轻易的处理To。

还有一些其它的邮件列表期望的可选但标准的头。根据这些头过滤比利用“To”或“Cc”头更加可靠;因为这些头是邮件列表软件本身为每个邮件添加的,一些用户会依赖他们的出现:

list-help: <mailto:discuss-help@lists.example.org>
list-unsubscribe: <mailto:discuss-unsubscribe@lists.example.org>
list-post: <mailto:discuss@lists.example.org>
Delivered-To: mailing list discuss@lists.example.org
Mailing-List: contact discuss-help@lists.example.org; run by ezmlm

绝大部分是自解释的,更多解释可以看http://www.nisto.com/listspec/list-manager-intro.html,或者如果你觉得不够详细,正式的规范可以看http://www.faqs.org/rfcs/rfc2369.html

如果你有一个名为“list”的邮件列表,请注意这些头是如何暗示的,然后你也有了管理地址“list-help”和“list-unsubscribe”。除此之外,用来加入的“list-subscribe”和接触列表管理员的“list-owner”也非常常见。取决于你所使用的管理软件,也可能会设置一些其它的管理地址;文档应该会有详细介绍。通常情况下,每个新用户在订阅时都会收到自动的“欢迎邮件”,其中会完整解释所有的特别地址。你可能有这个欢迎邮件的一份拷贝。如果你没有,可以问其他人获取一份拷贝,这样你就知道当你的用户到来时,他们会看到什么。手中有一份拷贝,你就可以回答邮件列表功能的问题,更好一点,可以放置到网页上。这样当有人丢失了自己的指导并询问“我如何从列表退订时?”,你就可以将URL发送个他。

一些邮件列表软件会在每个邮件的底部追加退订信息。如果有这个选项,请打开它。这样只会导致每个邮件有一段额外的行,在一个无害的位置,可以帮助你节省很多时间,减少了给你,或者更坏的情况,给邮件列表发邮件询问如何退订的人数!

伟大的Reply-to辩论

在前面的the section called “避免私下讨论”,我强调了保持在公共论坛讨论的重要性,谈论了如何防止私下邮件讨论的一些主动措施,除此之外,本章将会讨论如何设置项目交流软件来更好的做这件事。因为如果邮件列表管理软件提供了一个方法来自动导致讨论保持在列表中,你会认为开启这个功能是显而易见的选择。

好的,有时候也不是如此认为。尽管有这个特性,但是它却有严重的Bug。问题是无论你是否在邮件列表管理中使用这个功能都会成为最热的辩论—诚然,这不大可能成为你城市里的晚间新闻那样的论战,但它会在自由软件项目中一次次的爆发。下面,我将描述这个特性,提供两方面的主要论点,提出我能作出的建议。

这个特性本身非常简单:如果你愿意,邮件列表软件可以在每个邮件中自动设置转向到邮件列表的Reply-to头。也就是无论原来的发送者设置了什么Reply-to头(或者他们没有设置),当邮件列表的订阅者看到邮件时,它的头将会包含列表地址:

Reply-to: discuss@lists.example.org

从表面上看非常好。因为实际上所有的邮件阅读软件会注意到Reply-to头,这样当任何人回复邮件时,他们的回复都会自动来到整个列表,而不仅仅是邮件的发送者。虽然回复者仍然可以手工修改回复的地址,但重要的是缺省的回复会指向列表。这是通过技术鼓励协作的完美实例。

不幸的是,也有一些缺点。首先是找不到回家的路问题:有时候原来的发送者会把“真正的”邮件地址存放到Reply-to字段,通常是某种原因他们不能通过发送邮件的地址接收邮件。一直从同一个地址读取和发送的人们不会有这种问题,甚至会惊讶有这种情况。但是对于有特别的邮件设置,或者不能设置他们所看邮件的From地址(或许因为他们在工作时发送,而且不能通过IT部门修改配置)时,使用Reply-to可能是保证回复能够收到的唯一方法 。当此类人在未订阅的邮件列表中发送邮件时,她的Reply-to设置就成为了关键信息。如果列表软件覆盖了它,她可能就看不到回复了。

第二个可以预期的缺点,从我的观点看是Reply-to处理最有力的反对论点。大多数有经验的邮件用户会习惯于两个回复的基本方法:reply-to-allreply-to-author。所有现代的邮件阅读软件对于两个动作都有单独的按键。用户知道如果是回复到所有人(也包括列表),他们会选择reply-to-all,如果是私下回复到作者,他们应该选择reply-to-author。尽管你希望鼓励人们尽可能回复到列表,但确实有情况回复者需要有权利私下回复—例如,他们希望和邮件的原作者说一些机密的事情,可能不适合出现在公共列表中。

现在考虑一下如果列表覆盖了发送者的Reply-to时会发生什么。回复者点reply-to-author,希望向原发送者私下发送一个邮件。因为那是他所预期的行为,所以就可能不会小心查看新邮件的接收地址。他编写了他的私人的、机密信息,可能会说一些对列表中的人来说很尴尬的内容,并点击发送键。出乎意料的是,几分钟之后他的信息出现邮件列表中!诚然,他应该仔细查看接收字段,对于Reply-to头不要有任何设想值。但是作者几乎会肯定将Reply-to设置为他们的个人地址(更确切地说,他们的软件做了设置),许多资深的邮件用户都会期望这样。实际上,如果一个人直接将Reply-to设置为其他地址,他通常会邮件的正文提及这一点,这样人们就不会为回复所发生的事情感到惊讶了。

因为可能出现的严重后果,我的观点是保证列表管理软件决不要碰Reply-to头。这是一个使用技术来鼓励协作的实例,但是对我来说有潜在的危险副作用。然而,在论战的另一面也有强有力的论据。无论你选择何种方式,你都会在列表中看到有人问你为什么不选择另一种方式。因为你肯定不希望这成为邮件列表中的主要讨论,所以最好准备好回应,诸如此类结束讨论而不是鼓励讨论。请确认你不是坚持认定你的决定,也就是无论是哪个,它都应该明显是唯一正确和明智的选择(即使你认为那是一个事实)。相反,指出这是一个老争论了,两方面都有好的论点,没有能够满足所有用户的选择,因而你只是做出了你能做出的最佳决定。有礼貌的告知不要再炒冷饭了,除非有一些独特的新内容,然后不必再参与讨论并希望它能够自然死亡。

有些人会建议开展一个投票。如果你愿意你可以这样做,但是这个情况下我不认为这是一个满意的解决方案。对于某个人因为出人意料的行为模式的惩罚是巨大的(不小心的将私有邮件发送到公共列表),而对于所有其他人的不便是相对轻微的(偶尔需要提醒某人回复到整个列表而不仅仅是你),多数票是什么并不清楚,即使能得到多数票,少数者应该承担这样的危险吗?

这里我没有涉及问题的所有方面,仅仅包含了看起来最重要的。完整的讨论,请看这两篇权威的文档,当人们遇到争论时经常会引用它们:

无论你偏爱上面的哪一条,我不认为此问题有所谓的“正确”答案,也会很乐意参与到设置Reply-to的许多列表。最重要的事情是你尽早确立一种方式,之后再也不要陷入到争论之中。

两个幻想

将来有一天,有些聪明人会在邮件阅读器实现一个reply-to-list键。它可以使用前面提到的一些自定义的列表头来指出邮件列表的地址,然后会将回复仅指向到邮件列表,同时消除所有的其他接收地址,因此,无论如何大多数都是订阅列表的地址。最终,其他邮件阅读器也会采用这个特性,整个争论也就可以偃旗息鼓了。(实际上,Mutt邮件阅读器已经提供了这个特性。[13]

一个更好的解决方案是让每个订阅者自己选择是否进行Reply-to处理。如果希望经过Reply-to处理(自己与他人的邮件),可以要求,而如果不希望,则可以设置为Reply-to不变。然而,我不知道有任何列表管理软件提供这个每订户基础的设置。我们还是只能使用全局设置。[14]

归档

运转列表的软件都有自己特定的设置邮件列表归档的技术细节,超出了本书的范围。当选择归档时,请考虑这些特性:

立刻更新

人们经常会引用在上个小时所做的发布归档。如果可能,归档器必须能够立刻归档每个发布,这样发布出现在邮件列表时,它也就出现在了归档中。如果没有这个特性,至少应该将其设置为每小时更新一次。 (默认情况下,一些归档器会每夜更新,对于一个活跃的邮件列表这有点太滞后了。)

引用稳定性

一旦一个信息已经归档到特定URL,它应该在相同的可访问URL,并尽可能的永远保持。即使归档重建,从备份中恢复,或者其他修正,任何已经公开的URL应该保持相同。稳定引用可以让Internet上的搜索引擎能够索引归档,可以方便用户查找答案。稳定引用重要的另一个原因是因为邮件列表经常会在Bug跟踪(参考本章后面的the section called “Bug跟踪”)或其他项目的文档中被引用。

理想情况下,邮件列表应该能够包含一个信息归档的地址,或者至少在分发到接收者的信息头上有URL的信息特定的部分。这样人们就有了信息的拷贝,已经知道了归档的位置,而无须实际访问归档,这样做很有用,因为任何操作都需要花费网络浏览器的时间。我不知道是否有邮件列表软件实际支持这个特性;不幸的是,我用过的都不行。然而,这是我要寻找的(或者,如果你正在写邮件列表软件,这应该是一个可以考虑实现的特性)。

备份

如何备份归档必须相当清楚,而恢复方法也不能太难。换一句话说,不要把归档器当作黑盒子。你(或者你项目中的某个人)应当知道信息存放在什么地方,以及如何在必要时从信息存放处重新生成归档页。这些归档是珍贵的数据—失去了它们,就像失去了项目集体记忆中美好的一部分。

线索支持

应该能够从任意单独的信息进入原来信息所归属的线索(一组关联的信息),每个线索必须拥有自己的URL,与线索中的其他信息区分开来。

可搜索性

一个不支持搜索的归档器—针对信息内容、以及作者和主题—接近于无用。注意某些归档器只是将此工作交给了诸如Google的第三方搜索引擎。这是可以接受的,但是直接的搜索支持通常会更加易于调整,例如我们可以指定搜索匹配的是主题行还是正文。

上面是一个技术检查列表,可以帮助你评估和设置归档器,本章后面将讨论如何让人们利用归档器来使项目获益,特别是在the section called “归档的显著使用”

软件

这里是一些可以进行列表管理和归档的开源工具。如果你的项目主机已经有默认的设置,你可能无法决定一个工具。但是如果你必须自己安装一个,这些是可以选择的。我实际使用过的包括ailman、Ezmlm、MHonArc和Hypermail,这并不是意味着其他工具不好(当然可能有其他一些工具只是我碰巧没有找到,所以不要把这当作完全的列表)。

邮件列表管理软件:

邮件列表归档软件:

版本控制

一个版本控制系统(或修订控制系统)是跟踪和控制项目文件变更的技术与实践的组合,包括源代码、文档和网页。如果你以前从来没有使用过版本控制,那你最好赶快找一个有经验的人加入。现今,所有的人都希望你的项目源代码存放在版本控制下,如果不使用版本控制,人们将会轻视项目。

版本控制如此广泛的原因是因为它实际上能帮助运营一个项目的所有方面:内部开发者交流、发布管理、Bug管理、代码稳定性和试验开发投入,以及对某个变更所属开发者的归因和授权。版本控制系统为这些领域提供了一个集中的协调力量。版本控制的核心是变更管理:识别对项目文件的每一个不相关的变更,使用元数据例如变更的日期和作者来注解每个变更,之后无论使用什么方法,任何人询问时,重放这个事实。这是一种变更为信息基本单元的交流机制。

这个部分不会讨论使用版本控制的所有方面。它是如此包罗万象,我们不得在本书不时的提及。因此,我们会通过促进协作开发的方式,专注于版本控制系统的选择和设置。

版本控制词汇表

如果你没有用过版本控制,本书不会教你如何使用,但是如果没有一些关键术语,我们就无法讨论。这些术语独立于任何特定的版本控制系统:它们是网络交互的基本名词和动词,将会在本书剩下的部分广泛使用。即使这个世界上没有版本控制,变更管理的问题也会存在,这些术语为我们简明的讨论这些问题提供了一种语言。

提交(commit)

对项目做出一个变更;更正式的,以此方式在版本控制数据库存储一个变更,可以成为项目以后发布的一部分。 “提交”可以作为名词或动词。作为名词,从本质上讲可以看作是“变更(change)”同义词。例如:“我刚刚为报告的Mac OS X上的服务器宕机Bug提交了一个修订。Jay,你能评审一下提交并看一下我有没有误用内存分配吗?”

日志信息(log message)

每次提交所附的注释,描述了提交的性质和目的。日志信息是任何项目最重要的文档:它是单个代码变更的高度技术语言与特性、Bug修订和项目进展这类更面向用户的语言的桥梁。本节的后半部分,我们会关注将日志信息发布给适当读者的方法;另外,Chapter 6, 交流the section called “编制法律的传统”将会讨论鼓励贡献者填写简明和有用日志信息的方法。

更新(update)

请求将其他人的变更(提交)和项目的本地拷贝进行组合;也就是将你的拷贝“保持最新”。这是一个非常常见的操作;大多数开发者每天都会多次更新代码,因此,可以确认他们运行的代码与别人的相同,因此他们看到一个Bug,他们可以确信它还没有被修正。例如:“嗨,我发现索引代码一直会丢掉最后一个字节。这是一个新的bug吗?”“是的,但已经在上周修正了—更新一下,一定是好了。”

版本库(repository)

一个存放变更的数据库。一些版本控制是集中式的:有一个单独的主版本库,会存放项目的所有变更。也有一些分布式的系统:每个开发者都有自己的版本库,变更可以在版本库之间任意交换。版本控制系统跟踪了变更之间的依赖关系,当需要发布时,确认一部分变更集进入发布。集中式还是分布式的问题也是一场不朽的软件开发圣战;也要防止落入在你的项目列表中讨论这个问题的陷阱。

检出(checkout)

从版本库获取项目拷贝的过程。一个检出通常会产生一个叫做“工作拷贝”(看后面)的目录树,可以从这个目录将变更提交回原来的版本库。在一些分布式的版本控制系统,每个工作拷贝本身都是一个版本库,变更可以推出(拖入)到任何愿意接受的版本库。

工作拷贝(working copy)

一个包含项目源代码文件或者网页及其他文档的开发者的私有目录树。一个工作拷贝也可能会包含由版本控制系统管理的元数据信息,可以说明工作拷贝所对应的版本库,以及所展现文件的“修订版本(看后面)”等等。通常情况下,每个开发者都有自己的工作拷贝,他可以在其中进行变更以及测试,并提交。

修订版本(revision), 变更(change), 变更集(changeset)

一个“修订版本”通常是一个特定文件或目录的具体化身。例如,如果开始时一个项目有一个文件F,修订版本是6,然后如果有一个文件对文件F提交了一个变更,那么就会产生F的修订版本7。一些系统也使用“修订版本”,“变更”或“变更集”来引用作为一个逻辑概念的一组变更。

这些术语在不同的版本控制系统可能有不同的技术含义,但是大意基本相同:他们提供了一个方法可以精确的描述一个文件或一组文件历史中的精确位置(比方说,恰恰在一个Bug修正之前或之后)。例如:“她在修订版本10修正了那个”或者“他在文件foo.c的修订版本10修正了那个。”

当一个人在不指定特定修订版本的时候谈论一个文件或一组文件时,通常假定是指最近的修订版本。

差异(diff)

变更的文本化展现。一个差异显示了哪些行发生了怎样的改变,以及围绕上下文两侧的几行。一个已经熟悉代码的开发者通常可以阅读区别,并理解变更完成的事情,甚至定位Bug。

标签(tag)

一组特定修订版本的文件的标签。标签通常用来保存人们感兴趣的项目快照。例如,为每个公开发布使用标签,这样人们就可以从版本控制系统获取发布对应的文件/修订版本。常见的标签名称有Release_1_0Delivery_00456等等。

分支(branch)

项目的一个拷贝,在版本控制之下,但却是孤立的,所以分支上的变更不会影响项目的其他部分,或者相反,除非你故意将变更“合并”过去(看后面)。分支也被称为“开发线(lines of development)”。即使当一个项目没有明确的分支,开发也可以被认为是发生在“主分支”,也称为“主线”或“主干(trunk)”。

分支提供了一个将开发线隔离的方法。例如,一个分支可以用来进行对于主干不够稳定的实验开发。或者一个分支可以用来稳定新的发布。在发布过程中,有规律的开发可以继续不受干扰的在版本库的主线进行;与此同时,在发布分支,除非经过发布管理员的确认,不允许任何变更。通过这种方式,让发布不必干扰正在进行的开发工作。关于分支的详细讨论见本章后面的the section called “使用分支来避免瓶颈”

合并(又名搬运)(merge, a.k.a. port)

用来将变更从一个分支搬运到另一个。这包括从主干合并到分支,或者相反。实际上,这是最常见的合并类型;在两个非主分支之间搬运变更的情况很少见。关于此类合并的更多信息可以看the section called “信息单一性”

“合并”也有另一种相关的含义:也就是当两个人对于同一个文件作出没有交叠的变更时,版本控制系统所作的事情。因为两个变更没有互相干扰,当一个人更新其拷贝中的这个文件(已经包含他自己的变更)时,其他人的变更会自动合并进去。这非常常见,特别是当多个人编辑同一代码时。当两个变更确实交叠了,结果就是“冲突”了;看下面。

冲突(conflict)

当两个人希望对于代码的同一个地方作出不同的修改时。所有的版本控制系统会自动监测到冲突,并至少让一个人意识到他们的变更与其他人的冲突了。这依赖于解决(resolve)冲突的人,以及与版本控制系统解决的交流。

锁定(lock)

对于某个文件或目录进行排他变更声明的方法。例如,“我现在不能对网页文件提交任何变更。似乎Alfred已经锁定了所有文件,因为他要修改背景图片。”不是所有的版本控制系统都提供了锁定能力,它们并不都需要使用锁定特性。这是因为平行,同时开发是行为准则,而将人们锁定在文件之外违背了这个思想。

需要锁定才能提交的版本控制系统,我们称之使用锁定-修改-解锁模型。而其他的我们称之为拷贝-修改-合并模型。两种模型的一个完美的深入解释和比较可以看http://svnbook.red-bean.com/svnbook-1.0/ch02s02.html。通常情况下,拷贝-修改-合并适合于开源开发,在本书讨论的版本控制工具都支持这个模型。

选择一个版本控制系统

在写本文的时候,自由软件世界中两个最流行的版本控制系统是并行版本系统CVShttp://www.cvshome.org/)和SubversionSVNhttp://subversion.tigris.org/)。

CVS已经存在很长时间了。大多数有经验的开发者已经熟悉了它,它或多或少满足了你的需要,而且因为它已经流行了很长时间了,你可能不会陷入它是否为正确选择的争论。CVS有一些缺点。它不支持简单的引用多个文件的变更;它不支持版本控制下的文件重命名和拷贝(这种情况下如果你需要识别出项目开始后的代码树,会非常头痛);它对合并的支持很弱;它处理大文件和二进制文件不佳;以及在操作很多文件时操作会非常慢。

CVS的这些Bug都不是致命的,所以它一直非常流行。然而,最近几年Subversion逐渐被人们所接受,特别是在新创建的项目中。[15]如果你新开始一个项目,我推荐Subversion。

在另一方面,因为我参与了Subversion项目,我的客观性有理由值得怀疑。在最近几年,许多新的开源版本控制系统已经出现。Appendix A, 自由版本控制系统列出了所有我知道的,大体上根据流行性排序。就像列表说明的,决定使用何种版本控制系统可能成为一项终身的研究项目。有可能你也会省掉选择的过程,因为你的主站已经做出了选择。但如果你必须做出选择,请咨询那些有经验的人,然后选择一个并使用起来。任何稳定的产品状态的版本控制系统可以实现;你不必担心会做出灾难性的错误决定。如果你无法下决心,那就Subversion吧。它学起来相对简单,在近几年里还应该保持标准的地位。

使用版本控制系统

这一部分的建议不针对任何特定版本控制系统,它们都应当可以简单的实现。详细信息请参考特定系统的文档。

版本化所有的东西

不要仅仅将项目的源代码纳入到版本控制下,也应该包括网页、文档、FAQ、设计注释和任何人们希望编辑的内容。让他们与源代码尽量接近,在同一个版本库树中。任何值得写下来的信息都应该纳入版本控制—也就是任何可能会变更的信息。不会发生变更的东西都应该归档,而非版本化。例如,一个邮件一旦发布,就不会变更;因此,将其版本化没有任何意义(除非它成为一个较大的、进化文档的一部份)。

在一个地方版本化所有的东西的原因非常重要,这样人们只需要学习一种提交变更的方式。例如,经常是一个贡献者开始编辑一个网页或者文档,然后接着做一些代码变更。当项目对于所有的提交使用相同的提交方式时,人们只需要学习一次。一起版本化所有的东西也意味着随着文档的更新,新特性可以一起提交,而代码分支时也是对文档分支等等。

不要将生成的文件置入版本控制。那些应该不是可编辑的数据,因为它们是程序方式由其他文件产生的。例如,一些构建系统根据模板configure.in文件产生configure。为了改变configure,我们需要编辑configure.in,然后重新生成;因此,只有文件configure.in是“可编辑文件。”只版本化模板—如果你也版本化结果文件,人们在对模板进行修改后会不可避免的忘记重新生成它,结果的不一致会导致无休止的混淆。[16]

所有可编辑数据必须存放在版本控制下的规则也有一个不幸的例外:Bug跟踪。Bug数据库保存了大量的可编辑数据,但是因为技术原因不能将数据存放在版本控制系统。 (一些跟踪工具有一些原始的版本控制特性,然而,独立于项目的主版本库。)

可浏览性

项目的版本库应该能够通过web浏览。这不仅是意味着浏览最新修订的能力,也包括回到过去查看早先的版本,查看修订之间的区别,以及阅读针对特定变更的日志信息等等。

可浏览性非常重要,因为它是一个轻量级的项目数据门户。如果不能通过web浏览版本库,那一个人如果希望检查特定的文件(例如,看一下某个bug修正是否已经进入代码),他必须在本地安装版本控制客户端,这会让一项只需要两分钟的任务变成一项半小时或更长的任务。

可浏览性也暗示了浏览文件特定修订版本的标准URL,以及任意给定时间最近的修订。在技术讨论或向人们指明作为证据时这非常有用。例如我们不会说“关于调试服务器的提示,可以看你工作拷贝中的www/hacking.html”,而会说“关于调试服务器的提示,可以看http://svn.collab.net/repos/svn/trunk/www/hacking.html,”给定一个会一直指向hacking.html最新修订的URL会更好。因为它不会导致混淆,也避免了用户是否有最新工作拷贝的问题。

一些版本控制系统包含内置的版本库浏览机制,而其他一些依赖于第三方的工具实现。这类工具有ViewCVShttp://viewcvs.sourceforge.net/)、CVSWebhttp://www.freebsd.org/projects/cvsweb.html)以及WebSVNhttp://websvn.tigris.org/)。第一个工具可以支持CVS和Subversion,而第二个只支持CVS,而第三个只支持Subversion。

提交邮件

对版本库的每一次提交应当能够产生一个邮件,包含谁做出修改的、何时作出的修改、修改的文件和目录以及为什么修改。邮件必须发送到专注于提交邮件的特别邮件列表,在邮件列表中能够同普通人的邮件区分开来。必须鼓励开发者和其他感兴趣的参与者订阅这个提交列表,这是从代码级别来跟踪项目的最有效方法。除了同级评审(见the section called “实践明显的代码评审”)这一明显的技术益处,提交邮件帮助我们建立了一种社区意识,因为他们创建了一个共享环境,在其中人们可以对其他人也可见的事件(提交)作出反应。

设置提交邮件的具体方法依赖于你的版本控制系统,但通常有一些脚本或其他工具可以完成这个工作。如果你在寻找过程中遇到困难,可以查一下钩子(hooks)的文档,特别是post-commit hook,CVS中也称作loginfo hook。Post-commit钩子大意上就是对提交做出自动化的响应。这个钩子会由每个提交出发,并提供关于提交的所有信息,你可以自由的使用这些信息做任何事情—例如,发送一个邮件。

通过预先包装的提交邮件系统,你可能会希望修改一些默认的行为:

  1. 一些提交邮件程序会在邮件中包含实际的区别,而不是提供在web上使用版本库浏览系统查看变更的URL。虽然提供URL非常好,这样后面就可以引用这个变更,但是在邮件本身中包含区别同样非常重要。阅读邮件已经成为人们的例行的一部分,如果变更的内容在提交邮件中,开发者可以立刻进行评审,不需要离开邮件阅读器。如果他们需要点击一个URL来评审变更,大多数人就不会作了,因为需要开始一个新动作,而不是延续一个已发生的动作。此外,如果评审者希望询问变更的某些事情,可以直接选择带原文回复并注解区别,这样就不必访问网页并辛勤的从web浏览器拷贝粘贴到邮件客户端。

    (当然,如果区别非常大,诸如大片的新代码正文添加到了版本库,那么省掉区别而只提供URL就比较有意义。大多数提交邮件程序可以自动执行这种限制。如果你的不支持,那包含区别也没有关系,只是偶尔会有些大邮件,比完全没有区别更好。便利的评审和回复是协作开发的奠基石,是否存在十分关键。)

  2. 提交邮件必须将Reply-to头设置为普通的开发邮件列表,而不是提交邮件列表。那是因为,当有人评审一个提交并撰写了一个回复,这个回复应当自动转向到人们的开发邮件列表,也就是通常人们讨论技术问题的地方。有这么几个原因。首先,你希望将技术讨论保持在一个邮件列表中,因为这也是人们所期望的情况,而且这种情况下只需要搜索一个归档。其次,有一些感兴趣的参与者可能没有订阅提交邮件列表。第三,提交邮件列表把自己当作一个监视提交的服务,而不是用来关注提交偶尔进行技术讨论。订阅提交邮件列表的人除了提交邮件没有订阅其他东西;通过那个列表发送其他内容违反了隐含的契约。第四,人们经常写程序来阅读提交邮件列表并处理结果(例如为了显示一个网页)。这些程序预备好了处理一致格式的提交邮件,但与人写的邮件不匹配。

    请注意这里设置Reply-to的建议与本章前面the section called “伟大的Reply-to辩论”中说的并不矛盾。对于信息的发送者来说,设置Reply-to非常正常。在这个情况下,发送者是版本控制系统本身,它设置Reply-to是为了说明回复的合适地方是开发邮件列表,而不是提交列表。

使用分支来避免瓶颈

非专家的版本控制用户有时候会担心分支与合并。这可能是CVS流行性的副作用:CVS对于分支和合并的接口和我们的知觉不太一致,所以很多人学着完全避免此类操作。

如果你周围有很多这类人,立即下决心战胜所有恐惧,并花时间学会如何分支和合并。它们不是什么困难的操作,一旦你习惯了,对于项目获取更多的开发者这日益重要。

分支非常有价值,因为它将一项稀缺的资源—项目代码的工作空间—变得充足。一般情况下,所有的开发者在同一个沙盒一起工作,建设同一座城堡。当某个人希望添加一个新的吊桥,但是不能确认其他人是否正在工作,分支使她被隔离到一个角落并做出尝试成为可能。如果这种投入成功了,她可以要求其他开发者检验这个结果。如果所有人认可结果,他们可以告诉版本控制系统将吊桥从分支城堡移动(“合并”)到主城堡。

很容易看到这项能力是如何帮助协作开发的。人们需要自由尝试新问题的感觉,而无须担心干扰其他人的工作。同样重要的是,当为了完成bug修正或发布稳定化(见<Chapter 7, 打包、发布和日常开发the section called “稳定发布版本”the section called “维护多发布线”),代码需要从日常的开发中分离出来时,所花费的时间数倍于无需担心跟踪一个移动目标的情况。

不受限制的使用分支,并鼓励其他人也这样做。但是要确保任何特定分支只保持必要的最短时间。任何活动分支都会让社区分神。即使不是在分支工作的人也需要对此有所了解。这种了解是应该的,当然,对于分支的提交应该能和其他提交一样发送提交邮件。但是分支不应该成为分割开发社区的机制。除了很少的例外,大多数分支最终必须合并回它们的主干并消失。

信息单一性

合并有一个推论:不要将同一个变更提交两次。也就是一个修改只进入一次版本控制系统。变更的修订(或一组修订)可以在其进入版本控制系统之后拥有唯一标示。如果它需要应用到还没有应用过的分支,那么它应该从最初的入口点合并到其他目标—而不是直接提交相同的文本,这样虽然对代码的效果是一样的,但会导致我们无法进行精确的记录和发布管理。

这个建议对于不同版本控制系统的实践效果不尽相同。在一些系统,合并是特殊的事件,从根本上与提交不同,并包含他们自己的元数据。而另外一些系统,合并的结果就像其他变更一样是提交到了系统,所以区别“合并提交”和“新变更提交”的主要方法是使用日志信息。在合并的日志信息中,不会再重复原始变更的信息。而只是指明这是一个合并,并提供原始变更的修订版本,以及一段说明其效果的文字。如果有人希望看到完整的日志信息,她应该参考原来的修订。

避免在提交之后再重复日志信息的原因非常重要,因为日志会在提交后被修改。如果变更日志在每个合并目标中重复,那有朝一日她修改了最初的信息,而那些重复还是会保持错误—混淆就会持续下去。

同样的原理也适用于撤销一个变更。如果一个变更从代码中撤销,那么这个撤销的日志信息也应该仅仅是指明撤销的是哪些特定的修订版本,而不是描述撤销过程中实际变更的代码,因为变更的内容可以通过阅读原来的日志信息和修订获得。当然,修订版本日志信息也应当说明恢复变更的原因,但它不应该从原始变更日志信息复制任何东西。如果可能,回到原来的变更日志信息,并指明它已经撤销了。

前面所说的都暗示了你应该使用一致的语法来引用这些修订版本。这不仅仅在日志信息中有益,在邮件、Bug跟踪和其他地方也同样重要。如果你使用CVS,我建议使用“path/to/file/in/project/tree:REV”,其中的REV就是CVS的修订版本好吗,例如“1.76”。如果你使用Subversion,修订版本1729的标准语法是“r1729”(文件路径不是必需的,因为Subversion使用全局修订版本号)。在其他系统中,也都有一些表达变更集的标准语法。无论对你的系统合适的语法是什么,鼓励人们使用它们来引用变更。对变更名一致的表达方法可以帮助项目更简单的纪录(在Chapter 6, 交流Chapter 7, 打包、发布和日常开发我们将会看到),而且因为许多纪录是由志愿者完成的,它应该尽可能的简单。

Chapter 7, 打包、发布和日常开发the section called “发布和日常开发”也有介绍。

授权

大多数版本控制系统提供了控制特定人可以从版本库特定子区域提交的特性。根据这个原理,当人们手握锤子时,就开始到处找钉子,许多项目开始恣意使用这种特性,小心的为每个人只赋予他们被确认的权限,而不能在任何其他地方提交。 (看Chapter 8, 管理志愿者the section called “提交者”来确认何人可以在何处提交。)

执行这样严格的控制可能会有一些害处,一个宽松的政策也足够好。一些项目会简单得使用一个荣誉系统:当一个人被赋予提交权限,即使只是版本库的一个子区域,他也会收到一个可以在项目所有地方可以提交的密码。他们只是被告知要在自己的区域提交。请记住这里没有真正的危险:在一个活跃的项目里,所有的提交会被审核。如果有人在不被允许的地方提交,其他人会发现这一点并说出来。如果这个变更需要被回退,很简单—因为所有地变更都在版本控制之下,只需要回退。

这种宽松的方法有许多好处。首先,当开发者扩展了他们的活动范围(如果他们一直在项目中,这是一个通常的情况),赋予更宽泛的权限无需额外的管理工作。一旦作出了这样的决定,这个人就可以立刻在新区域提交。

第二,扩展可以以一种更细致的方式实现。通常情况下,区域X的提交者如果希望扩展到区域Y,他会通过发表对Y的一个补丁并寻求评审开始。如果对区域Y有提交权限的人看到这个补丁并确认,他可以直接让提交者直接提交这个变更(当然也要在日志信息中提及评审者/确认者的名字)。这样,这个提交就会成为实际编写变更者的作品,无论从信息管理角度还是审计角度这样都更好。

最后,可能是最重要的,使用荣誉系统来鼓励互相尊重和信任的氛围。给一个人对某一区域的访问权限是对他们已经完成技术准备的证明—这是说:“我们已经看到了你已经具备了对某一领域做出修改的专业知识,那就继续吧。”但设置严格的授权控制则是暗示:“我们不仅仅确认你专业知识的限制,而且我们对你的目的也保持怀疑。”如果可以避免的话,你一定不愿意做出这样的评价。将一个人引入为项目的提交者是将其引入互相信任循环的机会。好的方法是给他们比期望所能发挥作用更大的权力,然后告诉他们是否保持在规定的限制内完全依赖于他们自己。

Subversion项目按照荣誉系统的方式已经运作超过4年了,在写作时包含了33个完全的和43个部分提交者。系统实际强制的只是提交者和非提交者的区别;更细的划分只由人为控制。但是我们从来没有遇到故意在领域外提交的问题。只是有一两次由于对个人提交权限范围的误解造成的错误,而且都能够迅速和亲切的得到解决。

很明显,当自律的方式不够实际时,那你就需要严格的授权控制。但这种情形非常少见。即使当有几百万行的代码,以及数百或上千的开发者时,对于任何给定模块的提交,也必须经过模块上工作的人们的评审,而且他们可以识别出提交者是否得当。如果没有有规律的提交评审,那么项目恐怕就会遇到比没有授权系统更大的问题了。

归纳起来,不要在版本控制的授权系统上花费太多时间,除非你有特别的原因。复杂的授权系统不能带来实际的好处,依赖人为控制有更多的优点。

当然,上面所说的并不意味着限制本身不重要。项目不应该鼓励人们在不够格的地方提交。此外,在很多项目中,完全(无限制)的提交访问有一个特别的状态:它隐含了项目范围问题的投票权。提交访问的政治方面将会在Chapter 4, 社会和政治的基础架构the section called “谁进行表决?”详细讨论。

Bug跟踪

Bug跟踪是一个宽泛的话题;贯穿本书会讨论此问题的各个方面。尽管这里我们要着重于配置和技术因素,但是首先要从一个策略问题开始:Bug跟踪系统中应该包含哪些信息?

术语Bug跟踪很有误导性。Bug跟踪系统也通常会用来跟踪哪些初始与结束状态不同,包含可选的中间状态,并在生命周期中积累信息的问题,例如新特性请求、一次性任务以及被动性的补丁。由于这些原因,Bug跟踪也被称为问题跟踪(issue trackers)缺陷跟踪(defect trackers)制品跟踪(artifact trackers)请求跟踪(request trackers)以及问题票跟踪(trouble ticket systems)Appendix B, 自由Bug跟踪系统包含了一个此类软件的列表。

在本书中,我会继续使用“Bug跟踪(bug tracker)”这个名称,因为大多数人这样称呼,但我会使用问题(issue)来称呼Bug跟踪数据库中的单个条目。这让我们可以把用户遇到的(Bug本身)正常或不良行为与跟踪系统中Bug的发现、诊断和最终解决的记录区分开来。请牢记,尽管大多数问题与实际的Bug相关,我们也可以用其来跟踪其它类型的任务。

典型的问题生命周期如下:

  1. 某人发起了一个问题。他提供了摘要,初始描述(如果合适则包含重现方法;如何激励好的Bug报告请看Chapter 8, 管理志愿者the section called “将每个用户当作潜在的志愿者”),以及其它跟踪系统要求的信息。项目可能对发起人一无所知—Bug报告和特性请求既可能来自用户社区,也可能来自开发者。

    一旦发起,这个问题就进入了打开(open)状态。因为还没有作出任何行动,一些跟踪系统也将其标示为未验证(unverified)未开始(unstarted)。它还没有分配给任何人;或者在某些系统中将起分配给一个冒牌用户来表示其还没有真正的分配。此刻,它存在于一个保留区:这个问题已经记录,但是还没有成为项目关注的一部分。

  2. 其他人读到这个问题,并做出回复,或许会再向发起者询问来澄清一些问题。

  3. Bug得到重现(reproduced)。这可能是其生命周期中最重要的一个时刻。尽管bug还没有修正,但发起者之外的人重现这个事实可以证明这个bug的真实性,此外,可以确认原发起者通过报告真实的bug为项目做出了贡献。

  4. Bug得到诊断(diagnosed):它的原因得到确认,如果可能,会对修正这个bug所需的工作量做出评估。请确认这些内容会在问题中得到记录;如果诊断人要离开项目一会儿(对于志愿开发者这很普遍),其他人应该能够接手。

    在本阶段,或者前一个阶段,开发者可以“获取”问题所有权并将其分配(assign)给自己(Chapter 8, 管理志愿者the section called “明确区分调查和指派”详细描述了分配过程的细节)。问题优先级(priority)也可以在本阶段设置。例如,如果某个问题严重到足以影响下一个版本的及时发布,则需要尽早标示出来,跟踪系统必须能够使其突出显示。

  5. 问题纳入解决的日程(schedule)。纳入日程并不是意味着规定一个解决的日期。有时候只是决定未来的那个版本(下一个版本不是必须的)必须解决这个bug,或者这个bug将会阻碍哪些特定版本。如果很容易修正,也可以取消纳入日程这一步。

  6. Bug得到修正(任务完成、或应用了补丁、或者其他类似的事情)。变更或者变更集必须记录在问题的回复中,其后是问题被标注为解决(resolved)而得到关闭(closed)

这个生命周期有许多变种。有时候一个问题再发起之后很快就会关闭,例如发现它不是一个bug,而只是部分用户的误解。随着项目获得了越来越多的用户,就会带来更多无效的问题,开发者会用日益缺乏耐心的回应来关闭这些问题。要尝试预防这后一种趋势。这对谁都没有好处,每个案例中的每个单独用户对于此前的无效问题没有任何责任;统计学的趋势只是从开发者而不是用户的视点有效。 (在本章后的the section called “Bug跟踪的预过滤”将会看到减少这种无效问题的技巧。)另外,如果不同的用户反复经历同样的误解,这或许意味着软件的某方面需要重新设计。如果有一个问题经理监视着bug数据库,就会很容易发现这种模式;见Chapter 8, 管理志愿者the section called “问题管理员”

生命周期的另一种常见变种是问题在步骤1之后直接以重复(duplicate)状态关闭,重复是某人发起了一个项目已知的问题。重复不仅限于开放的问题:它也可能来自已经修正的bug重现(这个称为衰退(regression)),无论何种情况最佳的解决方式是重新打开最初的问题,并将新的报告复制到最初的问题中。Bug跟踪系统应当能够双向保持联系,这样重复的重现信息中就可以在原问题中看到,反之亦然。

开发者关闭这个问题的第三种情况是他们认为已经修正了问题,只是让原报告者拒绝这个修正并重新打开它。这通常仅仅是因为开发者不能访问重现bug的环境,或者因为他们不能通过报告者的再现描述测试这个修正。

除了这些情况,不同的跟踪软件也有一些其它小的生命周期细节。但基本的生命周期是相同的,生命周期本身并不特定于开源软件,只是暗示了开源项目如何使用他们的bug跟踪系统。

就像步骤1暗示的,跟踪系统和邮件列表或网页一样,是项目的门面。任何人可以发起一个问题,任何人可以浏览当前打开的问题列表。由此我们也能推断我们无法知道有多少人在等待给定问题的进展。而开发社区的规模和技巧限制了问题解决的速率,项目至少应该知道每个出现的问题。即使问题会缓慢小时,一个回复也会鼓励报告者保持参与,因为她能感觉到有人已经为其所作的事情登记(请牢记填写一份问题远比发一封邮件更麻烦)。此外,一旦开发者看到一个问题,它就进入了项目的意识中,也就是开发者会查看此问题的类似情况,或者会与其他开发者讨论,等等。

及时反应的需求意味着两件事:

  • 跟踪系统必须能够连接到邮件列表,这样问题的每个变更,包括初始的填写,都会导致描述发生情况的邮件。这些邮件列表通常与正规的开发列表不同,因为不是所有的开发者会希望接收自动bug邮件,但是(就像提交邮件)Reply-to头应该设置为开发邮件列表。

  • 填写问题的表单一定能够捕捉开发者的邮件地址,这样她可以联系到更多信息。 (然而,它不应当要求输入报告者的邮件地址,因为一些人喜欢匿名报告问题。匿名访问的重要性可以看本章后面的the section called “匿名和参与”。)

与邮件列表交互

请确保bug跟踪系统不会成为讨论论坛。尽管让人参与bug跟踪很重要,但从根本上它不适合实时讨论。更应该将其当作归档,组织证据和其他讨论(通常发生在邮件列表)的引用。

做出这种区别有两个原因。首先,Bug跟踪系统的使用比邮件列表(或者实时讨论论坛)更加笨拙。这不是因为bug跟踪系统都没有好的用户界面设计,而是因为它们的界面设计用来捕捉和展示分离的状态,而不是自由流动的讨论。第二,不是每个参与到特定问题讨论的人都必须注意bug跟踪系统。优良的问题管理(见Chapter 8, 管理志愿者the section called “像分担技术任务一样分担管理任务”)是让每个问题被恰当的人注意到,而不是让所有的开发者监视所有的问题。在Chapter 6, 交流the section called “Bug跟踪系统中无对话”,我们会关注确保人们不会脱离合适的论坛而陷入在bug跟踪系统内讨论的问题。

有一些bug跟踪系统可以监控邮件列表并自动记录关于已知问题的邮件。他们通常是通过在邮件列表中,将邮件标题出现的问题标示号码作为特殊字符串来识别问题;开发者学着在他们的邮件中包含这类字符串来触动跟踪系统的注意。Bug跟踪系统可以保存整个邮件,或(更好一点)只是记录邮件在邮件列表归档中的链接。无论何种方式,这是一个非常有用的特性;如果你的跟踪系统有这个功能,要确保在开启它的同时提醒人们利用这个特性。

Bug跟踪的预过滤

大多数问题数据库最终会遭遇相同的困境:由好心但没经验或消息不灵通用户所发起的重复和无效问题的洪流。与这种趋势斗争的第一步通常是在bug跟踪系统的前页放置一个显著的提醒,解释如何知道一个bug是否确实是bug、如何查找bug是否已经被发起、以及如果依然认为是新bug时如何有效的报告。

这会暂时减少噪音,但是当用户数增加后,问题还是会出现。每个单独的用户都不应该因此被谴责。即使他们的第一个bug报告没有用处,你还是要鼓励他们保持参与并在以后提出更好的问题。同时,项目需要保持问题数据库的垃圾越少越好。

这两件事可以最大程度的防止这些问题:请确认监视bug跟踪系统的人有足够的知识,能在问题无效或重复时关闭它,而且能够要求(或强烈的鼓励)用户在填入跟踪系统前确认他们的bug。

第一种技术看起来被广泛使用。即使项目有巨大的问题数据库(例如,Debian在http://bugs.debian.org/的bug跟踪系统,目前有315,929个问题)也是这样安排的,这样某人进入时就能看到所有的问题。不同的问题类别可能是不同的人。例如,Debian项目包含了一组软件包,这样Debian就能够自动路由每个问题到合适的包维护者。当然,用户有时会把问题类别搞错,这样一开始问题就会发送到错误的人,而他可以再将其转向到其他人。然而,最重要的事情是负担被分担了—无论用户在填写的时候是对是错,问题监视的任务还是会在开发者之间分配,所以每个问题都能够得到及时的回复。

第二种技术应用的没有那么广泛,可能因为它很难被自动化。本质思想是每个新问题都是经过伙伴处理后进入到的数据库中。当用户认为他发现了一个问题,他就会被要求在邮件列表或IRC频道中对其进行描述,然后得到某个人对其是bug确认。尽早引入第二双眼睛可以防止许多虚假的报告。有时候第二方可以识别出这个行为不是一个bug,或者已经在最近的发布中被修正。或者她可能由于类似症状bug而感到熟悉,而且可以通过给用户指明老的问题来防止重复的填写。通常仅仅是询问用户“你查找过bug跟踪系统以确定这个问题是否已经报告过了吗?”许多用户不会想到这个一点,如果有人期望,你可以愉快的为他们查找一下。

这种伙伴系统确实可以保证问题数据库的清洁,但是也有一些不利的地方。许多用户无论如何也要独立发起问题,对为发起新问题而寻找伙伴的指南看不到或者视而不见。因此,还是需要有志愿者关注问题数据库。此外,因为许多新报告者不理解维护问题数据库的难度,对他们忽略指南的行为进行过于严厉的斥责是不公平的。所以志愿者必须保持警觉,联系如何反弹未经搭档处理的问题给报告者。目标是训练每个报告者在未来使用伙伴系统,这样就有一个日益增长的能够理解问题过滤系统的用户池。当看到一个未经伙伴系统处理的问题时,理想的步骤是:

  1. 立刻回复问题,礼貌的感谢用户的填写,但是向他们指出伙伴系统的操作指南(当然应该在网站的显著位置)。

  2. 如果问题是明显有效而且没有重复,想办法证明它,使之开始正常的生命周期。毕竟,报告者没有被告知伙伴系统,所有浪费工作量关闭有效的问题是没有意义的。

  3. 否则,如果问题不是很清楚的有效,关闭它,但是要求报告者在得到伙伴的确认后重新打开它。当他们这样做时,他们应当放置一个确认邮件列表线索的引用(例如一个邮件列表归档的URL)。

请记住尽管系统会逐渐改善问题数据库的信/噪比,但是不会阻止误填的发生。完全防止误填的唯一方法是关闭bug跟踪系统,只开放给开发者—治愈几乎永远比疾病本身更坏。应当接受无效问题的清理是项目日常维护的一部分,并努力得到更多的人们来帮忙。

Chapter 8, 管理志愿者the section called “问题管理员”也有介绍。

IRC / 实时聊天系统

许多项目使用互联网多线交谈IRC)提供实时聊天室,作为用户和开发者互相提问并得到及时答复的讨论场所。即使你可以在你的服务器运行IRC服务器时,也不必为此事麻烦。而应该象其他人一样:在Freenode(http://freenode.net/)运行你的IRC频道。Freenode给了你足够的权利来管理你项目的IRC频道,[17]可以让你摆脱维护IRC服务器这类无意义的麻烦。

首先要选择一个频道名称。最明显的选择是你的项目名—如果在Freenode存在,就使用它。如果不存在,可以选择一个与项目名接近的名称,尽可能的易于记忆。在你的项目网站上将频道广而告之,这样期望快速提问的访问者可以立刻看到它。例如,Subversion主页上显著放置的方框中所出现的:

If you're using Subversion, we recommend that you join the users@subversion.tigris.org mailing list, and read the Subversion Book and FAQ. You can also ask questions on IRC at irc.freenode.net channel #svn.

一些项目有多个频道,每个子主题一个。例如,一个频道关注安装问题,另一个是使用问题,还有一个是开发聊天,等等。 (Chapter 6, 交流the section called “处理成长”讨论了如何划分多个频道)。当你的项目还年轻时,应该只有一个频道,所有人在一起讨论。之后,随着用户到开发者比率增加,也就有必要分开单独的频道。

人们如何知道所有的已有频道,以及在哪个频道讨论?他们何时交谈,如何知道当地的习惯?

答案是通过设定频道主题告诉他们。[18]频道主题是每个用户在进入频道时看到的一些信息。可以给每个新人一份快速指南,指出更进一步的信息。例如:

You are now talking on #svn

Topic for #svn is Forum for Subversion user questions, see also
http://subversion.tigris.org/. || Development discussion happens in
#svn-dev. || Please don't paste long transcripts here, instead use
a pastebin site like http://pastebin.ca/. || NEWS: Subversion 1.1.0
is released, see http://svn110.notlong.com/ for details.

内容很扼要,但是它告诉新人所必需知道的东西。它精确的说明频道的目的,提供了项目的主页(如果某人是游荡近来,而并非从项目网页过来),提及相关的频道,并给出一些指导。

机器人(Bots)

许多面向技术的IRC频道有一个非人的成员,叫做机器人(bot),它可以对特定的命令返回信息。通常情况下,这个机器人就像频道中的其它成员一样,命令是通过谈话传递给的机器人。例如:

<kfogel> ayita: learn diff-cmd = http://subversion.tigris.org/faq.html#diff-cmd
<ayita>  Thanks!

这是告诉机器人(以ayita登入了频道)记住以特定的URL回答“diff-cmd”的提问,现在其他用户可以向ayita讯问,并获取diff-cmd的信息:

<kfogel> ayita: tell jrandom about diff-cmd
<ayita>  jrandom: http://subversion.tigris.org/faq.html#diff-cmd

通过速记法可以得到同样的结果:

<kfogel> !a jrandom diff-cmd
<ayita>  jrandom: http://subversion.tigris.org/faq.html#diff-cmd

准确的命令集和行为方式各不相同。以上的例子来自ayitahttp://hix.nu/svn-public/alexis/trunk/),通常在freenode的#svn运行着一个实例。其它机器人包括Dancer(http://dancer.sourceforge.net/)和Supybot(http://supybot.com/)。请注意,运行机器人无需服务器的权限。一个机器人就是一个客户端程序;任何人可以设置一个并监听特定的服务器/频道。

如果你的频道一次次的得到同样的问题,我强烈推荐你设置一个机器人。只有一小部分频道用户会获得需要处理机器人的专业技能,而这些用户会回答不成比例的大部分问题,因为机器人可以帮助他们有效率的回复。

归档IRC

尽管可以将IRC频道发生的任何事情都归档,但这不是必要的。IRC对话名义上是公开的,但是许多用户认为这是非正式的,半私密的对话。用户会对语法不是很在意,而且经常会表达意见(例如,关于其它软件或其他程序员),这些都不是他们希望永久保存归档的。

当然,有时候摘要必须能够保存。大多数IRC客户端可以在用户要求的情况下记录对话到一个文件,如果不能,人们也可以仅仅是将对华拷贝和粘贴到固定的论坛(经常是bug跟踪系统)中。但是不加区分的归档所有内容会让某些用户不悦。如果你需要归档所有的事情,请确认你已经在频道主题明确说明,并给出了归档的URL。

RSS供稿

RSS(Really Simple Syndication)是一种将元数据新闻摘要发布给“订阅者”(那些自己说明对某些摘要感兴趣的人)的机制。一个给定的RSS源通常被称作供稿(feed)而用户的订阅界面被称为供稿阅读器供稿聚合器。例如RSS Bandit和eponymous Feedreader两个开源RSS阅读器。

这里没有更多的空间解释RSS的技术细节[19],但是,你应当意识到两件事。首先,供稿阅读软件是由订阅者选择的,这个阅读软件会用来监控他的所有供稿 — 事实上,这正是RSS的主要卖点:订阅者选择一种界面使用他的所有供稿,而每个供稿只需要将精力集中于分发内容。第二,RSS现在是独一无二的,用的如此之多以至于很多人都不知道他们正在使用它。在世界范围内,RSS看起来像网页上的一个小按钮,标签上写着“Subscribe to this site”或“News feed”。你在按钮上点击,自此之后,你的供稿阅读器(可能是嵌入在你主页上的一个小应用)会根据自动从站点更新。

这意味着你的开源项目应当提供RSS供稿(注意,很多包装主机站点 — ,见the section called “包装主机” — 恰恰提供)。确保不要每天发布过过多的内容,以至于订阅者感到龙蛇混杂,找不到重点。如果有太多的新闻事件,人们会忽略供稿,甚至会激怒订阅者取消订阅。理想情况下,项目应该分开供稿,一个用来做较大的声明,另一个对应每一个邮件列表等等。在实践中,很难做好:不仅对访问项目网站的访问者和管理员都会造成界面混淆。但至少项目应该在首页提供一个RSS供稿,用于发送重要的声明和安全提醒。[20]

Wikis

一个wiki就是允许任何访问者都可以编辑或扩展其内容的站点;术语“wiki”(来自夏威夷词汇,意思是“快”或“非常迅速”)也用来特指支持这种编辑功能的软件。Wikis在1995年发明,但它们的流行是从2000或2001年开始的,一定程度上由维基百科(Wikipedia,http://www.wikipedia.org/)的成功推动,维基百科是以wiki为基础的自由内容的百科全书。可以把wiki看作介于IRC和网页之间:wikis不会实时发生,所以人们可以仔细考虑并润色他们的贡献,但是他们也可以很容易的添加,比正规的网页需要较少的界面操作。

wikis还不是开源项目的标准配置,但是可能很快就会。因为它还是相对新的技术,人们还在实验使用它的多种方式,这里我只提供一些劝诫—在本阶段,更容易分析wiki的误用,而不是他们的成功。

如果你决定运行wiki,需要花费很多力量在保持清洁的页面和可视化的布局上,这样访问者(也就是潜在的编辑者)才可以凭直觉知道如何提供贡献。同样重要的是,在wiki上发表这些标准,这样人们可以访问这些指导。经常是,wiki管理员成为幻想的牺牲品,他们相信因为大群访问者各自为站点添加高质量的内容,所以这些贡献的组合也是高质量的。但那不是网站工作的方式。每个单独的页面或段落可能单独看来不错,但是如果在一个没有组织的或迷惑的整体中它就不是了。wikis经常遇到的困境有:

  • 缺乏导航原则。一个组织良好的站点可以让访问者永远知道自己在哪里。例如,如果页面设计良好,用户会凭本能说出“目录”和“内容”区域的区别。wiki的贡献者也会尊重这种区别,但是这要求以这些区别作为开始。

  • 信息重复。wikis经常会变得有很多页面讨论相似的内容,因为每个单独的贡献者不会注意到重复。这可能部分由于缺乏前面提到的导航原则,人们可能无法在预期的地方找到重复的内容。

  • 不一致的目标读者。当有许多作者时,某种程度上这个问题是不可避免的,但是如果存在关于创建新内容的编写指南时可以减少这种情况。如果能够首先就做出贡献作为实例也非常好,这就成为标准被理解。

对所有这些问题的一般解决办法完全相同:有编辑标准,不仅仅是发表出来,而且要让编辑页包含它。通常情况下,wikis会放大原始材料中的所有缺陷,因为撰稿者会模仿任何眼前的模式。不要期望设置了wikis就会发现所有的事情来到恰当的位置。你还需要编写好例子,这样人们可以将其作为遵从的模板。

一个运行良好的闪耀实例是维基百科,尽管可能是部分因为它的内容(百科条目)本身就适合wiki的格式。但是如果你深入维基百科,你会发现管理员为合作提供了非常完整的基础。有关于如何编写新条目,如何维护合适的视角,做何种编辑,避免怎样的编辑,争议编辑解决过程(涉及许多步骤,包含最终的裁决)等问题的大量文档。他们也有授权控制,如果某个页面反复成为不当编辑的目标,他们会锁定它,直到问题解决。换句话说,他们不只是在网站上抛出了几个模板就希望坐享其成。维基百科能够成功是因为它的创建者仔细思考过如何让几千陌生人调整他们的写作来实现共同的梦想。虽然对于自由软件项目,你可能不需要同样级别的准备,但是其精神值得模仿。

关于wiki的更多信息可以看http://en.wikipedia.org/wiki/Wiki。另外,第一个wiki还活得很好,包含了许多运行wiki的讨论,在http://www.c2.com/cgi/wiki?WelcomeVisitorshttp://www.c2.com/cgi/wiki?WhyWikiWorkshttp://www.c2.com/cgi/wiki?WhyWikiWorksNot有许多不同的视点。

网站

从技术角度上看,对于设置项目网站没有可以多说的:设置网站服务器并编写网页都是相当简单的任务,大多数需要说的重要事情如布局和安排已经在前面的章节提过。网站的主要功能是为项目提供一个清新和友好的概况,并组合其他工具(版本控制系统、bug跟踪系统等等)。如果你没有设置网站的技能,通常不难能找到有能力的人乐意帮助你。虽然如此,为了节省时间和工作量,人们通常会选择一个包装主机站点。

包装主机

使用包装站点有两个主要的好处。首先是服务器容量和带宽:他们的服务器通常位于非常宽的管道上。无论你的项目多么成功,你都不会用完你的磁盘并消耗完网络带宽。第二个好处是简单。他们已经选择了bug跟踪、版本控制系统、邮件列表管理器、归档程序以及其他运行一个站点所需的所有东西。他们已经配置好了工具,并且会小心的备份其保管的所有数据。你不需要作出任何选择。你所需要的只是填写表单,点击按钮,你就立刻得到了一个项目网站。

这些是很明显的益处。坏处当然也有,你必须接受他们的选择和配置,即使有时候不同的方式更适合你的项目。通常情况下,包装主站可以通过特定较少的参数进行调整,但是你永远无法得到细致的控制,就像你自己搭建站点并对服务器有完全管理权限时的那样。

这里的一个完美例子是对生成文件的处理。特定项目网页可以是生成的文件—例如,有系统可以保持FAQ数据为易于编辑的原格式,而不是HTML、PDF、和其他可以生成的展示格式。本章后的the section called “版本化所有的东西”会有解释,你不会希望版本化这些生成格式,而只要保存原文件。但是当你的网站存放在其他人的服务器上,就不能设置一个自定义的钩子,当原格式文件变更时,来生成在线的HTML版本的FAQ。唯一的解决办法是也版本化生成的格式,这样,它们才可以在网站上展示。

也可能有更大的后果。你可能无法控制你所展示的内容。一些包装主站允许你自定义网页,但是站点的缺省布局通常是通过许多蹩脚的方法完成。例如,一些SourceForge上的项目拥有完全的自定义主页,但仍然将开发者指向他们的“SourceForge页面”来获得进一步信息。SourceForge页面是项目的主页,使得项目不能使用自定义主页。SourceForge页面包含到bug跟踪、CVS版本库、下载等链接。不幸的是,SourceForge页面也包含了太多外来的噪音。顶上有一个广告条,通常是一个图像动画。左面垂直布局的是项目中的某人感兴趣的一些相关链接。右侧可能是另一个广告。只有中央才是项目特定的材料,甚至让访问者无法确定下一步应该点击什么。

SourceForge设计的每个方面后面,无疑有一个好的原因—从SourceForge的视点是好的,例如广告。但是从每个项目的视点,结果可能不是一个理想的网页。我不是要招惹SourceForge;类似的关注会在许多包装主站出现。关键是代价。你省去了运行项目站点的负担,但是要接受其他人运行它的方式。

你唯一可以决定的是哪个包装主站适合你的项目。如果你选择了一个包装站点,可以保留将站点转移到你自己服务器的选项,通过使用自定义域名作为项目的“主地址”。你可以将URL转向到包装主站,或者你在公共URL上有完全自定义的主页,只在复杂功能时才将用户转移到包装主站。只要确保这样安排,如果之后你希望使用不同的主机方案,项目地址不需要改变。

选择一个包装站点

最大最著名的主机站点是SourceForgesavannah.gnu.orgBerliOS.de这两个站点提供了相同或类似的服务。一些组织,例如Apache Software基金会Tigris.org[21]也会为开源项目提供免费主机,但要符合他们的目标和他们社区已有的项目。

Haggen So对于各式包装站点有一个完全的评估,作为他的博士论文研究的一部分,Construction of an Evaluation Model for Free/Open Source Project Hosting (FOSPHost) sites。结果在http://www.ibiblio.org/fosphost/,还可以看非常易读的比较图http://www.ibiblio.org/fosphost/exhost.htm

匿名和参与

一个不仅是包装主战,而且许多其他地方也能看到的问题是对于用户登录功能的滥用。这个功能本身很简单:站点允许每个访问者自己通过用户名和密码注册。此后他就保存了一份用户信息,项目管理员可以为用户赋予特定的权限,例如,提交版本库的权利。

这非常有用,实际上这也是包装主站的一个好处。问题是有时候有一些附加给注册用户的任务本应该由未注册访问者执行,特别是如在bug跟踪系统发起问题和对已有问题进行回复。如果对此类活动要求输入登陆用户名,项目就为这类快速方便的任务设置了障碍。当然,人们希望可以联系到输入数据的人,但只要保留一个输入邮件地址(如果她愿意)的字段就够了。如果一个新的用户发现一个bug,并希望报告它,她会被在输入bug之前被要求填写帐户信息惹恼。她可能会放弃发起这个bug。

用户管理的好处被过高估计了。但是如果你可以选择哪些动作可以匿名完成,请确保不仅只有所有的只读动作对于未登陆用户是允许的,也包括一些数据条目动作,特别是在bug跟踪系统,可能的话还有你的wiki页。



[13] 在本书出现后不久,Michael Bernstein告诉我:“也有一些Mutt之外的其他客户端实现了reply-to-list功能。例如,Evolution的一个快捷键有这个功能,但不是一个按钮(Ctrl+L)。”

[14] 写到这里,我已经发现至少有一个列表管理系统提供了这个特性:Siesta。请看这篇相关的文章:http://www.perl.com/pub/a/2004/02/05/siesta.html

[16] 对于版本化configure的不同意见,可以看Alexey Makhotkin的文章,在http://versioncontrolblog.com/2007/01/08/configurein-and-version-control/的“configure.in and version control”。

[17] 没有要求或期望你能够为Freenode捐献,但是如果你或你的项目能够负担,请考虑贡献一下。他们在美国有一个免税的慈善团体,提供有价值的服务。

[18] 使用/topic命令设定频道主题。IRC频道中的所有的命令以“/”开头。如果你不熟悉IRC的使用和管理,可以看http://www.irchelp.org/;而http://www.irchelp.org/irchelp/irctutorial.html是一份完美的教程。

[20] 荣誉应当属于有功之人:这一部分并出现在本书的第一次发布版本中,但是Brian Aker的博文"Release Criteria, Open Source, Thoughts On..."提醒了我RSS对开源项目的作用。

[21] 免责生命:我由CollabNet雇佣,它是Tigris.org的赞助商,我经常会用Tigris。

Chapter 4. 社会和政治的基础架构

有关自由软件,人们经常问到的第一个问题是:“它能行吗?如何保持项目一直运行?谁来做决定?”我一直对关于知识界精化、合作精神、代码会说话此类的平淡回复无法感到满意。事实是这个问题很难回答。知识界精化、合作精神和运行代码只是其中的一部分,但它们对于解释日复一日的项目运转贡献不多,对于如何解决冲突什么也没说。

本章尝试展示支持成功项目的共同结构。 “成功”不仅仅指的技术质量方面,而且也包含了运行健康状况和生存性。运行健康状况是指项目将新代码和新开发者吸收进来,并对到来的bug负责的持续能力。生存性是项目独立于任何单独参与者或赞助商而存在的能力—考虑一下如果项目所有的创始成员离开后项目继续运作的可能性。技术成功不难实现,但是如果没有健壮的开发者基础和社会基础,一个项目就不能处理由初始的成功带来的成长,或者有魅力个体的离开。

获取此类成功有很多方法。有些涉及正式的管理结构,通过哪些争论被解决、新开发者被邀请加入(有时是离开)和计划的新特行等等。还有一些涉及不太正式的结构,但需要更有意识的自我克制,来产生一种人们可以依赖的正直氛围,作为事实上的管理形式。两种方式都产生相同的结果:一种由来已久的永恒感觉,由所有参与者都充分理解的习惯和程序作为支撑。这些特性在自我组织的系统中甚至比集中控制的系统更重要,每个人都知道一个坏苹果可以毁掉一桶,即使只是一会儿。

分叉能力(forkability)

能将开发者绑定在一个自由软件项目中的必需组成部分,能让他们在必要时愿意作出妥协,是代码的分叉能力:也就是任何人可以使用一个拷贝并使之成为一个竞争项目的能力,被称为分叉。怪异的是自由软件项目的中分叉可能性具备比实际的分叉更大的动力,很少会发生。因为分叉对于每个人都不好(Chapter 8, 管理志愿者the section called “分叉”会解释详细原因),分叉的威胁越大,越期望的人就越会妥协去避免它。

分叉,更确切说是分叉的可能性,是自由软件项目中没有真正独裁者的原因。考虑到在一个特定开源项目中听到某人被称为“独裁者”或者“暴君”是多么常见,这看起来是一个令人惊讶的断言。但是此类暴政是特别的,与一般意义上的字面理解非常不同。想象一下一个国王的臣民可以在任何时候复制整个王国,并搬过去按自己满意的规则统治。这与国王无论如何做,臣民都无法离开的情况是多么的不同?

这也是为什么即使项目不是完全按照民主方式组织时,在实践中,重要决定还是通过民主方式产生。可复制性暗指了分叉能力;分叉能力暗指了意见一致。也可能是每个人都希望与一个领袖不同(最有名的例子是在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需要修正,而这就是我做的修正。”当然,开发者不会真的这么说;她只是提交修正,而项目中的其他人无需表明立场,因为沉默代表了认可。如果有人提交的结果没有导致共识,结果就是项目会象这个变更没有提交一样进行讨论。这个方法可以正常工作的原因请看下一个小节。

版本控制意味着你可以放轻松

如果项目源代码已经纳入版本控制,这意味着大多数决定都可以轻易的取消。一个常见的情况是某人自以为提交了一个别人会喜欢的变更,但实际上并不如此。通常始于反对者对于遗漏某个预先讨论的道歉开始,当然,如果反对者在邮件列表归档中没有发现此类讨论的纪录,可以省略这一步。另一个方法是,变更是否已经提交没有理由影响我们讨论的基调。所有的变更都可以回退,至少在引入依赖的变更之前都没有问题(例如,在移除原来的变更后会破坏新代码)。版本控制系统让项目有能力收回错误或仓促判断的后果。这也释放了人们,使他们对于做任何事情之前所需要的反馈可以相信自己的直觉。

这也意味着达成共识的过程不需要非常正式。许多项目跟着感觉处理。小的变更可以直接引入,而无需讨论,或者只需要通过最少的讨论来点头确认。对于重要的变更,特别是有可能造成大量代码不稳定的变更,人们应当需要等待一两天才能达成共识,不应当因为某人没有足够频繁的检查邮件,而将其排斥在对话之外。

因此,当某人相信他知道应该做什么,他应当继续前进和完成它。这不仅仅适用于软件修正,也可以用于网站更新、文档变更和其他任何不会引起争议的事情。通常情况下,需要进行回退操作的情况很少,应当根据实际情况处理。当然,不应当鼓励人们刚愎自用。正在讨论和已经生效的决定会造成一定的心理差异,即使它在技术上是可逆的。人们一直认为动力等同于行动,相对于回退变更,人们更情愿在开始的时候阻止它。如果开发者滥用这个事实,过于快速的提交有争议的变更,不管怎样,人们可以也必然会抱怨,会将开发者置于更严格的标准,直到事情改进。

如果无法达成共识,那么表决!

不可避免的,一些争论无法达成共识。当打破死锁的所有其他方法都已经失效,最后的方案就是表决。但是,在表决之前,一定要理清表决的选项。这里一切又重演了,技术讨论的正常过程会混合项目决策程序的偶然发现。此类需要表决的问题通常会很复杂,具有多方面的问题。在所有此类复杂讨论中,需要有一两个人扮演诚实的中间人的角色:定期发布各种论点的摘要,并保持对于分歧(和一致意见)核心论点的跟踪。这些摘要可以帮助每个人评估所做工作的进展,并提醒每个人还需要解决什么问题。如果需要表决,这些摘要也可以作为表决表格的原形。如果诚实中间人的任务完成的好,当时机成熟就可以发布表决的可信请求,而团队会希望使用以他们对于此问题的摘要为基础的表决表格。中间人自己也可以参与辩论;只要他们可以理解并公平的表示其他人的观点,不会因党派观点而影响以中立地态度总结辩论的状态,就没必要让他们脱离争论。

表决的实际内容通常不应当是有争议的。当表决时刻到来,分歧通常会归纳为一些包含可识别的标签和简短描述的关键问题。偶尔某个开发者会反对表决本身的形式。有时候他的考虑是有道理的,例如,一个选项被遗漏了或描述的不够精确。但是还有一些时候,开发者仅仅希望避开这个表决,因为他知道表决不会得到自己期望的结果。如何处理此类蓄意阻挠可以看Chapter 6, 交流the section called “刺儿头”

要记住指明表决系统,因为有许多不同的类型,人们很容易错误的假定使用某个步骤。大多数情况下的较好选择是同意表决(approval voting),也就是每个表决者可以选择多个中意的选项。同意表决易于解释和统计,也不会像其他方法那样,它只有一轮表决。关于同意表决和其他表决系统的更多细节可以看http://en.wikipedia.org/wiki/Voting_system#List_of_systems,但是要避免陷入使用何种表决系统的长期辩论(因为,当然你会发现你陷入了使用何种表决系统选择表决系统的辩论!)。同意表决是正确选择的一个原因是任何人都很难反对—作为表决系统它足够公平。

最后,公开引导表决。没有必要对公开讨论的事务进行秘密或匿名的表决。让每个参与者在项目邮件列表中发布自己的表决,这样每个观察者都可以自己检查结果,而且所有的内容都会记录到归档中。

何时表决

最难的事情是决定何时开始表决。通常情况下,很少会进行表决—是其他方法都失败后的补救方法。不要将表决当作解决争辩的重要方法。它不是。它可以终结讨论,也会结束关于此问题的创造性思考。只要讨论还会继续,就有可能会有人得出所有人满意的解决方案。这经常令人吃惊:活跃的争论可以产生关于问题的新方法,也会得出使每个人都满意的提议。即使没有出现新的提议,通常采纳某种妥协也比举行表决要好。经过妥协,每个人都或许会有点不高兴,但是表决过后,有些人会开心,还有些人会失望。从政治视角,前一种状态更可取:至少每个人都会感到为自己的不快萃取了一定的价值。他会不满意,但其他人也一样。

表决的主要优点是最终可以解决问题,这样每个人都可以继续前进。但是通过数人头,而不是通过有理性的对话解决问题,导致每个人得出相同的结论。开源项目中的人越有经验,就会越发现他们越不会急于用表决解决问题。相反,他们会尝试考察以前未考虑的解决方案,或者对以前计划的方法进行较大的妥协。有许多技术手段可以防止过早的表决。最明显的方法是说“我觉得还没有准备好开始表决,”然后解释为什么还不行。另一个方法是要求进行非正式(无约束力的)的举手表决。如果结果明确倾向到一边,就会让某些人立刻更希望进行妥协,以避免正式的表决。但是最有效率的方法是简单的提供一个新的方案,或者一个较早建议的新视点,所以人们可以重新审视问题,而不是简单的不断重复同样的论点。

在某些很罕见的情况中,每个人都认为所有折中的解决方案都比任何一个非折中方案要差。当这种情况发生时,表决就会有较少的异议,不仅仅因为它能够得到一个高人一等的解决方案,而且是因为这样不会导致所有人对结果感到不高兴。尽管那样,表决也不应该匆忙进行。导致表决的讨论可以教育全体选民,所以过早的结束讨论会降低结果的质量。

(要注意前面所说的表决建议不适用于Chapter 7, 打包、发布和日常开发the section called “稳定发布版本”中描述的变更包含表决。此时,表决更像是一种交流机制,一种在变更评审过程注册某人参与的方法,这样每个人都可以说出对于一个变更收到了多少评审。)

谁进行表决?

有了表决系统就会出现一个全民选举的问题:谁应该表决?这有可能成为敏感的问题,因为它强制项目正式识别出一些更应该参与的人,也就是比其他人更有判断力的人。

最好的方法是采用已存在的划分,提交访问,并为他们附加表决特权。在提供完全和部分提交访问的项目中,部分提交者是否可以表决的问题,很大程度上取决于部分提交访问被赋予的过程。 如果项目自由处理,例如,在版本库中维护许多第三方贡献工具的方法,那时就应当澄清部分提交访问只是关于提交,而不是表决。相反的暗示自然也成立:因为完全提交者有提交特权,他们应当不仅仅是程序员,而且是全民选举的成员。如果某人在邮件列表中有分裂或破坏倾向,那么要小心将其加为提交者,即使这个人在技术上非常娴熟。

表决系统本身应当用来选择新的提交者,包括完全和部分提交者。但这是一个不太常见的需要注意保密性的情况。你不能为一个潜在的提交者在公共邮件列表表决,因为不能伤害候选者的感情(和荣誉)。相反,通常的方法是某个现有的提交者在只包含提交者的私有邮件列表中发布一个私有邮件,建议给某人附加提交权限。其他提交者可以自由发表意见,他们清楚讨论是私下进行的。通常没有异议,因而没有表决的必要。在等待几天之后,确保每个提交者有机会回应之后,提议者通知候选者并赋予其提交权限。如果存在异议,因而出现其他问题的讨论,可能会导致表决。因为这个过程需要开放和坦白,所以发生讨论的事实应当完全保密。如果被考虑的人知道事情的进展,然后没有提供提交权限,他可能认为他已经在表决中失败,会感到受到伤害。当然,如果某人明确的要求提交权限,没有其他的选择,要么同意,要么拒绝。如果是后者,应当尽量的有礼貌,并使用清晰的解释:“我们喜欢你的补丁,但是还没有看到足够的补丁,”或者“我们感谢你的补丁,但是在实际使用之前需要相当大的调整,所以我们觉得现在还不能放心给你提交权限。我们希望下一次会有些改观。”请记住,你所说的会是一个打击,这要看个人的自信心水平。应当从他们的角度想想如果你看到那些邮件的感觉。

因为添加新提交者不是那种一次性决定,会有后续的结果,某些项目会有表决的特殊要求。例如,他们会要求提议至少获得n个肯定的表决,而且没有否定的表决,或半数以上的赞同票。精确的参数并不重要;主要的思想是在添加提交者时需要让团队小心处理。类似的,或更严格的,特别的需求也可以应用到选举移除提交者上,尽管很希望那永远没有必要发生。关于添加和移除提交者的非表决方面的信息可以看Chapter 8, 管理志愿者the section called “提交者”

民意调查与表决

对于特定类型的表决,有时候扩展选民会很有用。例如,如果开发者只是不能确定哪种界面符合人们实际使用软件的方式,一个方法就是询问项目邮件列表中的所有人进行表决。这更应该叫做民意调查而不是表决,但是开发者可能将结果视为有约束力的。在任何民调中,要确保参与者可以附加选项:如果某人对于民调问题想到了更好的选项,她的回应会成为最重要的民调结果。

否决权

某些项目允许一种特殊的表决类型,称为否决权。否决权是一种开发者停止仓促或考虑不够充分变更的方法,至少希望每个人能够再进行一些讨论。考虑到否决权介乎于强烈反对和阻挠之间。它确切的含义对于每个项目都不尽相同。有些项目让否决很难被逾越;有些则允许经过强制的更多讨论延迟后,被普通的多数投票替代。任何否决必须伴随完整的解释;任何没有这类解释的否决都应当被认为是无效的。

否决权会带来对其的滥用。有时候开发者会急迫的通过否决权来为自己的论点加重砝码,而真正需要的是更多的讨论。你可以通过自己对于否决权的勉强使用来防止对于否决的滥用,并有礼貌的警告某人太过频繁的使用否决权。如果必要,你可以提醒团队,否决权只在团队也认可的时候有效—毕竟,如果很明显大多数开发者希望X,那么就应该采纳X。否决的开发者要么自己让步,要么让团队决定削弱否决权的作用。

你可能会看到人们写了一个“-1”来表示否决。这种方法来自拥有高度复杂表决和否决过程的Apache软件基金会,具体内容可以看http://www.apache.org/foundation/voting.html。Apache标准也传播到了其他项目,你可以看到他们的习惯在开源世界的许多地方以不同的面貌出现。从技术上讲,即使根据Apache标准,“-1”也不是表示正式的否决,而只是一种表达否决或强烈反对的非正式方法。

类似于表决,否决权也可以是追加的。如果有问题的变更已经提交,行动已经执行(除了一些不可挽回的事情,例如新闻发布),不应该以此为理由反对一个否决。另一方面,如果否决在事情发生几周后才出现,它也不会被重视,而且这种情况根本不应该发生。

写下所有的内容

有时,项目中的许多广为流传的惯例和协定变得非常重要,你需要记录下来。为了保证这种文档的正统性,要清楚的表明这些内容基于邮件列表的讨论,并已经形成协定开始生效。随着你的编写,应当引用邮件列表归档中的相关讨论,对于任何不能确定的要点,要重新询问并确认。文档中不应当包含任何出其不意的东西:它不应当是协议的来源,而只是对于协议的描述。当然,如果它足够成功,人们会开始引用它来作为自己权利的来源,但是这只是说明它精确的反映了团队的整体意愿。

这是Chapter 2, 起步the section called “开发者指南”暗示的文档。当然,当项目还非常年轻时,你无法依靠项目的历史来规划指导方针。但是随着开发社区的成熟,你可以调整这些语言以反映实际的内容。

不要尝试全面。没有文档能够涵盖参与一个项目所需的所有事情。许多项目演进出的习惯是永远不会说出来的,永远不会明确提出来,即使是所有人遵循的。还有一些内容则明显太过简单,无需提及,只会分散人们对于重要内容的注意力。例如,没有必要写下指导方针如“在邮件列表中要有礼貌,要互相尊重,不要激烈的争论”或“要写清楚的、可读的和无bug的代码。”当然,这些事情都是人们希望的,但是因为没有想像到他们可能不会渴望得到的东西,所以没有价值去提及。如果人们在邮件列表中过于粗暴,或编写了充满bug的代码,不会因为项目指导方针没有说,他们就会继续下去。这种情形出现时就会需要被处理,不会因为预先的劝诫就会好起来。另一方面,如果项目有关于如何写好代码的指导方针,例如关于使用何种格式记录API的规则,那么这个指导方针就应该尽可能的写完整。

决定将什么内容纳入文档的最好方法是以新来者所经常询问的问题,以及资深开发者最经常的抱怨为基础。这不是说一定要变成一个FAQ表单—很可能需要一个比FAQ所能提供的更连贯的叙述结构。但是它必须遵循事实为根据的原理,记录问题实际发生的地址,而不是好像你预期会出现。

如果项目是一个慈善独裁者所有,或者有拥有特殊权利的官员(总裁、主席或其他),那么继任程序也应当制定成法律形成文档。有时候,这仅仅是BD因故突然离开项目并简单的指定继任者。通常情况下,如果有一个BD,那么只有BD可以离开并提名继任者。如果有竞选的成员,那么文档就应该描述从中取出第一名的提名和选举程序。如果原来没有程序,那么在编写应该在邮件列表中达成共识。人们有时候可能对于等级结构十分敏感,所以主题应当敏感的达到这个目标。

可能最重要的事情是表明规则是可以商量的。如果文档中规定的习惯变得束缚了项目,要让每个人想到这是一种对于团队意愿的生动反映,而不是挫折和堵塞的来源。如果某人养成了每当遇到妨碍自己的规则都要求重新考虑规则的习惯时,你不需要一直与其辩论—有时候沉默是最好的策略。如果其他人认可这种抱怨,他们会插话,也就是意味着某些事情很明显需要改变了。如果没有其他人认可,人们就不太会响应,那规则还是会保持不变。

两个指导方针的好例子是Subversion的hacking.html文件,在http://svn.collab.net/repos/svn/trunk/www/hacking.html,以及Apache软件基金会管理的文档,在http://www.apache.org/foundation/how-it-works.htmlhttp://www.apache.org/foundation/voting.html。ASF是真正的一组软件项目,合法的组织成一个非盈利公司,所以它的文档倾向于描述管理程序,而不是开发惯例。他们也值得阅读,因为他们代表了许多开源项目积累的经验。

Chapter 5. 金钱

本章仔细检查了如何为自由软件环境带来资金。这不仅仅是在自由软件中被支付工资的开发者的目标,也是他们的经历,那些需要理解开发环境社会动态性的人的目标。在接下来的章节中,假定收件人(你)是被付费的开发者,或者是管理这类开发者的人。对于二者的建议基本相同;如果不同,有意的读者可以从上下文中分清。

对自由软件开发来说,公司投资已经不是一个新的现象。许多开发被非正式的资助。当一个系统管理员写了一个网络分析工具来辅助她的工作,然后把它发布到网络,接受来自其他系统管理员的bug修正和特性贡献,这就产生了一种非正式的合作组织。这个合作组织的资金来自系统管理员的薪水,而它的办公室空间和网络带宽是捐助的,尽管是通过其所工作的默默无闻的组织。这个组织从投资中获益,当然,尽管开始时他们不会意识到这一点。

现在的一些变化是这种力量已经更加正式。公司已经观察到开源软件的好处,在他们自己的开发中直接参与其中。开发者也更能预期真正重要的项目至少能获取到捐助,甚至可能是长期的赞助。而金钱的出现并没有改变自由软件开发的基本动力学,它已经极大地改变了发生事情的范围,无论是从开发者的数量来说,还是每个开发者贡献的时间。对于项目的组织,以及参与者的交互也有影响。这个问题不仅关于金钱如何花费,也关于如何测量投资回报。他们也关于管理和过程:公司层级指挥结构和自由软件项目中半集中的志愿者社区能够以相近的生产率工作?他们认可“生产率”的含义?

财政支持通常会受到开源开发社区的欢迎。它可以减少项目面对混乱势力的弱点,这一点经常让项目在起飞之前就被清除,因此它可以让人们更希望给软件一个机会—他们感到正在一项至少会再干6个月的工作上花费时间。毕竟,可靠性从来都是最有感染力的因素。假定IBM支持了一个开源项目时,人们就会更容易设想这个项目不会失败,而他们的因此所自发的投入反而会去实现这个会成为事实的预言。

然而,资金也会带来控制的感觉。如果处理不好,金钱会让项目分裂为圈内和圈外开发者。如果未付酬的志愿者感到设计决策或特性添加仅仅是由出价最高者决定的,他们会转而投向那些感觉更像是由知识精英管理的,不象是为了某个他人利益进行未付酬劳动的项目。他们绝不会在邮件列表中公开抱怨。相反,随着志愿者逐渐不再努力被重视,来自外部的声音也会越来越少。小规模活动的吵闹还会继续,会以bug报告和偶尔的小修订形式出现。但是再也不会有任何大规模的代码贡献和来自外部的设计讨论参与。人们意识到他们是如何被期望的,而且也会按照这个预期行事。

尽管需要小心的使用金钱,并不意味着不能购买影响力。大多是可以的。技巧是不能直接购买影响力。在一个直接的商业交易中,你使用金钱交换你所需要的。如果你需要添加一个特性,你签署一个协议,为此付款,然后它就会被实现。在开源项目,不会如此简单。你可以与某些开发者签署协议,但是他们需要欺骗自己—和你—如果他们保证你付费的工作会被开发社区接受,仅仅因为你为此付了费。这个工作只应该根据事实,以及与社区对于此软件的长远规划的符合程度来完成。你可以对这个长远规划发表意见,但你不应该是唯一的声音。

所以金钱不能购买影响力,但是可以购买导致影响力的东西。最明显的例子是程序员。如果雇佣了好的程序员,他们逗留了足够长的时间,以获取社区中的软件经验和信誉,那么他们就可以使用其他成员一样的方式影响项目。他们会有一个投票,或者如果人数太多,他们会有投票集团。如果他们在项目中受到尊重,他们会有超越投票的影响力。被支付的开发者没有必要掩盖他们的动机。毕竟,每个希望修改软件的人都有自己的目的。你公司的原因并不比其他人的缺乏道理。只是给与公司目标的砝码取决于代理人在项目中的状态,而不是公司的规模、预算或商业计划。

参与的类型

开源项目被资助有许多不同的原因。这个列表中的条目并不互斥;通常一个项目的财政支持会出自这里的多个,甚至全部的动机:

分担负担

拥有相关软件需要的不同组织经常会发现他们在重复投入,包括在内部重复编写类似的代码,以及从私有供货商购买类似的产品。当他们意识到事实真相后,这些组织会集中他们的资源,并创建(或加入)到一个开源项目,并为他们的需要调整。好处是明显的:开发的代价被分担了,而对所有人利益则增长了。尽管这个场景凭直觉应该大多数是非盈利组织所做的,但是即使对于盈利竞争者也具有战略意义。

例如:http://www.openadapter.org/http://www.koha.org/

提高服务

当一个公司出售的服务依赖于某个开源程序,或因为某个开源程序而更加具有吸引力,很自然这个公司会有兴趣保证程序能够活跃的维护着。

例如:CollabNet对于http://subversion.tigris.org/的支持(免责声明:是我的日常工作,但是也是这个模型的完美实例)。

支持硬件销售

计算机和计算机组件的价值和之上的软件直接关联。硬件销售商—不仅是整机销售商,还包括外围设备和芯片制造商—都发现让高质量的自由软件运行在他们的硬件上对客户来说非常重要。

暗中削弱竞争者

有时候公司支持特定的开源项目作为对竞争者产品的暗中破坏,无论竞争产品本身是否开源。争夺竞争者的市场份额通常不是参与开源项目的唯一原因,但却是一个因素。

例如:http://www.openoffice.org/(不,这不是OpenOffice存在的唯一理由,但是这个软件至少部分的回应了微软的Office)。

市场营销

让你的公司与流行的开源应用联系在一起,是简单而且好的品牌管理。

双重许可证

双重许可证会为希望将软件作为自己私有软件的一部分进行销售的客户提供传统私有许可证,同时为开源范围使用的客户提供自由许可证(见Chapter 9, 许可证,版权和专利the section called “双许可证模式”)。如果开源开发者社区是活跃的,软件可以广泛领域获得调试和开发的好处,尽管公司仍然保持支持一些全职程序员的特许权。

两个著名的例子是MySQL,相同名称数据库软件的制造商,以及Sleepycat,提供Berkeley数据库的发布和支持。他们都是数据库公司并不是巧合。数据库软件通常会集成到应用中,而不会直接交给用户,所以非常适合双重许可证模型。

捐赠

一个广泛使用的项目有时可以获得可观的捐助,包括来自个人和组织的,只需要有一个在线的捐赠按钮,或者有时通过销售诸如咖啡杯、体恤和鼠标垫之类的品牌商品等等。小心一点:如果你的项目接受捐赠,在得到之前要计划好如何使用这些钱,并在项目网站中注明。在实际花费之前保留,可以让关于如何分配钱的讨论变得十分顺利;但不管怎样,如果有明显的分歧,最好把它找出来,这还是很学术的东西。

投资者的商业模型不是它与开源社区如何联系的唯一因素。二者的历史关系也很重要:这个公司开始了这个项目,或者它联合了现有的开发力量?在这两种情况下,投资者都需要赢得信誉,但是,不令人意外,在后一种情况下需要的更多。组织需要对项目的未来有清晰的目标。公司希望保持领导地位,或仅仅是成为社区的一个声音,从而能够引导而不必控制项目的方向?或者它只是希望有一些提交者,能够修复客户的bug并能够不费吹灰之力的将变更置入公共版本?

当你阅读后面的指导方针时要留意这些问题。他们可以应用到自由软件项目中的此类组织参与,但每个项目都是一个人类环境,因此没有完全相同的。在某种程度上,你需要跟着感觉演奏,但是遵从这些原理会增大结果符合你想法的可能性。

长期雇佣

如果你正在管理开源项目中的程序员,要尽量保持足够的时间,这样他们才能获得足够的技术和政治技能—最少也需要几年时间。当然,没有项目,无论是开源还是闭源,都可以从轮换程序员中获益。新来者搞清楚窍门需要的时间在不同环境下各不相同。但是在开源项目中的代价更加巨大,因为离开的开发者不仅带走了他们的知识,也带走了社区中的他们的地位和其中建立的人际关系。

开发者已经积累的信誉不能够传递。一个新来的开发者不能继承来自离开者的提交权限(可以本章后面的the section called “钱不能让你可爱”),如果新的开发者还没有提交权限,在获得这个权限之前它只能提交补丁。但是提交权限只是所失去的影响中最容易度量的表现。一个长期的开发者也知道邮件列表中所有以前达成和未达成一致的讨论。一个新的开发者,没有这些对话的记忆,也许会再次发起某些讨论,这会损失在组织中的信誉;其他人会奇怪为什么“他们什么也记不住?”新的开发者也对项目特性没有太多政治感觉,所以也不能象老手一样迅速和平滑的影响开发方向。

通过指导契约的程序来训练新手。新的开发者第一天就可以与公共开发社区直接交流,从bug修正和清理任务开始,这样他们可以逐渐熟悉代码基并在社区获取声誉,尽管此时他们还不能在设计讨论中蹦出火花。一个或多个有经验的开发者应当一直负责解惑的任务,阅读新手在开发列表中的每一篇帖子,即使是经验丰富的开发者通常不会注意的内容。这可以帮助团队在新手搁浅之前定位潜在的暗礁。私下的幕后鼓励和忠告也会非常有益,特别是当新手不习惯大量的代码平行同级评审的时候。

当CollabNet雇佣新的开发者为Subversion工作时,我们会坐在一起为新人找一些打开的bug来练练手。我们会讨论解决方案的技术要点,并让至少一个有经验的开发者来评审(公开的)新开发者的补丁(也是公开的)。我们通常不会在主开发列表公开之前查看这个补丁,虽然,如果情况特殊,我们可以如此。重要的是,新开发者经历公开评审的过程中,在熟悉代码基的同时,也需要习惯于接受来自完全是陌生人的批评。但是我们会调整时机,保证我们的评审会在补丁发出之后立刻出现。这样列表中出现的第一个评审就是我们的,这可以帮助我们确立其他评审的基调。它也可以加强一个概念,也就是这个新人需要认真对待:如果其他人看到我们花时间提供详细的评审,并包含完整的解释和归档中合适的参考,他们会意识到正在进行一种培训,并意味着一个长期的投资。这可以帮助他们对那个开发者保持正面的态度,至少会花费更多的时间回答问题和评审补丁。

作为一些个体出现,而不是一个整体

你的开发者必须力求在项目的公共论坛中以一个单独的参与者出现,而不是一个单独的公司。这不是因为作为一个公司出现本身固有的一些负面含义(好的,或许有一些,但那不是本书所讨论的)。而是因为开源项目的结构配备只能处理个人实体。一个单独的贡献者可以讨论、提交补丁、获取信誉、表决等等。而一个公司不能。

此外,因为分布式的行为方式,你避免了对于刺激性中央集权的敌对。让你的开发者在邮件列表中意见并不一致。鼓励他们经常评审他人的代码,尽可能的公开,就象他们是任何其他的人。阻止他们象一个集团一样表决,因为如果你这样做,其他人就会感觉到,根据一般的原理,一定有一个有组织的力量在控制他们。

实际的非中央集权和假装的是有区别的。在特定环境下,让你的开发者协同一致会非常有用,而且如果必要还必须在幕后进行协调。例如,当发出提议时,让许多人尽早跳出来表示认可,得出正在达成共识的印象会有助于提议的进展。其他人会感到提议的动量,如果他们反对,他们需要阻止这个动量。因此,人们只会在有好的原因时才会提出反对。如果能够慎重对待反对意见,这样的精心安排也没有错。私下协议的公众表现不会因为经过预先的协调而变得不够诚实,只要他们没有用这个方法来扼杀反对意见就不会有太多害处。他们的目的仅仅是阻止那些喜欢保持个性的人提出反对意见;更多相关内容可以看Chapter 6, 交流the section called “主题越软,辩论越长”

公开你的动机

尽可能公开你的组织的目标,不要因此而让商业秘密妥协。如果你希望项目能够获得某个特定的特性,例如你的客户要求这个特性,那么就应该在邮件列表中坦率的说出来。如果客户希望保持匿名,实践中这种情况很多,至少要询问一下客户是否愿意以未命名的方式使用他们的实例。开发社区对于你为什么这样做的原因了解越多,就会对你提议的事情越感到舒服。

这与直觉背道而驰—得到容易甩掉难—知识就是力量,你的目标别人知道的越多,他们就越有可能超越你的控制能力。但是那种直觉在这里并没有错。通过公开支持这个特性(或是bug修正或其他任何东西),你已经亮出了底牌。现在唯一的问题是你能否成功的引导社区来分享你的目标。如果你仅仅是表明你需要它,而不能提供任何表明原因的切实例子,你的论点就会很脆弱,而人们会开始猜疑其隐藏的动机。但是如果你能够提供现实的场景来展示为什么提议的特性是重要的,就可以有力的影响辩论的效果。

为了看清楚这样做为什么有效,考虑另外一种选择。关于新特性或新方向的讨论会非常耗时和烦人。人们提出的论点经常会变成“我个人希望X,”或曾经流行的“根据我多年作为软件设计师的经验,对用户来说,X是极端重要的/一个无用的花边功能不会让任何人满意。”可以预料到,现实用例的缺乏不仅不会缩短或缓和这种辩论,而会扯得离实际用户体验越来越远。如果没有一些增补的力量,那么最终的结果很可能需要由口才最好、坚持最久或地位最高的人决定。

对于有许多客户数据的组织,你有机会提供这种增补的力量。你可以作为无法达到开发者社区的数据的信息管道。不必因为那些支持你愿望的信息事实而感到窘迫。大多数开发者个人没有他们所写软件如何使用的广泛经验。每个开发者都会按照自己的怪异方式使用软件;只要有其他的使用模式,她就会凭直觉并臆断之,而且事实上,她们知道这一点。通过提供包含可观用户数量的可信数据,你就象为整个公共开发社区提供了氧气。只要你提供的例子是正确的,他们就会狂热的欢迎它,就会推动事情往你希望的方向发展。

关键是提供正确的例子。不要因为你要应付大量需要某特性(或以为他们需要)的用户,就坚决要求你的特性,也就是你的解决方案必须实现。相反,你必须将你最初的帖子关注于问题,而不是一个特定的解决方案。详细描述你的客户遇到问题的细节,尽可能提供你已经完成的分析,以及你能想到的可行性方案。当人们开始考虑不同方案的效果时,你可以继续通过提供数据来支持或反对她们的意见。你在心里可以有一个特定的解决方案,但是不要在开始单独提出来以期望获得特殊的考虑。这不是欺骗,这只是标准的“诚实代理人”的行为。毕竟,你的真正目标是解决问题;一个解决方案只是达到目标的一种方法。如果你选中的解决方案确实更好,其他开发者最终会识别出来—她们会出于自愿的跟进,肯定比你通过威逼她们实现更好。 (当然,也有可能她们找到了更好的方案。)

这不是说你不能说出你看好某个方案。但是你必须耐心的查看你所做的分析反复成为公共开发列表的中心。不要在列表中说“是的,我们试过这种方式,但是因为原因A、B和C,它是行不通的。当你彻底了解它后,解决它的唯一办法是...”问题不是它听起来很傲慢,而是让人觉得你对此问题已经研究了许多未知的(但是,人们会假设有很多)分析资源,只是一切都在门后面。它让人觉投入的精力白费了,或许已经做出了决定,而公众都不是有利害关系的人,这是招致怨恨的好方法。

自然,知道你自己在某个问题上所投入的力量,而这些知识从某种意义上来说是一种劣势。它让你的开发者处于和邮件列表中的其他人些许不同的心理空间,减弱了开发者从那些普通人的视角看待这个问题的能力,这些普通人没有像开发者那样考虑过这个问题。你越早能够让所有人用与你相同的术语考虑问题,这种差距就会越小。这种逻辑不仅适于个人技术情形,而且适用于更广泛的让你的目标尽可能清晰的授权。未知总比已知的更不稳定。如果人们理解了为什么你希望你所希望的,即使他们不认可,在与你交谈时也会感到舒服些。如果他们不能指出何事让他们愤怒,他们会假定最坏的情况,至少有时候。

你不能宣传所有的事情,当然,人们也不会期望你如此。所有的组织都有秘密;或许会因为利益,但是没有利益也会如此。如果你必须发起这样一个过程,而无法揭示任何原因,那就提供你在这种不利条件下最好的论点,并接受你将不会在讨论中获得你期望影响力的后果。这是让你不必为开发社区支付薪水的一个折衷手段。

钱不能让你可爱

如果你的项目有付费的开发者,一定要尽早设置钱可以购买什么东西的指导方针。这并不意味着你需要每天在邮件列表中说明两次来重申你的高尚和不腐的本性。你只需要在恰当的时机放松由钱导致的紧张。你不需要从一开始就假设存在这种紧张;你只需要说明有这种可能性。

一个完美的例子就是Subversion项目。CollabNet在2000年开始了Subversion,从一开始它便是项目主要的投资者,为多个开发者提供薪水(免责声明:包括我)。项目开始后不久,我们雇佣了另一个开发者Mike Pilato,参与开发工作。此时,编码工作已经开始。尽管Subversion还处于早期阶段,但已经有了一个开发者社区和许多基本的规则。

Mike的到来突现了一个有趣的问题。Subversion已经有了开发者如何获得提交权的政策。首先,他需要在开发邮件列表中提交一些补丁。当有了足够的补丁后,其他提交者看到新贡献者知道自己所做的事情,某人就会提议他直接提交(这个提议是私下的,就像the section called “提交者”所描述的)。如果提交者们同意,其中的某人就会邮件通知新的开发者,并为他设置直接提交访问项目版本库的权限。

CollabNet是专门为Subversion项目雇佣了Mike。他们已经对他足够了解,对于他的编码技巧和在此项目所作的准备毫无疑问。此外,志愿者开发者已经与CollabNet雇员有了非常好的关系,看起来如果我们直接在雇用Mike当天就赋予他权限也不会有什么反对意见。但是我们知道我们正在设置一个先例。如果我们按命令给Mike提交权利,我们会说CollabNet有权无视项目的指导方针,只是因为它是主要的投资者。这种行为的害处未必立刻显现出来,它会导致非付费开发者逐渐感到被剥夺了投票权。其他人自己赢得他们的提交权利—而CollabNet只需要花钱买。

所以Mike赞成象其他志愿开发者一样,在没有提交权限的情况下开始了在CollabNet的雇佣工作。他在公共列表中发布补丁,在其中可能会受到,实际上也确实受到了所有人的评审。我们在列表中也说过我们是故意这样做的。经过Mike数周的扎实活动,某人(我不记得是否是CollabNet开发者)提议给他提交权限,而他被接受了,当然,我们知道他会被接受。

那种类型的一致性会让你确信钱不可以买到一切。这种确信是技术讨论中珍贵的流通货币:可以免于以后让某人的动机被怀疑。在辩论最激烈时,人们有时会寻找非技术的方式来赢得战斗。项目的主要投资者,因为涉足较深并且显然会对项目采取的方向十分关注,会展示出比大多数人更广的目标。通过从一开始就一丝不苟的遵守项目方针,投资者就可以获得和所有人一样的影响力。

(Danese Cooper的blog上http://blogs.sun.com/roller/page/DaneseCooper/20040916有关于提交权限的类似故事。Cooper是Sun Microsystem的“开源Diva”—我相信这是她的官方头衔—在她的blog中,她描述了Tomcat开发社区让Sun在控制提交权限时对Sun的人员和非Sun的人员一视同仁。)

创始人对所有人使用相同规则的需要意味着慈善独裁统治模型(见Chapter 4, 社会和政治的基础架构the section called “慈善独裁者”)在投资面前有一点难于实施,特别是独裁者为主要的投资方工作的情况。因为独裁有一些规则,投资者很难证明遵守了社区标准,即使事实如此。这确实不是不可能;只是需要项目领导者既能够从投资方也能够从外围开发者的视角看待事物,并依此行动。即使那样,也最好能在后口袋有一个非独裁管理的提议,准备好在社区的不满扩散时掏出来。

契约

在自由软件项目中的契约需要小心处理。理想状况下,你希望一个承包者的工作被社区接受并打包进入公共发布版本。在理论上,谁是承包者并不重要,只要他的作品足够好并满足项目的指导方针。理论和实践一般也是一致的:一个通过贡献好的补丁展示自己的完全陌生人通常能将代码置入软件当中。问题是,一个完全的陌生人很难为非琐碎的改进或新的特性贡献好的补丁;一个人必须首先和项目的其他人进行讨论。讨论的时间不能精确预测。如果承包者根据小时付费,你最终可能会付出超过预期的费用;如果他是通过总费用支付,那么他最终会做出超过承受能力的工作。

这里有两种方式。较好的一个方法是根据以前的经验,对讨论过程的长度做出一个有根据的推测,并要考虑到出错的延误,并根据这些信息完成契约。这也有利于尽可能的将问题分离为许多小的独立的区块,增加每个区块的可预测能力。另一个方法是为每一个发布的补丁单独契约,然后将补丁的被接受当作公共项目一个独立的事件。这样编写契约就可以很容易,但是只要你依赖这个软件,或至少在这个补丁或对应功能进入主线的这些时间里,你必须承担维护单个补丁的责任。当然,即使是你中意的方法,契约本身不能要求代码必须可以接受补丁,因为那会包含出售一些不能销售的东西。 (如果项目的余下成员不希望对这个特性提供支持?)然而,契约可以要求真诚地投入以获得社区接受的机会,也就是在社区认可的情况下被提交到版本库。例如,如果项目编写了代码变更的标准,契约可以参考这个标准并指明作品必须达标。在实践中,这通常会超出每个人期望的方式。

最好的策略是雇佣项目的一个开发者—最好是提交者—作为承包者。这可以看作是购买影响力的一种形式。但是并不是表面上那样的不道德。一个开发者对于项目的影响力主要取决于他的代码质量和与其他开发者的交互。他作为承包者完成特定工作的举动并不会提升他的状态,当然也不会降低,尽管这样会让人们对他更加仔细的审视。大多数开发者不会因为返回不当或广泛反对的新特性而让自己的长期位置经受风险。实际上,当你雇佣一个这样承包者时,一定程度上你会得到,或者说一定会得到一些关于哪些变更会被社区接受的忠告。项目的优先级也会得到些许转变。因为优先级只与哪个人有时间完成哪个任务有关,当你为某人的时间支付时,会导致他们工作的优先级提前一些。这是经验丰富的开源开发者都理解的一个事实,至少他们中的某些人会将精力投入到承包者的工作上,仅仅因为它看起来将要完成,所以他们希望去帮助正确完成。或许他们不会编写任何代码,但是他们还是会讨论设计并评审代码,这些都非常有用。出于以上原因,承包者最好是那些已经参与到项目的人。

这样立刻凸显了两个问题:承包协议必须是私密的吗?如果不是,你应当为你在社区中造成的不安而感到担忧吗?你为某些开发者提供了承包合同,为什么不是其他人呢?

如果可以,最好将合同公开。否则,承包者的行为与社区中的其他人相比会看起来有些奇怪—或许他突然对一些过去从未表现出兴趣的特性展示出了不可理解的高优先级。当人们询问其原因时,他怎样才能避免说出他是根据合同编写代码,同时回答的让人信服。

与此同时,你和承包者都不应该表现的仿佛其他人应当把你的安排看得过重。我见过一些承包者招摇着进入开发列表,自认为他们的留言应该被更加郑重的对待,仅仅因为他们是支付薪水的。那种态度也是对于项目其他人的一种信号,承包者看重合同这件事—而不是合同导致的代码—本应当是重要的事情。但是从其他开发者的视角,只有代码有意义。在任何时候,注意力应该保持在技术问题上,而不是谁给谁付薪水的细节。例如,Subversion社区的一个开发者用一种优雅的方式处理承包。当在IRC讨论他的代码变更时,他会在旁白(通常是在私有备注,一种IRC privmsg,发送给其他提交者)中提及他是被支付薪水完成特定bug或特性。但是他也一直表现出无论如何他都会作出那些变更的印象,并很高兴金钱可以让他完成那些工作。他可以表露客户的身份,也可以不表露,但是无论怎样,他没有详述合同。他关于此事的备注只是一个对于如何完成工作的另类技术讨论的修饰。

那个例子也展示了开放承包合同带来益处的另一个原因。会有多个组织为开源项目资助承包,如果他们都知道其他人的目标,他们可以更好的调配资源。在上面的例子中,项目最大的创建者(CollabNet)没有以任何方式参与这种计件承包,但是当知道有人为某些bug修正提供资助时,CollabNet便将其资源转向到了其他bug上,从整体上大大提高了项目的效率。

其他开发者会憎恨这些因为薪水而为项目工作的人吗?通常情况下不会,这些得到支付的人都是社区值的尊敬的成员。没有人会期待承包工作会公平的分发给所有的提交者。人们理解长期关系的重要性:从事承包的不确定性会导致一旦你发现某人值的信赖,你就不太会只是因为公平性而找其他人。可以这样想一下:你第一次雇佣时,不会有抱怨,因为你必须选出某人—不能雇佣所有人不是你的错。此后,当你第二次雇佣此人时,那只是常识:你已经了解了他,上一次是成功的,为什么要承担不必要的风险?因此,只雇佣一个或两个人,而不是将工作分散开,这是非常自然的。

评审和接受变更

社区对于承包工作的成功也非常重要。他们为较大变更所投入的设计和评审过程不能只是事后处理。不应该把它当作工作的一个部分,并且完全交给承包者。不要把社区的仔细审查当作需要克服的障碍—而应该把它当作一个免费的设计委员会和QA部门。可以从攻击性的追逐中获益,而不仅仅是忍受。

案例研究:CVS密码认证协议

1995年,作为合伙人中的一个,我为CVS(并行版本系统,见http://www.cvshome.org/)提供支持和改进。我的搭档Jim和我,当时在非正式的维护着CVS。但是我们没有仔细考虑如何与已有的,主要是志愿者的CVS开发社区处理关系。我们只是假定他们会发送补丁,我们会应用补丁,那样就会一切正常。

那时,网络化的CVS还只能通过如rsh的远程登录程序完成。在CVS访问时使用与登录相同的密码显然存在安全风险,许多组织因此而放弃。一个主要的投资银行雇佣我们来添加一个认证机制,这样他们就可以使用网络CVS安全的连接远程办公室。

Jim和我得到这个契约并坐下来设计新的认证系统。我们面临的问题非常简单(当时美国对于加密算法代码有出口控制,所以客户知道我们无法实现较强的加密),但是因为我们没有设计这种协议的经验,我们还是作出了许多对于专家来说非常明显的错误。如果我们能够花时间写下提议并交给其他开发者评审,这些错误可以很容易的被发现。但是我们没有这样做,因为我们当时没有把开发列表当作可以利用的资源。我们认为人们将会接受所有我们提交的东西,而且—因为我们不知道我们所不知道的—我们不愿意在众目睽睽之下工作,例如频繁发布补丁,在一个特殊的分支作出较小、简单和易消化的提交等等。最后的认证协议并不是很好,当然,一旦建立起来,就很难在改进了,因为兼容性的考虑。

问题的根源是缺乏经验,我们可以轻易的认识到我们需要的知识。问题是我们对志愿者开发社区的态度。我们将对变更的接受当成了跨越障碍,而不是变更可以被改进的一个过程。因为我们很自信我们所做的任何事情都几乎会被接受(事实也是如此),所以放弃了让其他人参与的努力。

很明显,当你选了一个承包者,你一定希望他拥有此工作的正确技术技能和经验。但是,同样重要的是要选择一个拥有与社区其他开发者有建设性交流历史的人。你得到的不仅仅是一个人,也是一个代理人,他将会构建一套专业技能网络以确保他是以健壮和可维护的方式完成的工作。

资助非编程活动

编程只是开源项目的所有工作的一部分。从项目志愿者的视角,这是最明显和迷人的部分。很不幸,这意味着其他活动,例如文档、正式测试等等,是可以忽略的,至少与私有软件相比,投入了更少的精力。公司组织有时可以弥补这件事,通过投入一些他们内部软件开发时的基础架构到开源项目。

在公司内部过程和公共开发社区之间的转换是成功的关键。不过这种转换也不是轻而易举的:通常二者并不是一场接近的比赛,这种区别只能通过人为干预连接起来。例如,公司会使用与公共项目不同的bug跟踪系统。即使使用相同的跟踪软件,其中存放的数据也会大不相同,因为一个公司需要的bug跟踪与自由软件社区完全不同。位于某一跟踪系统的信息在映射到另一个系统时,必然要删除机密部分,从另一个方向来说,则是要添加。

本小节余下部分关于如何构建和维护这种联系。最后的结果必定是开源软件运行的更加平滑,社区会认可公司对于资源的投资,也不会感到公司掌控事情往自己的目标发展有什么不适合。

质量保证(也成为专业测试)

在私有软件开发中,一般都有一组人专注于质量保证:寻找bug、性能和扩展性测试、接口和文档检查等等。作为一般的原则,此类活动一般不会被自由软件项目的志愿者社区积极的追求。部分原因是很难为测试之类的不起眼工作找到志愿者,也因为人们总是假定他们有一个大的用户社区,可以给项目好的测试覆盖,以及性能和扩展性测试,也因为志愿者经常无法使用必要的硬件资源。

有很多用户等价于有许多测试者的假设并不成立。诚然,有时候分配测试者在普通环境中进行基本功能测试有一点用处:bug会在用户的日常操作中迅速被发现。但是因为用户只是期望把事情完成,他们不会有意识的开始探索程序未知的最新功能。此外,当他们在一个简单的场景发现了一个bug,他们经常悄悄的实现这个场景,而不会去报告这个bug。大多数没有意识到,你的客户(驱使进行软件开发的人)对于软件的使用模式会与普通用户的使用模式在统计学上有显著的不同。

专业的测试团队可以迅速发现此类bug,和他们在私有软件时一样容易。真正的挑战是将测试团队的结果以有用的形式反馈给公众。在内部测试部门中,通常有自己报告测试结果的方法,也需要使用公司特定的术语,或与特定客户和他们数据集相关的专业知识。这种报告对于公共bug跟踪并不适合,一方面是因为其格式,另一方面是因为机密性。即使你公司的内部bug跟踪软件与公共项目相同,仍然需要对此问题发生的公司特定的评论和元数据变更进行管理(例如,提升某个问题的内部等级,或者设定其为特定客户进行解决)。通常情况下,这些注释是机密的—有时候他们甚至不会展示给客户。但是即使没有机密,他们对于公共项目也没有意义,因此公众不想因此分散注意力。

核心bug报告本身对于公众非常重要。实际上,来自测试团队的bug报告会比普通用户的报告更有价值,因为测试团队是在为发现问题进行探测,而普通用户不是。因为你不太可能从任何其他来源获取这样的bug报告,你一定希望将其保留并发布给公众。

为此,如果他们愿意,或者可以将内部测试报告的问题转化到公共跟踪系统中,QA部门可以在公共问题跟踪系统中归档问题。转化仅仅意味着使用不涉及用户特定信息(重现的处方会使用用户数据,当然要假定用户对此认可)的方式描述bug。

推荐让QA部门在公共跟踪系统直接填写问题。这样会让公众对你公司的投入更加感激:有用的bug报告和技术贡献一样会增加你的组织的信誉。这样也给了开发者一个与测试团队直接交流的渠道。例如,如果内部QA团队监控着公共问题跟踪系统,一个开发者可以为一个可量测bug(开发者没有资源自己测试)提交修正,并为该问题提交一个说明询问QA团队查看该修正是否起到了预期的效果。也许会遇到一些开发者的抵制;最好情况下,程序员会把QA当作必要的魔鬼。通过发现显著的bug,填写复杂的报告,QA团队可以轻易的达到这个目标;另一方面,如果他们的报告甚至没有来自普通用户社区的报告质量高,那么让他们与开发团队直接交流也没有什么意义。

无论哪一种方法,一旦公共问题已经存在,原来的内部问题就应当在技术内容中引用公共问题。管理层和有薪开发者根据需要,或许可以继续关注包含公司特定注释的内部问题,但是使用公共问题可以让所有人看到对应的信息。

你应当会预期有额外的成本。维护一个bug的两个问题,将会比一个时耗费更多的工作。好处是,将有更多的程序员将会看到这个报告,并且能为这个解决方案作出贡献。

法律建议和保护

公司,无论是盈利或非赢利,恐怕是唯一在自由软件中将精力投入到法律问题上的实体。单个开发者通常理解多种开源许可证的微妙,但他们没有时间和资源去对版权、商标和版权法进行详细研究。如果你的公司拥有法律部门,可以通过否决代码的版权状态来帮助项目,并可以帮助开发者理解可能的版权和商标问题。如何帮助的具体形式将会在Chapter 9, 许可证,版权和专利讨论。主要是确保法律部门和开发社区的交流,如果发生这种交流,主要是因为完全不同的双方都有相互的渴望。在偶然情况下,这两组人会互相讨论,每一方会假定拥有另一方没有的领域特定知识。一个好的策略是在中间设定一个联络,在任何需要的时候进行转化。

文档和可用性

文档和可用性都是开源项目著名的软肋,尽管我认为,在文档方面,自由和私有软件的差距被夸大了。然而根据经验,大多数开源软件缺乏一流的文档和可用性研究。

如果你的组织希望为一个项目弥补这个差距,最好雇佣一些不属于项目常规开发者,但可以与开发者进行有效率交流的人。不雇佣开发者有两个原因:首先,你不会从项目带走开发时间;其次,距离项目过近的人通常不是编写文档或研究可用性的最佳人选,他们很难从外部视角观察软件。

然而,从事该工作的人还是有必要与开发者进行交流。找到的人需要拥有与编码团队交流的技能,但不必对软件过于专业而无法移情于普通用户。

一个中等用户很可能是编写好文档的合适人选。实际上,本书发行第一版后,我收到开源开发者Dirk Reiners的一封电子邮件:

关于金钱::文档和可用性的一些意见:当我们要花一些钱
并决定我们最需要的是编写初学者教程时,我们雇佣了一
个中级用户。他刚刚经历了系统的入门,所以能够记住问题
,但是因为已经通过问题,所以他知道如何描述问题。这样
他就可以编写一些只需由核心开发者进行少量修正的内容,
同时还是会覆盖开发组会认为‘非常明显的’而遗漏的内容。
他的案例甚至更好,随着他的工作,引入了许多用户(学
生)进入系统,所以他组合了许多人的经验,有时候某些事
看起来只是好运当头,恐怕不是在任何情况下都有效。

提供主机/带宽

对于不使用包装主机的站点(见Chapter 3, 技术基础设施the section called “包装主机”),提供服务器和网络连接—以及更重要的系统管理帮助—会是重要的辅助。即使这是你的组织为项目所做的唯一工作,也是一种获取公共关系回报的适度有效的方法,尽管,它不会带来任何对于项目方向的影响。

你可能会在项目主页发现一个广告条或致谢,用以感谢提供主机的公司。如果你通过设置主机,让项目网址位于公司域名之下,那么单纯通过URL你就获得了额外的联系。这会导致大多数用户认为软件与你的公司有关,即使没有在开发中作出任何贡献。问题是,开发者也会意识到这种关联的趋势,会对项目位于你的领域感到不适,除非你能贡献出除带宽以外的更多资源。毕竟,现在有很多存放主机的地方。社区会最终感觉到这种隐含信用分化与主机带来的便利并不相配,并将项目带到别的地方。所以,如果你希望提供主机,要这样做—不但要计划投入更多,更要细心的考虑声明投入多少。

市场营销

虽然大多数开源开发者不愿意承认,但市场推广确实有用。好的营销活动可以为开源产品创造良好的氛围,即使此时顽固的编码者因为一些无法说明的原因,对于软件还没有清晰肯定的思路。这里我不会讨论一般意义的市场营销的军备竞赛动力学。所有参与到自由软件的公司最终都会发现自己需要考虑如何营销自己、软件或他们与软件的关系。下面是在进行这种努力时如何避免落入陷阱的建议;请看Chapter 6, 交流the section called “公开性”

记住你正在被注视着

为了让志愿开发者社区一直站在你一边,非常重要的一点是不要说任何不能确定正确的事情。作出任何声明前要仔细审核,并要为公众提供独立检查该声明的方法。独立事实检查是开源项目的主要组成部分,它不仅仅适用于代码。

很自然,没有人会建议公司作出未验证的声明。但是在开源活动中,通常会有不可思议的大量拥有专业技能的人去验证声明—这些人也都有高速的宽带接入和足够的社会联系,可以用一种危险方法发布他们的发现,他们一定会这么干。当Global Megacorp化工的工厂污染了河流,只有经过训练的科学家可以验证,他们也会受到Global Megacorp科学家的反驳,让公众抓耳挠腮而不知如何考虑。而另一方面,你在开源世界中的行为不仅是可见的和可记录的;也很容易被许多人独立的检查,得出他们自己的结论,并口头传播这些结论。这种交流网络一直都在;那是开源操作的本质,他们可以用来传播任何信息。如果不是不可能,反驳通常很困难,特别是当某人所说的是正确的。

例如,如果你们确实这么做了,可以称你的组织“资助了项目X”。但是,如果大多数代码是外人写的,不要称自己为“X的制造者”。相反地,如果任何人都可以看到版本库只有少量代码变更来自于组织之外,不要声明已经有了一个深入参与的开发者社区。

不久之前,我看到一个知名计算机公司的一次声明,说明他们以开源许可证发布了一个重要的软件包。当最初的声明发出之后,我看了一下他们的公共版本控制版本库,发现其中只有三次修订。换句话说,他们只是做了一次代码的初始化导入,之后没做什么事情。此事本身没有什么好担心的—毕竟,他们只是做了声明。没有理由期待会立刻发生大量开发活动。

不久之后,他们作出另一次声明。下面是将名称和数字替换后声明:

我们很高兴的宣布经过Singer社区严格的测试,Linux和Windows版本的Singer 5已经做好生产使用的准备。

很想知道是什么社区进行的“严格测试”,我回到版本库去看最近的变更历史。项目还在修订3,很明显,他们没有发现任何一个值得在发布前修订的bug。考虑到社区测试一定是记录到了其他地方,接着我检查了bug跟踪系统。发现刚好有6个开放的问题,其中四个已经打开了几个月。

当然,这是乞丐的信仰(不可信)。当测试者在一个大型和复杂的软件上认真推敲一段时间,他们一定会发现bug。即使bug的修正不会进入即将到来的版本,人们还是希望有一些版本控制活动会作为测试过程的结果出现,或至少是一些新的问题。很显然,在开源许可证声明和第一次开源发布声明之间没有发生任何事情。

重点不是说这个公司在社区测试问题上说了谎。我不知道他们到底做了没有。但是他们很明显是在欺骗。因为,无论是版本控制版本库还是问题跟踪系统,都没有任何迹象来说明所谓的严格测试曾经发生过,这个公司要么不要过早的声明,要么提供一些测试结果的明确链接(“我们发现了278个bug;点击此处看详细内容”)。后一种方法可以让任何人迅速掌握社区活动的级别。就像前面说的,我只有了几分钟就确定了这个社区测试的真相,它没有在任何常见的地方留下痕迹。那样不会花费太多力气,我确信我不是唯一保持疑惑的人。

当然,透明性和可验证性也是准确信用的重要部分。关于这些内容可以看Chapter 8, 管理志愿者the section called “荣誉”

不要痛击竞争开源产品

要忍住不要发表关于竞争开源软件的负面意见。可以做的是提供负面的事实—也就是通常在一些好的比较图表上可以轻易确定的断言。但是最好避免不太严格的本性的负面特征,有两个原因。首先,这样会点燃论战而脱离有建设意义的讨论。其次,更重要的,在你的项目的一些志愿开发者会转向为竞争项目工作。开始并不是很明显:项目都在同一个领域(这也是为什么他们会竞争),拥有专业技能的开发者会在任何可以发挥专业才能的地方作出贡献。即使没有直接的开发者重叠,也很可能你的项目的开发者会与关联项目的开发者相识。他们维护建设性的个人关系的能力会被负面营销信息所束缚。

在开源世界中,痛殴闭源产品中的竞争者是可以广泛接受的,特别是如果这些产品是微软制造。个人来讲,我为这种趋势感到悲哀(虽然如此,这种直接基于事实的比较没有任何错误),不仅仅是因为这样很粗鲁,也因为这样很危险,让一个项目开始相信它自己的夸夸其谈,并忽视竞争者实际上可能更加优越的方式。通常情况下,可以仔细观察市场声明的效果,因为这也会发生在你自己的开发社区。人们可能因为市场美元的支持而丧失客观性,无法看清自己软件的真正力量和弱点。一个很可能出现的情形,某个公司的开发者会公开展示自己对于某个市场声明的无辜,甚至是直接在公共论坛。很明显,他们不应当直接跳出来否决市场营销信息(除非它事实上是错误的,尽管人们希望此类事情能够尽早被捕获)。但是他们可能会一次次的取笑这种行为,这也是将开发社区的其余部分带回地球的一个方法。

Chapter 6. 交流

将代码写清楚的能力或许是开源环境中最重要的一项技巧。从长期来看,这不仅仅取决于编程天赋。即使是优秀的程序员,如果没有好的沟通技巧,在同一时间也只能完成一件事,即使如此也很难让其他人注意。但一个糟糕的程序员如果善于交流,则可以协调并说服许多人做很多事情,对于项目的方向和动力起着重要的作用。

无论从哪个方向看,编写好代码的能力和与其他人交流的能力看起来毫不相关。编码能力和描述技术问题的能力则有一些关系,但是描述技术问题只是项目交流中很小的一部分。更重要的是移情到其读者的能力,可以像其他人那样去看待自己的文章和回复,可以让他人以同样的客观性看待自己的文章。同样重要的是发现某种媒介或交流方法不再有效,这或许是因为它并没有随用户数量的增多而扩展,然后花时间去解决它。

在理论上很明显—但因为开源软件开发环境的受众和交流机制引起的混乱,在实践中的非常困难。一个给定的想法必须在邮件列表中作为bug跟踪系统的注释或代码的说明发布出来?当在一个公共论坛回答一个问题时,应该如何假定读者的知识水平,只是为咨询问题的“读者”解答,而是为所有会看到回复的读者?如何让开发者与其他用户保持建设性的联系,而避免陷入特性请求、虚假的bug报告和一般的聊天。如何知道一个媒介达到了容量的限度,你该如何做呢?

针对这些问题的解决方案都只能是部分的,因为任何特定方案都会随项目结构的成长或变化而废弃。他们也经常是专门的方案,因为他们需要随机应变。所有的参与者需要意识到交流在何时,如何陷入困境,并立刻参与到解决方案中去。帮助人们完成这件事是管理开源项目的重要任务。本小节后面的部分会讨论如何引导你自己的交流,以及如何在项目中为所有人维护交流机制的优先级。[22]

人如其文

考虑如下情况:因特网上别人对你的了解都来自你所写的东西。你或许是一个富有才华、敏锐和领袖气质的人—但是如果的你的邮件散漫且没有组织,人们会以为你也是这样。或者也许你是一个散漫和无组织的人,但没人会知道这一点,只要你的文字能够清晰且言之有物。

在写作上的投入回报巨大。长期自由软件黑客Jim Blandy说过这样一个故事:

回到1993,我为自由软件基金会工作,正在为GNU Emacs的19版本进行beta测试。我们每周都会发布一个这样的beta版本,人们会进行测试并回馈我们bug报告。有一个我们都不认识的人,但是完成的工作很好:他的报告总是十分清晰,并能让我们直接找到问题,而且当他自己提供修正时,也几乎都是正确的。他是顶尖人物。

现在,在FSF可以使用其他人编写的代码之前,我们会让他们准备一些文书工作,将该代码的版权利润赋予给FSF。完全获得陌生人的代码是处理法律灾难的好办法。

所以我给这个家伙发了一份表单,说,“这里是我们需要的一些文书工作,你签署这一份,让你的雇主签另一份,然后我们就可以开始提交你的修正。非常感谢。”

他回复了一封信息说,“我没有雇主。”

所以我说,“很好,那就让你的大学签署它并发回来。”

不久,他又回复了,并说,“很好,实际上,我已经30岁了,与父母一起住。”

因为那个小孩并没有像30岁的人那样写东西,所以没有人知道他的情况。下面也是让你的写作能够带来良好印象的一些方法。

结构和格式

不要像编写手机短信那样编写所有的东西。要使用完整的句子,每个句子首字母要大写,也要根据需要分段。在编写电子邮件和其他内容时这一点最重要。在IRC或类似的短命论坛上,忽略大小写或压缩形式的常见短语也无所谓。只是不要把这个习惯带到更正式,会持久化保存的论坛中。邮件、文档、bug报告和其他会永久保存的东西,必须使用标准语法和拼写,并有一致的叙事结构。并不是因为任何事情都有遵循任意规则的内在特性,而是因为规则并不是任意的:他们演化成现在的形式是因为可以让文本更可读,因此你应该遵循这些规则。可读性是令人向往的,并不是因为这样人们就能够理解你所写的,而且是因为这样可以让你看起来像是人们可以花时间进行清晰交流的人:也就是值得人们关注的人。

对于个别的电子邮件,有经验的开源开发者会使用特定的约定:

只发送文本邮件,而不应该是HTML、富文本或其他格式,因为有许多只支持文本的邮件阅读器。将每行列长格式化为72。列长不要超过80,80已经成为事实上的标准终端宽度(也就是会有人使用更宽的终端,但没有更窄的)。通过将列数设置为小于80,可以为其他人回复中的引用字符留出空间,从而不必让文本强制换行。

使用真正的换行。一些邮件程序可以使用一种假的换行,可以让你编写的邮件在没有实际换行时显示出来有换行。当邮件发送以后,邮件不会有你所以为的换行,他们会非常难看的出现在某些人的屏幕上。如果你的邮件程序使用假换行,应该找一个恰当的设置,可以在编写邮件时显示真换行。

当包含屏幕输出,代码片段或其他格式化文本时,需要清晰的处理缩进,这样可以轻易的区分你的叙述和引用的内容。 (当我开始撰写此书时,我没有想过编写这些建议,但是当在许多开源邮件列表中看到了很多人混合文本和其他资源,以至于无法区分开时,我改变了注意。这样的效果很让人灰心。这让他们的文章很难被理解,很明显也让这些人看起来有点混乱。)

当引用其他人的邮件时,可以直接在合适的位置插入你的回应,如果需要可以在不同的位置,然后删节那些在你的邮件不使用的部分。如果你需要为全文进行评述,可以写在顶部(将你的回应置于引用的邮件文本之前);否则,请首先引述原邮件的相关文本,然后紧跟你的回应。

小心构建新邮件的主题行。这是邮件中最重要的一行,因为它可以让项目中的其他人决定是否进一步阅读。现代邮件阅读软件可以将相关信息组织成一组线索,并不仅仅是根据共同的主题,而且可以根据其他头(有时并不显示)。它遵循了如下原则,如果线索转移到另一个主题,你可以—也必须—根据回复修改主题行。由于其他邮件头,线索的完整性得以保全,但是新的主题可以帮助人们获知主题已经转移。同样的,如果你确实希望开始一个新的主题,那么可以发布一个新的邮件,而不是对现有邮件修改主题并回复。否则,你的邮件会仍然分组到你所回复的线程中,因此会让人们不知道讨论的内容已经改变。再次,惩罚不仅仅是所浪费的时间,也会使你使用交流工具的信用受损。

内容

组织良好的邮件会吸引读者,但是内容可以留住他们。当然,没有可以确保好内容的固定规则,但是有一些可以让其更像的原理。

让事情对你的读者更简单。任何一个开源项目都有大量的信息,不能期望读者熟悉所有的东西—事实上,不可能期望他们知道如何熟悉。所以要尽可能让你的文章以尽量便利的形式提供给读者。如果你能够额外花费几分钟在邮件列表归档中找出特定线索的URL时,从而减少读者寻找的麻烦,这样做非常值得。如果你可以花费5到10分钟为复杂的线索总结一个结论,从而为人们理解你的文章提供一个上下文环境,那么一定要去做。可以这样考虑这件事,项目越成功,在任何论坛中的读者-作者比率越高。如果你的文章被n个用户看到,那么随着n的增大,扩展额外的努力节约其他人的时间就越值得。随着人们看到你将自己置于这个标准之下,他们也会在自己的交流中与此匹配。理想情况下,会带来项目整体效率的提升:当人们在n个人和一个人这样努力做出选择时,大家会选择前者。

不要使用夸张法。在线发布中的夸大是经典的军备竞赛。例如,一些报告bug的人会担心开发者不会投入足够的注意力,所以他们将其描述为严重的、会中断他(以及他的所有朋友/同事/亲戚)使用该软件的问题,而实际上只是一般的不适。但是夸大并不限于用户—程序员也会在技术讨论时也这样做,特别是当问题是关于他们不认可的某种口味而不是正确性时。

“这样做事会让代码完全不可读。 与J. Random的建议相比,这是维护的梦魇。”

当措辞不是如此尖锐,同样的感情也会变得更强

“这样也可以工作,但是出于可读性和可维护性的考虑,并不是理想的方式,我认为。J. Random's的建议避免了这类问题,因为它...”

你不可能完全消灭夸大,一般来说也没有必要。与其他形式的交流问题相比,夸大并不是对所有人都有害—他只会伤害夸大者。接收者也会做出相应的抵消,每次都会让发送者损失自己的信用。因此,为了你自己在项目的影响力,请使用温和的方式。只有这样,人们在会在你真的需要表达强烈观点时重视你。

编辑两次。对于任何超过中等长度段落的信息,请在你第一次认为完成之后再从头到尾检查一遍。这是所有参加过写作课程的人会得到的忠告,但是在在线讨论中格外重要。因为在线写作的过程很容易变得非常不连贯(在编写信息的过程中,你需要回头检查其他邮件,访问特定的网页,或者运行某个命令捕获调试信息等),这样很容易让你失去叙事的感觉。不连贯编写的信息,而且在发送以前也不检查通常会被认为会让他们的作者懊恼(或者这样某人会希望)。花时间检查你发送的内容。你的内容组织的越好,就会有越多的人去阅读。

基调

在写过几千条信息后,你一定会发现自己会趋向于简洁。这看起来是大多数技术论坛的标准,在本质上没有任何错误。在社会交流中不可接受的简洁程度则是自由软件黑客的默认程度。下面是我在一个邮件列表中发表的关于自由内容管理软件的文章,完全引用:

您能更详细的说一下所遇到的问题吗?
可能是:

您使用什么版本的Slash?你能说出原始信息吗。
你是如何编译的apache/mod_perl源?

你尝试过发布在slashcode.com的Apache 2.0补丁吗?

  Shane

就是简洁!没有问候,没有他的名字以外的签名,整个信息本身只有一系列尽可能紧凑的疑问句。其中的一个祈使语句是隐含的对原始信息的批评。虽然如此,我还是很高兴看到Shane的邮件,并没有因为其简洁而把他当作一个大忙人。事实仅仅是他们在询问问题,而不是忽略我的问题,意味着他愿意在这个问题上花更多的时间。

读者能够对这种方式作出正面的反应吗?这不是必须的;这取决于人和上下文。例如,如果某人刚刚承认她犯了一个错误(例如写了一个bug),而你根据以前的经验知道这个人容易不安全,那么你仍会编写一个紧凑的回复,你应当确信其中包含一些考虑其感受的内容。你的回复可能很简短,只有工程师对于形式的分析,和你想的一样简洁。但是在最后,应该指明你的简洁不应该理解为冷漠。例如,如果你要建议如何正确的修正某个bug,应该签署“好运,<这里是你的名字>”指明你希望他们做好工作而不会发疯。一个笑脸或其他符号表情通常也足够安抚你的对话者。

也许像关心参与者所说事情的表面一样关心其情绪有一些古怪,但是认真的说,情绪影响生产力。由于其他原因情绪也非常重要,但如果仅出于功利原因,我们也能发现不快乐的人会写出糟糕的软件。因为大多数电子媒介的本性所限,通常没有关于人们情绪的明显线索。你应该根据这些猜测:a)大多数人在那种形势下的感觉,b)你在以前的交流中对参与者的了解。一些人采用更简单的态度,仅根据表面处理事情,如果没有参与者直接说出自己的感受,则别人没有义务像他已经说出那样去对待她。我不会选用这个方法,有如下一些原因。首先,人们在真实生活中并不是这样处事的,为什么要在线上这样?其次,因为所有的互动发生在公共论坛,人们会比私密情况下更加控制自己的感情表达。更精确的说,他们通常希望对某人直接表达感情,例如感激和愤怒,而不是直接的内部情绪,例如不安和骄傲。当知道其他人会关注到他的心理状态时,大多数人会工作的更好。通过在细微线索上投入注意力,你可以在大多数时候猜到问题,并且能够鼓舞人们比原来更深入地参与。

我不是说,你的角色是团队治疗师,一直通过触及别人的情绪来帮助每个人。但是通过对于个人行为长期模式的观察,即使你们从来也没有面对面,也会获得像单个人之间的感受。而且通过对于自己文章基调的敏感性,你会为自己对于其他人情绪的影响力感到吃惊,最终会使项目受益。

识别无礼

开源文化的一个定性特征是对于何为无礼的特色定义。下面叙述的习惯不只是出现在开源软件开发,也不只是在一般软件—在数学、严密科学或工程纪律中也并不陌生—自由软件,由于其跨领域性,并有不断涌入的新来者,许多不熟悉这种环境的人将要面对这些习惯。

我们先从无礼开始。

技术批评,即使很直接且没有铺垫,也不是无礼的。实际上,这可以看作是一种谄媚:批评者在说话,说明目标值得重视,值得花时间研究。可以说,平静只是简单的忽视某人的文章,花费更多时间批评它则是更多的赞美(当然,除非批评升级到了非理性的攻击或其他形式的明显无礼)。

迟钝、朴实的问题,例如前面Shane的对我的邮件,也不是无礼。在其他环境下这种提问会看起来有些冷酷,玩弄文字或甚至是嘲弄,通常是有意的严重行为,而且除了尽快释放出信息,没有隐藏的日程表。著名的技术支持问题“你的电脑插电了吗?”是经典的案例。支持者确实需要知道你的电脑是否插电,经过一段时间的这类工作,他已经厌倦了在问题前点缀一些有礼貌的奉承(“请原谅,我只是要问一些问题以排除一些可能性。有一些可能很基础,请暂时忍受一下我...”)。 此刻,他没有再做任何铺垫,只是直接问:到底插电了没有?类似的问题会一直在自由软件邮件列表中被问起。目的不是冒犯接收者,而是快速排除大多数明显的(或许也是最常见的)解释。理解这种行为并作出响应的接收者会因为大度的态度获得成功。不能正确反应的接收者也不会受到谴责。这只是文化的冲突,不是某人的过错。要和蔼的解释你的问题(或批评)没有隐藏的含义;只是希望让(或传递)信息尽可能有效率,无他。

那么怎样是无礼?

详细的技术评论一种形式的谄媚,同理,如果不能提供高质量批评也可以看作是一种冒犯。我不是说仅仅忽略某人的工作,是提议、代码变更、新问题添加或任何事。除非您之前明确的承诺会有详细的反应,不做任何反应也没有错。人们只会假设你没有时间回答。但是如果你反应,就要用心:花时间真的去分析,提供合适的实在例子,在以前的归档中发掘相关的文章等等。或者如果你没有时间花费这种精力,但仍需要写一些简短的回应,然后在信息中公开说明缺陷(“我知道有一个对应的问题,不过我没时间去搜索,对不起”)。主要是认识到文化标准的存在,通过履行承诺或公开的告知缺乏时间实现。无论何种方式,标准都会被加强。即使不能达到标准,不要在同一时间解释为什么你没有达到,这样做好像是说这个主题(以及那些参与者)不值得你花费时间。更好地是通过简洁而不是懒惰展示你的时间的价值。

也有一些其他形式的无礼,当然,但是大多数并不只存在于自由软件开发,而且常识足够引导你避免他们。如果你还没有看,可以看Chapter 2, 起步the section called “防无礼于未然”

面容

人脑中有一块专门负责识别面容的区域。它被非正式的称为“梭型面容区域”,其能力大多来自天生,而不是学习得到。因为识别单个人是至关重要的生存技巧,所以我们演化出了专门的硬件负责这个工作。

互联网基于的交流从心理上说有些古怪,因为需要许多无法用自然,原始的方法识别对方的人,进行紧密的合作:首先是面部识别,也有声音和姿势等。为了弥补这种不足,可以在所有地方使用一致的屏幕名称。他应该是你邮件地址的一部分(@之前的部分),你的IRC用户名,你的版本库提交名,你的问题跟踪用户名等等。这个名字就是你的在线“面容”:一段可以同你的真实面容起到同样效果的标识字符串,尽管他不是,但至少模拟了内置在电脑的硬件。。

屏幕名称应该是你真实姓名的直觉(例如我的是“kfogel”)展示。在一些情况中,会伴随你的完整名,例如在邮件头中:

From: "Karl Fogel" <kfogel@whateverdomain.com>

实际上,这个例子有两件事。就像前面提到的,屏幕名称用直觉方式匹配真实姓名。但是,真实姓名是真实的。而不是某种修饰的名称:

From: "Wonder Hacker" <wonderhacker@whateverdomain.com>

Paul Steiner有一副著名的卡通,刊登在1993年6月5日的纽约客,里面是一条狗登录到了电脑终端并阴险的与另一个人交谈:“在因特网上,没人知道你是一条狗。”这类思想的背后是自我夸大,这些有些俏皮的在线标识的人给了他们自己—好像被叫做“Wonder Hacker”真的是神奇黑客了。但是事实没有改变:即使没人知道你是条狗,你还是条狗。一个幻想的在线标识不会打动读者。相反,他们会认为你只是形象而没有本体,或者仅仅是你是不安全的。在所有的交流中使用真实姓名,或者因为某些原因需要匿名,那么就请起一个完全像真名的名称,并一直用下去。

为了保持你的在线面容的一致,有一些方法可以让他更吸引人。如果你有正式的头衔(例如”博士“、”教授“和”导师“),不要炫耀,除非与对话内容相关,最好不要提及。作为一般的黑客之道,特别是自由软件文化,认为这些头衔是多余和不安全的标志(例如叫兽和砖家)。当然,如果这些头衔是作为标准的签名出现在每封邮件,不要把这个当作支持你在讨论中位置的工具—这种尝试必定事与愿违。你需要尊敬人的家伙,而不是尊敬这些头衔。

说到签名区:要保证短小有意义,或者更好的情况是没有签名区。避免大段的法律免责声明出现在每个邮件的结尾,特别是当他们表达的感情与自由软件项目的参与精神不匹配时。例如,如下是我参与的一个公开邮件列表中的某个用户每个文章都会出现的的经典流派:

IMPORTANT NOTICE

If you have received this e-mail in error or wish to read our e-mail
disclaimer statement and monitoring policy, please refer to the
statement below or contact the sender.

This communication is from Deloitte & Touche LLP.  Deloitte &
Touche LLP is a limited liability partnership registered in England
and Wales with registered number OC303675.  A list of members' names
is available for inspection at Stonecutter Court, 1 Stonecutter
Street, London EC4A 4TR, United Kingdom, the firm's principal place of
business and registered office.  Deloitte & Touche LLP is
authorised and regulated by the Financial Services Authority.

This communication and any attachments contain information which is
confidential and may also be privileged.  It is for the exclusive use
of the intended recipient(s).  If you are not the intended
recipient(s) please note that any form of disclosure, distribution,
copying or use of this communication or the information in it or in
any attachments is strictly prohibited and may be unlawful.  If you
have received this communication in error, please return it with the
title "received in error" to IT.SECURITY.UK@deloitte.co.uk then delete
the email and destroy any copies of it.

E-mail communications cannot be guaranteed to be secure or error free,
as information could be intercepted, corrupted, amended, lost,
destroyed, arrive late or incomplete, or contain viruses.  We do not
accept liability for any such matters or their consequences.  Anyone
who communicates with us by e-mail is taken to accept the risks in
doing so.

When addressed to our clients, any opinions or advice contained in
this e-mail and any attachments are subject to the terms and
conditions expressed in the governing Deloitte & Touche LLP client
engagement letter.

Opinions, conclusions and other information in this e-mail and any
attachments which do not relate to the official business of the firm
are neither given nor endorsed by it.

对于只想偶尔询问一个问题的人,如此巨大的免责声明虽然有点傻,但是没有任何永久的伤害。但是,如果某人希望活跃的参与到项目中,这个法律的陈词滥调会开始一个更潜在的影响。它会释放出两个潜在的破坏性的信号,这个人对于自己的工具没有完全的控制权力—他陷入了某个公司的邮件系统,这个系统会在每个邮件结尾添加讨厌的信息,而他无法绕过—其次,他对自己参与的自由软件活动只有有限或没有任何组织支持。诚然,组织明显没有禁止他在公共列表发表文章,但可以让他的文章看起来明显的不受欢迎,仿佛泄漏机密信息的风险必须排在第一位。

如果你所在的组织坚持对所有外发邮件添加这种签名区,应该考虑申请一个免费邮件帐号,例如,gmail.google.comwww.hotmail.comwww.yahoo.com,然后作为你在项目中的地址。

避免常见的陷阱

不要发表无目的的文章

在线项目中一个常见的陷阱是认为你需要回复所有的东西。你不必如此。首先,一般会有太多你无法同时跟踪的线索,至少是经过它开始的几个月后。其次,即使你已经决定参与,人们说的大多数话都无需回应。开发论坛都会不同程度的由下列三类信息占据:

  1. 提出重要事物的信息

  2. 提出对他人曾经说过的话表示支持或反对的信息

  3. 总结信息

上述信息并不是必定需要一个回应,特别是当你根据到目前为止的线索,很确定其他人会说出以前你说过的话时。 (如果你担心别人也使用这个策略,而落入等待-等待的循环,不必如此;几乎总会有某人愿意跳出来解决问题。) 回复应该由明确的目的激发。首先要问自己,是否知道所期望的完成的任务?其次,是否如果没有你的话,这个事情就无法完成。

在线索中发出你的声音的有两个理由,包括a) 当你在提议中发现了一个瑕疵,你怀疑你是唯一看到它的人,另外b) 你发现他人之间错误交流,并且知道你可以通过澄清文章修正它。通常在邮件中仅仅表明对某人工作的感谢或者只是说“我也是!”,因为读者可以立刻确认此类文章无需任何回应或进一步的动作,所以当读者达到邮件的最后一行,一个干净的结束符合他的心理需求。但是即使到了此时,说话之前也要再三考虑;一定要让别人觉得你说的太多而不是太少。(在忙碌的邮件列表中工作的更多想法的第二部分请看Appendix C, 为什么我要关注车棚的颜色?

多产VS非多产的线索

在忙碌的邮件列表中,你有两个诫命。第一,很明显,要指出哪些需要关注,哪些需要忽略。第二,要避免产生噪音的方式:不仅仅是你希望自己的文章保持较高的信噪比,你也希望这些信息可以刺激其他人也保持同样的信噪比,或者干脆不发表文章。

为了展示这是如何发生的,考虑一下事情发生的上下文。非多产的线索的特征是什么?

  • 发生的争论是在重复,仿佛发布者认为没有人听说过。

  • 随着赌注的缩小,夸大和连累的升级。

  • 大部分评论来自做过很少事情或没做过事情的人,而能帮助完成事情的人则保持沉默。

  • 大多数想法的讨论都没有作出明确的提议。 (当然,任何有趣的想法都是从不清晰的远见开始;重要的问题是之后的方向。讨论是否将远见变得更具体,或者分裂为更小的远见,副远见和本体论的争论?)

不要因为某个线索开始不够多产而认为它是浪费时间。它可能是一个重要的主题,正因为他非常棘手所以难以做出进展。

将线索引向有用而不是蛮干是一项艺术,仅仅是告诉人们不要浪费时间,或者告诉他们在没有形成建设性的内容前不要说话并没有用。你或许可以在私下这样想一想,但是如果你大声的说出来就会成为一种冒犯。相反,你必须促成进一步进展的条件—给人们一条路,一条可以将结果导向期望的路,而无需发出指挥命令。这样的基调将会大为不同。例如,这样很不好:

这个讨论已经跑的漫无边际了。我们可以暂停这个主题,直到某人能够提交一个补丁实现这些建议吗?没有理由继续反复说同一件事情。代码比单词更有力,伙计们。

然而这样很好:

线索浮现出了多个提议,但都没有完成所有的细节,至少还不足以形成表决。然而现在我们也说不出新东西了;只是在反复重复以前说过的东西。此时,为了进一步的讨论,最好提供提议的完整规格或补丁。然后我们至少有明确的动作可以做(即对规格达成一致,或应用和测试补丁)。

第二种方法与第一种方法完全相反。第二种方法不会让你与他人发生联系,也不要指责他们将讨论带入了螺旋。无论你在之前是否参与到线索的讨论,都要说是“我们”,因为即使你一直在线索中保持沉默,线索的结果也有你的份。它描述了为什么线索到了乌有之地,这样做并没有轻蔑或判决的含义—它只是不带感情的对事实的描述。最重要的,它提供了一个行动的正面课程,这样人们就不会感觉到讨论被关闭了(对于他们可以被诱惑去造反的限制),而会感到获得了一个方法可以将对话带入更有建设性的水平。这是人们自然会期望遇到的标准。

你不会一直希望让线程进入更有建设性的水平—有时,你只是希望它赶快离开。文章的目的只是从中选择一个,放弃另一个。如果你能断定线索离题太远,而且没有能实际上完成你所建议的步骤,那么你的文章会有效的终止线索,而且不需要这样做。当然,没有关闭线索的安全方法,即使有,你也不会希望去使用。但是询问参与者在作出可见的进展和停止讨论之间做出选择则是完美可防卫的,如果可以圆滑完成的话。然而,还是要小心永久的平息线索。一些纯理论的讨论可能会十分多产,取决于主题,而且如果过快的要求解决也会扼杀创造过程,也会让你看起来不够耐心。

不要期望线索会立刻停止。在你的文章之后,还是会有些文章,一方面因为邮件是排队传递的,另一方面是因为人们想说最后一句话。不必为此担心,你不用再说一遍。只需要让它逐渐消失或不消失,这取决于具体的情况。你不可能有完全的控制;另一方面,你可以期望在大量线索的统计上有显著的效果。

主题越软,辩论越长

尽管讨论会在任何主题上缓慢前进,但是随着主题技术难度的降低,缓慢前进的可能性就越高。毕竟,技术难度越大,能够理解的参与者也就越少。这些参与者更有可能是最有经验的开发者,他们已经参加过无数次这样的讨论,知道如何才能与每个人达成共识。

因此,如果技术问题易于理解或容易得出自己的意见,或者是诸如组织、公开性和资金的软主题,就很难达成共识。人们可以永远参与到这种辩论中,因为这事没有门槛,没有决定(甚至在之后)正确或错误的明确方法,而且因为等待其他讨论者结束是一个成功的策略。

对于长期的主题,讨论的数量与主题的复杂度成反比的原理,被非正式的称为Bikeshed效用。这里是Poul-Henning Kamp为BSD开发者作出解释的著名文章:

这是一个很长的故事,或者说是一个老故事,但它实际上很短。C. Northcote Parkinson在20世纪60年代初编写了一本叫做“Parkinson定律”的书,包含了许多管理动态性的真知灼见。

[...]

这些例子中包括自行车棚,另一个更重要的组件是核电站,我猜这描述了本书的年龄。

Parkinson展示了如何进入董事会,并得到建造花费几百万,甚至几十亿美元核电站的许可,但如果你希望建造自行车棚,则会陷入无休止的讨论。

Parkinson解释了这是因为核电站太大、太贵和太复杂了,人们无法掌握,所以不会去尝试,转而会假设某人会在需要时检查所有的细节。Richard P. Feynmann在他的书中提供了一些关于洛斯阿拉莫斯(美国新墨西哥州中北部一个无法人地位的社区,位于圣菲市西北。1942年被选作核研究基地,生产了第一批原子弹。从1947年至1962年原子能委员会统治着这个城镇。)的有趣而且非常到位的例子。

另一方面是自行车棚。所人都可以在周末建一个车棚,而且还有时间看电视上的比赛。所以无论准备的多好,无论你的提议是多么的有道理,人们会抓住机会展示他在做自己的工作,他正在关注,他就在这里

在丹麦,我称之为“配置你的指纹”。它关于自尊和声望,关于能够指向某事并说“这里!我那样的。”这是政客的典型特征,但是现在很多人都会这样。想想湿水泥中的足迹。

(他的完整文章也十分值得阅读。请看Appendix C, 为什么我要关注车棚的颜色?,以及http://bikeshed.com。)

任何参加过团队决策的人都会知道Kamp所说的东西。然而,通常还是不可能说服每个人避免喷刷自行车棚。最好你能指出这是一个必然存在的现象,并在你发现它时,说服高级开发者—这些文章拥有最高权重的人—尽早丢下他们的刷子,或至少不要添加噪音。自行车棚喷涂的聚会永远不会完全消失,但是你可以通过在项目文化中传播这个现象的知识让这种事变得时间更短,频率更低。

避免圣战

一场圣战是一场争论,经常但不会一直是相对的小问题,一般不会通过辩论得到解决,但是有人会充满热情的继续辩论,期望他们一方会获胜。圣战并不与自行车棚完全一样。人们粉刷车棚通常是突然跳出来的意见(因为他们可以),但是他们不必强烈的感觉必须如此,并且以后会表达其他的意见,互相矛盾的意见,以展示他们理解问题的所有方面。而另一方面,在圣战中,理解对方则是示弱的表现。在圣战中,每个人认为有一个唯一正确的答案;他们只是不认可是什么。

圣战一旦开始,通常就不可能让每个人都满意。在正在进行的圣战中指出这点并没有好处。每个人都已经知道。不幸的是,但是对于通过连续的讨论能否解决争论这一问题,是圣战并不认可的一个常见特性。从外部看来,很明显没有一方可以改变另一方的意见。而从内部看,则认为另一方太过蠢笨,也没有想清楚,但是经过足够的恫吓则能回心转意。现在,我没有说在圣战中永远没有正确的一方。有时确实有—在我参加的圣战中,真理当然永远属于我这一边。但是没有关系,因为没有算法可以令人信服的描述某一方是正确的。

人们试图解决圣战的一个常见的,但是不能令人满意的方法是说“我们的讨论已经浪费了过多的时间和精力!我们能不能把它忘掉?”这样有两个问题。首先,时间和精力已经投入,不可能收回了—现在唯一的问题是还有更多的力量吗?如果某人感觉更多的讨论会结束这个问题,那么继续就还有意义(从他们的角度看)。

另一个要求这件事必须丢弃的问题是这通常等同于允许某一方打破现状,通过无为宣布胜利。在某些情况下,现状无论如何是不能接受的,每个人都认为需要作出决定,必须有所行动。为每个人丢弃这个主题通常比任何人放弃论点更坏。但是因为这种两难可以平等的应用到所有人,所以仍有可能永久结束辩论。

那么你应当如何处理圣战?

第一个回答是,做好准备避免其发生。看起来并不是完全没有希望:

你可以预期到一些标准的圣战:可能关于编程语言、许可证(见Chapter 9, 许可证,版权和专利the section called “GPL和许可证兼容性”)、回复处理(见Chapter 3, 技术基础设施the section called “伟大的Reply-to辩论”)和一些其他主题。每个项目可能都有自己的圣战,长期开发者会很快熟悉。停止圣战,或者减少其危害的技巧在大多数地方都是相同的。即使你肯定你属于正确的一方,可以试着寻找一些方法展示自己对对方的同感,并理解另一方的论点。通常问题是在圣战中的每一方都尽可能高的建筑自己的墙,而使其他见解看起来是完全的愚蠢,放弃或改变思想的行动在心理学上变得不可忍受:这样做不仅仅是承认错误,而是必然并且会一直错下去。将这种承认变得可口的方法是展示你的不确定性—精确的展示你理解他们的辩论,发现他们至少很敏感,即使最终并不是令人信服。作出为回应姿态留出空间的姿态,通常情况会得到改善。也许你不会得到期望的技术结果,但是你可以避免对于项目士气的非必要相关损害。

当圣战不可避免时,尽早决定你要关注多少,并乐意公开放弃。当你这样做,你可以说你正在退出,这场圣战毫无价值,而不要展示出挖苦,并且不要利用这个机会对对方的辩论做最后一次攻击。只有优雅的去做才能有效的放弃。

编程语言的圣战有些特殊,因为虽然其本身的高技术性,然而很多人感觉自己有资格参与其中,因此结果可能取决于项目编码编写较好的部分的语言。最好的解决方案是尽早选定语言,由初始的有影响的开发者引入,根据你最舒服的语言,而不是因为其优于其他语言而使用。不要将对话退化为经典的编程语言比较(通常是当某人因为某些原因提出Perl。);那是死话题,你应该明确的拒绝涉及。

关于圣战的更多历史背景,可以看http://catb.org/~esr/jargon/html/H/holy-wars.html,Danny Cohen的论文普及了这个术语,http://www.ietf.org/rfc/ien/ien137.txt

“吵闹的少数派”效应

在所有的邮件列表讨论中,都有一些少数派不断用大量冗长的邮件血洗列表,给人存在大量异议的印象。有些像filibuster(一种议会程序,阻挠议案的通过),但是这种广泛异议的幻想更加强大,因为它分割了任意数量的不连续文章,大多数人无法跟踪何人在什么时间说了什么。他们会产生主题存在严重争议的直觉印象,并等着小题大做的平息。

中和这种效应的最好方法是明确指出并提供证据证明这种异议的数量与认可的数量相比是微不足道的。为了增大这种差距,你或许会希望私下调查大多数时候会保持沉默,但是你怀疑是认可大多数的人。不要说这些持异议者是故意夸大这种印象。他们一般不会是故意,即使故意,指出来也没有策略上的好处。你只需要指出双方实际数字的比较,人们就会认识到他们对于形势的直觉与现实不符。

这个建议并不是只能应用到具备明确支持和反对位置的问题。它可以应用到所有小题大做的问题上,但是如果大多数人认为讨论的问题不是一个问题时,则不是这么清楚。如果经过一段时间,你认为这个问题并不值得行动,并且看到它无法获得更多的吸引力(即使有了大量的邮件),你可以公开评论其没有吸引力。如果“吵闹的少数派”正在工作,你的文章就会像一缕清风。大多数人对于这个讨论的印象都会有一些阴郁:“好象是发生了一些大事,因为有很多文章,但是我看不出有什么进展。”通过解释讨论的形式使其显得比实际上更加吵闹,你给其新的面貌,人们可以重新修订自己对于发生问题的理解。

刺儿头

在电子论坛对付刺儿头并不比在现实中容易。这里“刺”不是“无礼”。无礼的人很讨厌,但不一定难对付。本书已经介绍了如何处理他们:在第一时间回复无礼行为,之后,选择忽略他们或者同其他人一样对待他们。如果他们继续无礼,他们会让自己更加不受欢迎,并在项目中毫无影响力,所以这是他们自己的问题。

真正的问题不是完全无礼的人,而是那些操弄或滥用项目进程,消耗他人时间和能量,而不会为项目带来任何利益的人。这些人经常会寻找项目规程中的楔点,而释放在其他地方无法获得的影响力。这比单纯的无礼更加狡猾,因为其导致的行为或损害都不是随意的观察者能够发现的。一个经典的案例是filibuster,某人会一直声称讨论的事情还没有准备好解决,并一直提供更多的解决方案,以及对旧方案的新视点,而实际上是他感到会达成共识或投票,而他可能无法保持领先。另一个例子是当一个辩论无法达成一致,但是团队尝试至少理清异议并为所有人制作一份以后可以参考的总结时。蓄意阻挠者知道总结会导向他不期望的结果,所以会通过反对合理的建议或引入意料之外的新条目来夸大问题的复杂性,试图延迟总结。

处理刺儿头

为了中和这种行为,我们需要理解从事这种行为的心理。人们并不是有意识的这样做。没有人会在早晨起床并对自己说:“今天,我会处理规程表单,从而成为恼人的蓄意阻挠者。”相反,这种行为经常是出于希望在项目互动和决策中发表意见的半偏执的情绪。有些人感觉自己没有被重视,或者(更严重的情况)认为存在一个针对自己的阴谋集团—其他项目成员决定成立一个排他的俱乐部,而他不是其成员。然后作为辩护,在他的思想中,认为按照字面意思遵循项目的规则,并参与到项目规程的正式处理中,从而让所有其他的人可以重视他。在极端的例子中,某些人甚至会认为自己正在为拯救项目而孤军奋战。

不是所有的人在同一时间可以看到这种攻击,某些人可能会完全看不到,除非提供了强有力的证据。这意味着中和它需要大量的工作。说服自己它的发生并不足够;你也需要配置足够的证据说服他人,并使用考虑周到的方法分发这些证据。

考虑到有大量的工作,最好不要容忍太长时间。考虑到它的寄生性,但只是温和的疾病:感染时并不会对项目造成过大的损害,药物反而可能有严重的副作用。然而,如果损害变得无法容忍,就应该采取行动。从收集见到的模式的记录开始。确保包含对公共归档的引用—这是项目保留这些记录的原因,所以你也可以利用它们。一旦建立了好的案例,开始与其他参与者的私下对话。不要告诉他们你所观察的;相反,首先要询问他们所观察的。这恐怕是你最后一次收集他人对于麻烦制造者行为未过滤反馈的机会;一旦你开始对此事的公开讨论,意见就会分化,没人会记得过去对于此事的想法。

如果私下讨论表明至少有其他人也发现了这个问题,则是时候行动了。你应当十分小心,因为很容易给这些人机会让你显得对他们不够公平。无论你做什么,不要指控他们因为偏执狂恶意滥用项目的规程,或者任何你怀疑他们的事情。你的策略是必须保持合理性和对于项目整体利益考虑,以改良个人的行为或使之离开作为目标。取决于其他开发者,以及你与他们的关系,首先在私下里获取同盟者是一个优势。或者如果不是;则只能会暗中的破坏,如果人们认为你正在从事一项不当的政治诽谤活动。

要牢记,尽管是另外一个人具有破坏性,但如果你不能支持你的公开指控,那么就会看起来是那个破坏者。请确保你拥有足够多的实例来描述你所说的,并在直接说出的情况下尽可能的保持礼貌。你可能无法说服有问题的人,但只要能说服所有其他人就足够了。

案例学习

我只记得一次,在10年的自由软件工作中,事情变得太坏,以至于我们必须要求某人停止发布文章。更常见的情况是,他并不是无礼,只是希望更有益。他只是不知道何时发布何时不发布。我们的邮件列表对公众公开,但是他发布的太频繁,在许多不同的主题中提出问题,成为了社区的噪音问题。我们已经和蔼的告诉他在发表文章前对文章多做一点研究,但是没有效果。

最终有效的策略是如何根据中立、定量的数据构建强大案例的完美案例。我们的一个开发者研究了一些归档,然后将如下信息私下发送给了一些开发者。冒犯者(在列表中的姓显示为“J. Random”)在项目中的历史不多,没有贡献任何代码或文档。然而他是邮件列表中第3活跃的用户:

From: "Brian W. Fitzpatrick" <fitz@collab.net>
To: [... recipient list omitted for anonymity ...]
Subject: The Subversion Energy Sink
Date: Wed, 12 Nov 2003 23:37:47 -0600

In the last 25 days, the top 6 posters to the svn [dev|users] list have
been:

    294  kfogel@collab.net
    236  "C. Michael Pilato" <cmpilato@collab.net>
    220  "J. Random" <jrandom@problematic-poster.com>
    176  Branko Čibej <brane@xbc.nu>
    130  Philip Martin <philip@codematters.co.uk>
    126  Ben Collins-Sussman <sussman@collab.net>

我可以说这些人中的5位会在不久的将来将Subversion带到1.0。

我也必须说我们中的一位也在消耗另外5人的时间和精力,更不用说整个
邮件列表,因而(虽非故意)也延缓了Subversion的开发。我没有做线索分析
但是通过vgrep我的Subversion邮件,我发现此人的每个邮件都会被上面5人中
的2人回复过。

我觉得有必要做一次根本的干预,即使我们会吓跑前面提到的这个人,和蔼
和友好的方法被证明没有效果。

dev@subversion是辅助进行版本库控制系统开发的邮件列表,而不是一个团队
心理治疗会议。

-Fitz,尝试从堆积了3天的svn邮件中费力前行

尽管一开始还不明显,但J. Random的行为是滥用项目规程的典型案例。他不会像filibuster一个表决那样明显,但是他利用了邮件列表中成员自我评审的政策。我们依赖每个个体的判断。因此,我们没有规程资源可以处理某人是否没有或没有练习这种判断。没有可以让某人指出并说某个家伙违反的规则,但每个人知道他过于频繁的文章已经成为一个严重问题。

Fitz的策略是专横的事后回想。他收集了定量的证据,然后谨慎的将其首先发送给那些在任何过激行动中都会对支持起关键作用的人。他们认可有必要采取行动,最后我们在电话上联系了J. Random,直接描述了这个问题,告知他停止发表文章。他从未真的理解原因;如果能够理解,他可能会尝试首先进行合适的判断练习。但是他认可停止发布文章,邮件列表又变得可用了。这个策略可以发挥作用的部分原因或许是我们可以限制其发表的隐含威胁,我们可以通过软件的审核功能来防止垃圾邮件(看Chapter 3, 技术基础设施the section called “垃圾邮件防护”)。但是我们能够让该选择作为备用的原因是Fitz已经从关键人物那里收集了必要的支持。

处理成长

开源世界中成功的价值很重。随着你的软件的流行,搜寻信息的人也会急剧增加,而能够提供信息的人则增长的慢很多。此外,即使比率能够保持平衡,在大多数开源项目中处理交流也依然存在基础扩展问题。以邮件列表为例。大多数项目有一个一般用户问题的邮件列表—有时,列表的名称是“users”、“discuss”、“help”或其他。无论名称是什么,列表的目的相同:为人们获取问题的答案提供一个场所,同时其他人可以观看并通过观察这种交换(假设的)获取知识。

这种邮件列表可以在数千用户和每天几百文章的情况下工作良好。但之后不久,这个系统就会出现问题,因为每个订阅者看到的文章会超过单个订阅者每天可以处理的数量,这个列表成为了其成员的负担。想象一下,如果微软有一个针对Windows XP的邮件列表。Windows XP有数亿的用户,如果仅有千分之一的用户在24小时内有问题,那么这个假设的列表每天也会有数十万的文章!不可能有这种列表,因为不可能有人会一直订阅它。问题不仅仅限于邮件列表;同样的逻辑也可以应用到IRC频道,在线讨论论坛,以及所有从单个人获取问题的团队。其暗示并不吉利:大规模并行支持的普通开源模型不能扩展到支配全世界的级别。

当论坛达到临界点时并不会发生爆炸。只有一个静悄悄的负面反馈效果:人们会取消列表的订阅,或者离开IRC频道,或者不再去咨询问题,因为他们无法去听所有的噪音。因为有越来越多的人作出了理性的选择,论坛的活动会看起来一直处于可管理的级别。但是,它精确的处于可管理级别是因为理性的(或仅仅是有经验的)人会去寻找其他地方获取信息—而缺乏经验的人会留下来继续发表文章。换句话说,随着项目的成长,如果仍使用未扩展的交流模型,那就会产生询问和回答的平均质量逐渐下降的副作用,感觉就好象新用户比原来更呆了,但实际上并不是如此。只是高人口论坛的收益/花费比变得更低,自然那些有经验的人会开始在其他地方寻找答案。根据项目的成长调整交流机制包含两个相关的策略:

  1. 识别出论坛特定部分,甚至整个论坛正在经历有限制的增长,将这部分分割为新的更专业的论坛(也就是说不要让坏的拖累好的)。

  2. 确保有许多自动的信息来源,并组织有序、更新及时和易于查找。

策略(1)通常并不难。大多数项目有一个主要论坛开始:一个一般的讨论邮件列表,会包含所有的特性构想、设计问题和编码问题。项目的参与者都会在这个列表上。经过一段时间,整个列表就会很清晰的进化为基于不同主题的子列表。例如,一些线索很明显是关于开发和设计;而另外一些是诸如“如何完成X?”的用户问题;或许还有第三类关于如何处理bug报告和增强请求的主题;等等。对于每一个个体,或许会参与到许多不同的线索类型,但是这些类型之间没有过多的重叠。他们可以划分到不同的列表,而不会造成严重的割据问题,因为这些主题极少会跨越主题的边界。

实际上这种分割是两步骤的过程。你创建新的列表(或者IRC频道,或任何其他的东西),然后你要花必要的时间有礼貌的唠叨和提醒人们使用新的更合适的论坛。后一个步骤会持续几周,但是最终人们会明白。你只需对所有发送到错误目标的人解释这个问题,然后因为大家都看到得到,人们就会被鼓励例行公事一样去帮助解决。当然,提供一个所有列表的指南网页也非常有用;你的回复可以直接引用网页,然后作为奖励,接收者会在发表文章前通过指南学习到一些东西。

策略(2)是一个持续的过程,会伴随项目的一生,需要许多参与者。当然,它部分依赖于是否拥有及时的文档(Chapter 2, 起步the section called “文档”),并能够指引人们去观看。但不仅仅如此;这个小节的后面会详细讨论这个策略。

归档的显著使用

通常来说,开源项目中的所有交流(除了一些IRC的对话)都应该归档。归档应该公开且可搜索,并要具备引用的稳定性:也就是一旦信息记录到了特定的地址,就可以永远使用这个地址。

尽可能多的使用那些归档,越显著越好。即使你知道某个问题的答案就在你的脑中,但如果你知道归档中有一个包含此答案的引用,那么请找到并展示出来。每次你使用公开可见的方式完成,有些人就会知道归档,并会在其中寻找答案。另外,通过引用归档而不是重写建议,可以加强对于复制信息的社会标准。为什么同一个答案会出现在不同的地方?当可以找到答案的地方还比较少,人们就更可能会记住地址并再次查找。精心放置的引用也可以帮助改进搜索结果的质量,因为他们可以加强目标资源在互联网搜索引擎中的权重。

当然有时复制信息也有意义。例如,在归档中已经有了一个来自别人的回应说:

看起来你的Scanley索引开始fronbnicated。为了unfrobnicate,可以按照如下步骤:

1. 关闭Scanley服务器。
2. 运行Scanley的'defrobnicate'程序。
3. 启动服务器。

然后,几个月之后,你看到另外一篇文章显示某人的索引变得frobnicated。你搜索归档并发现了上面这个较早的回复,但是你认识到它遗漏了一些步骤(或许是因为误解,也可能是因为软件在那篇文章之后发生了改变)。最经典的方式是发表一篇新文章,更完整的指导,并明确的废弃较早的那篇文章:

看起来你的Scanley索引已经变得frobnicated。我们在7月份看到过这个问
题,而且J. Random在http://blahblahblah/blah发布过一个解决办法。下面
是根据J. Random的指导unfrobnicate你的索引的方法,有一些扩展:

1. 关闭Scanley服务器。
2. 成为通常运行Scanley服务器的用户。
3. 作为该用户,在索引上运行'defrobnicate'程序。
4. 手工运行Scanley,并查看索引是否工作。
5. 重启服务器。

(在理想的世界,可以为原来的文章附加一个注释,说明有较新的信息,并指向新文章。然而,我不知道有什么归档软件支持“废弃”特性,或许因为在不违反归档逐条的归档完整性的情况下实现有一点狡猾。这是设置一个专门的网页回答常见问题的另一个原因。)

归档可能经常被用来查找技术问题的答案,但是他们对于项目的重要性不仅如此。如果说项目的正式指南的法定法律,那么归档就是不成文法:所有决策如何制定和如何得出的记录。对于任何重现的讨论,从归档搜索开始是义不容辞的。这允许你从当前状态、期望的目标、举反证和发现你没有想到立场的摘要开始讨论。另外,其他参与者会期望你已经做了归档搜索。即使之前的讨论没有结果,在你重新提出这个主题时也要指出它们,这样人们就可以自己看到a) 讨论没有结果,并且b) 你做了功课,那么现在说一些没说过的话吧。

将所有的资源视为归档

之前的所有建议不只是能应用到邮件列表归档。零散的信息都位于稳定,便利和可查询的地址,这必须成为项目所有信息的组织原则。我们以项目FAQ为例进行研究。

人们如何使用FAQ?

  1. 他们希望在其中查找特定的单词和短语。

  2. 他们希望进行浏览,获取信息,而不是去寻找特定问题的答案。

  3. 他们希望诸如Google之类的搜索引擎可以知道FAQ的内容,所以可以搜索到FAQ条目。

  4. 他们希望在FAQ中直接为其他人提供特定项目的引用。

  5. 他们希望为FAQ提供新的材料,但是注意到添加比查询回答要少许多—FAQ更多的是阅读,而不是编写。

第1点暗示我们FAQ一定要以文本格式存在。第2和第3点暗示FAQ应当以HTML格式存在,第2点也说明HTML必须针对可读性进行设计(即你会希望控制起观感),而且必须有目录。第4点意味着FAQ的每个条目都赋予了一个HTML命名的Anchor,一个用户可以到达页面特定位置的标记。第5点说明FAQ的源文件必须用便利的方法存在(见Chapter 3, 技术基础设施the section called “版本化所有的东西”),并使用易于编辑的格式。

格式化FAQ只是如何让一个资源可以展示出来的例子。同样的属性—直接的咳嗽索性、主要搜索引擎的存在性、可浏览性、引用稳定性和(合适的地方)可编辑性—可以应用到其他网页、源代码树和bug跟踪系统等等。只是在不久之前大多数邮件列表归档软件才认识到了这些属性的重要性,也是邮件列表倾向于本身具备这些功能的原因,其他格式或许需要维护者花费更多的经历(Chapter 8, 管理志愿者讨论了如何在多个志愿者间分担负担)。

编制法律的传统

随着项目的日积月累和复杂化,每个新来的参与者必须吸收的数据量大增。那些伴随项目很长时间的人能够根据以前的经历认识到和发明项目的习俗。他们会本能的意识到积累了大量传统,并会为新来者的大量过失而感到惊讶。当然,问题不是新来者的质量降低了;而因为他们面对的是比以前更多的积累负担。

一个项目积累的传统取决于他们交流和保存信息的方法,以及他们的编码标准和其他技术备忘录。我们已经看了两种标准,分别在Chapter 2, 起步the section called “开发者文档”Chapter 4, 社会和政治的基础架构the section called “写下所有的内容”,也都有各自的例子。本小节关注的是如何在项目进化中保持指南的及时性,特别是关于如何管理交流的指南,因为这些指南会随着项目规模和复杂性的成长发生最显著的变化。

首先,关注人们陷入混淆的模式。如果你看到同样的情形屡次发生,特别是发生在新参与者身上时,就是需要记录指南的机会了。其次,不要厌烦反复说同样的话,也不要表现出对说这些话的厌烦。你和其他项目老兵都需要经常的重复自己;这是新手到来时不可避免的副作用。

每个网页、每个邮件列表信息和每个IRC频道必须考虑广告空间—不是商业广告,而是自己项目资源的广告。你所放置的内容取决于会观看它的人口统计数据。一个针对用户问题的IRC频道,其中通常是那些从未与项目交互的人—通常是只安装了软件,需要立刻获得问题答案的人(毕竟,如果他们可以等待,他们可以发送到邮件列表,整体上他将会花费较少的时间,尽管那样会需要更长的时间得到回答)。人们通常不会在IRC频道作出永久投资,他们会露面,询问问题,然后离开。

因而,频道的主题必须针对那些希望立刻寻找软件技术回答的人,而对那些以长期方式参与项目的人,社区交流指南或许更合适。下面是真正忙碌频道的处理方式(Chapter 3, 技术基础设施the section called “IRC / 实时聊天系统”):

你现在位于#linuxhelp

关于#linuxhelp的主题请阅读
http://www.catb.org/~esr/faqs/smart-questions.html &&
http://www.tldp.org/docs.html#howto 询问问题之前 | 频道规则
在http://www.nerdfest.org/lh_rules.html | 升级到内核2.6.x
请看 http://kerneltrap.org/node/view/799 
 | 内存读可能性: http://tinyurl.com/4s6mc ->
更新到2.6.8.1或2.4.27 | 哈希算法灾难: http://tinyurl.com/6w8rf
| reiser4放出

在邮件列表中,“广告空间”是追加在每封邮件后的小注脚。大多数项目会在这里放置订阅/取消订阅的指导,也可能是项目主页或FAQ的链接。你或许会认为所有订阅列表的人都会知道如何做,很可能是—但是会有更多不是订阅者的人会看到邮件列表信息。一个归档的文章会被链接到许多地方;实际上,某些文章最终会变得家喻户晓,有远多于列表订阅者的阅读者。

格式化可以产生明显的区别。例如,在Subversion项目,我们在Chapter 3, 技术基础设施the section called “Bug跟踪的预过滤”中描述的使用bug过滤技术,取得了有限的成功。经验不足的人会一直发起许多虚假的bug报告,每当发生这种情况,档案管理员必须像他之前的500人那样对此有足够的认识。某天,我们的某个开发者终于忍无可忍,对那些不阅读问题跟踪系统指南的倒霉用户开始发火,另一个开发者则决定这种情况不应该再发生了。他建议重新调整问题跟踪首页的布局,这样最要的部分,也就是在提交之前必须在邮件列表中讨论bug的命令,将会使用较大和粗体红色字体,亮黄色背景,页面居中突出显示处理。我们这样做了(你可以在http://subversion.tigris.org/project_issues.html看到结果),结果是虚假问题的录入率大大降低。我们依然会得到虚假的问题,当然—我们一直会—但是比例显著降低,甚至是在用户数大增的情况下。结果不仅是bug数据库中的垃圾大大减少,而且那些响应问题的人也得到了好情绪,也就更容易在面对罕见的虚假bug时保持友好。这样不仅改善了项目的形象,也改善了志愿者的心理健康。

仅仅是写出指导方针的课程对于我们来说还远远不够。我们也必须让最需要的人看到这些东西,它们的状态要像介绍材料一样格式化处理,这样对项目不熟悉的人们也可以立刻清晰明了。

静态网页不是发布项目习惯唯一的维纳斯。一定数量的的交互政策(友情提示的感觉,而不是冷冰冰的手铐脚镣)也是必需的。所有的同级评审,甚至Chapter 2, 起步the section called “实践明显的代码评审”描述的提交评审,都应该包括对于人们是否遵守项目规范的检查,特别是与交流习惯相关的。

Subversion项目的另一个例子:我们在版本控制版本库设定了“r12908”表示“修订版本12908”的习惯。小写的“r”前缀很容易输入,又因为它只有数字的一半高度,所以与数字在一起时非常易于识别。当然,设定了习惯并不意味着每个人都会一直以正确的方式使用它。因而,每当有这样包含日志信息的提交邮件时:

------------------------------------------------------------------------
r12908 | qsimon | 2005-02-02 14:15:06 -0600 (Wed, 02 Feb 2005) | 4 lines

Patch from J. Random Contributor <jrcontrib@gmail.com>

* trunk/contrib/client-side/psvn/psvn.el:
  Fixed some typos from revision 12828.
------------------------------------------------------------------------

...某些提交评审者就会说“顺便说一句,请使用‘r12828’,而不是修订版本(revision)12828引用过去的变更。这不是卖弄学问;重要的是自动解析和人类阅读。

通过遵循一般的原理,包括对常见实体的权威参考方法,以及必须放之四海皆准参考方法,这个项目输出特定的标准。这些标准使得人们可以编写工具用更有价值的方式展现项目交流—例如,一个格式为“r12828”的修订版本可以在版本库浏览工具中被转化为可用的链接。但是如果修订版本写成“revision 12828”,则这项工作将会难许多,一方面因为链接会在换行处分隔,另一方面也因为限制不足(单词“revision”会经常单独出现,一组数字也会单独出现,而他们的组合“r12828”则只意味着修订版本号码)。类似的,同样的关注面也适应于问题号码,FAQ项目(提示:在命名的Anchor和ID属性描述的,使用命名锚点的URL)等等。

即使对于没有简短和权威形式的实体,也要鼓励人们提供一致的关键细节信息。例如,当引用到一个邮件列表信息时,不要只给出发送者和主题;请也给出归档URL信息的ID头。这样可以让那些虽然自己也有邮件列表拷贝(人们有时会保存离线备份,例如在旅行中使用笔记本时)的人,能够明确无误的定位到正确的信息,甚至无须访问他们自己的归档。发送者和主题并不足够,因为一天里同一个人可能为某一个线索发表过许多文章。

项目愈大,愈是需要这类一致性。一致性意味着人们会在所有的地方,看到被以相同的方式遵循的模式,这样他们知道自己也需要遵循这些模式。作为回报,减少了回答问题的必要。拥有几百万读者的负担并不比仅仅一个更大;扩展性的问题源于一定比例的读者开始提问了。随着项目的成长,必须依靠增加信息的密度和可访问性,才能减少这种比例,这样人们才能更容易的找到答案,而无需提问。

Bug跟踪系统中无对话

对于积极使用bug跟踪系统的项目,要小心它变成讨论论坛,虽然邮件列表可能更好。通常情况下,它总是很无辜的开始的:某人评论了某个问题,例如提出了一个解决方案或部分补丁。另一个人注意到这个,认为这个方案有些问题,所以附加了另一个评论指出这个问题。第一个人再次回应,对问题作出补充,就这样一直继续下去。

这样做的问题是,首先,bug跟踪系统用于讨论时非常的笨拙,其次,其他人可能不会投入关注—毕竟,他们希望在邮件列表中进行开发讨论,这也是他们查找问题的地方。他们可能没有订阅问题变更列表,即使订阅了,也不可能紧跟所有的变化。

但是这个过程中到底何时出了差错?是不是那个人将自己的解决方案附加到问题时—她是不是应该发布到列表中?或者是当第二个人直接回复这个问题,而不是在列表回复时。

这里没有正确的答案,但是有一般的原理:如果你仅仅是为问题添加数据,那么请在跟踪系统中操作,但是如果你想发起一次对话,那么请到邮件列表。不是每次都能判断出是哪种情况,但是你要作出最佳的判断。例如,当你提交的补丁会包含反对的解决方案时,你应当会预期有人会对此发出质疑。所以,即使你会自然的为该问题附加这个补丁(假定你不希望或者不能直接提交修改),也应当选择将其发布到邮件列表。有一定的可能性,整个交流最终会有得出结果,某一方可能会说应该不仅仅是追加数据,而应该开始一场讨论了—在本小节开头的例子中,也就是第二个回复者,他认识到了补丁的问题,预测到将会有真实的交流发生,因而应该通过更合适的媒介完成。

用数学模拟来说,如果根据信息显示问题将会很快收敛,那么直接在bug跟踪系统中发布;如果看起来将会发散,那么邮件列表或IRC频道将会是更好的地方。

并不是说在bug跟踪系统中不能有任何交流。例如,向原报告者询问重现的步骤细节就一般是一个很容易收敛的过程。人们的回应并不是提出新的问题,而仅仅是澄清已经记录的问题。没有必要分散邮件列表的注意力;并不一定要通过小心跟踪系统中一系列的评论实现。同样的,如果你认为这个bug是误报的(例如,根本就不是一个bug),你只需要在问题中说出来。甚至指出解决方案中的些许缺陷也没有问题,只要该缺陷不会影响整个解决方案。

另一方面,如果你会在bug的范围或软件正确行为方式方面,指出哲学问题,你肯定会认为将有其他开发者参与。讨论也许会发散一段时间,那么请在邮件列表中完成。

如果选择了邮件列表,就一直要在问题中保存到邮件列表讨论的链接。对于查看问题的人,能看到对应的讨论是非常重要的,即使问题本身不是讨论的场所。发起这个线索的人会发现有点牵强,但是开源从根本上说就是一种撰写-回应的文化:让成千上万的人读起bug来更容易,远比三五个编写者的麻烦重要的多。

如果可以让读者更便利,可以将重要的结论或总结从邮件列表中粘贴到问题中。一个常见的习俗是开始一个列表讨论,在问题中附加讨论线索的链接,然后是讨论结束的时间,粘贴最终的总结(以及包含总结信息的链接),这样浏览此问题的人就可以轻松的看到已经得出的结论,而无需点击到其他地方。需要注意的是,这里不存在重复数据的问题,因为归档和问题回复都是通常是静态的,不会改变的数据。

公开性

在自由软件中,在纯内部讨论和公开联系声明之间通常有一个相对平滑的连接。这部分因为目标读者一直不明:因为大多数文章都是公开可访问的,项目无法控制整个世界对此的印象。某人—假设是slashdot.org的一个编辑—可能为谋篇文章带来几百万的读者,而本来没人认为它会被项目之外的人看到。这就是开源项目生活的世界,但是在实践中,这种风险通常很小。通常情况下,项目希望公开化的声明就会得到最大的公开化,只要你能用正确的机制指出其对外部世界的新闻价值。

对于主要的声明,通常会有4或5个主要分发渠道,所有的声明最好尽可能同时发出:

  1. 你的项目主页可能是项目中被看得最多的页面。如果你确实有主声明,请在此放一个夸张的广告。这个广告一定是一个简短的概要,可以链接到有更多信息的新闻稿。

  2. 同一时间,你的站点一定也要有一个“新闻”或“新闻发布”区,可以详细写明声明。新闻稿的部分目的是提供一个单独的权威“声明对象”,这样别的站点可以用来链接,所以要以此为依据确保其结构:要么每个发布一个网页,或每个是一个博客条目,要么其他种类可以被链接的实体,同时与同一区域的其他新闻稿区分开来。

  3. 如果你的项目有RSS供稿(见the section called “RSS供稿”),请确保声明也会出现在这里。这也可能在你创建新闻稿时自动发生,取决于你是如何设置的站点。

  4. 如果声明是软件的新版本,请更新http://freshmeat.net/中的项目条目(关于首次创建条目请看the section called “通告”)。每当你更新Freshmeat条目时,该条目就会出现在Freshmeat当日的变更列表中。这个变更列表不仅仅会在Freshmeat本身更新,也会出现在许多被很多人关注的门户站点(包括http://slashdot.org)上。Freshmeat也会通过供稿提供相同的数据,所以即使那些没有订阅你的项目供稿的人,也会通过Freshmeat看到声明。

  5. 向你的项目声明邮件列表发送一个邮件。这个列表的名称应当是“announce”,例如announce@yourprojectdomain.org,因为现在这已经成为了标准的习惯,而且列表的管理者一定要说明该列表的内容很少,仅用于主要的项目声明。大多数此类声明都是关于软件的新版本,但是偶尔也会其他事件,例如本章后面说的募集资金激励,发现安全漏洞(见the section called “声明安全漏洞”),或者项目方向的重大转移,也会发布到这里。因为内容很少,只用于重大事件,所以announce列表通常是项目中订阅最多的列表(当然,这意味着你不要滥用它—发布之前一定要小心)。为了防止其他人,甚至是垃圾邮件发出声明,announce列表应该一直需要审核。

要力争在所有的三个地方同时作出声明,越接近越好。人们在邮件列表中看到声明,而在主页或新闻发布区上没有对应的内容时就会感到困惑。如果你能将各方面的(邮件、网页等等)修改排队,并依次发出,你可以将这种时间差控制到最小。

对于不太重要的事件,你可以省略上面的某个发布出口。根据事件的重要程度,该事件还是会被外部世界注意到。例如,软件的一个新版本是主要事件,而设定下一次发布的日期,即使有些新闻价值,也不会比发布本身更重要。设定日期值得我们在日常邮件列表(而不是声明列表)中发一个邮件,以及更新项目时间线或网页状态,但仅此而已。

然而,你还是会在网上的其他地方的讨论中看到日期。在你的列表中的潜伏者仅仅会听,而不会说任何事,并不一定在其他地方也是沉默的。口碑会造成广泛的传播;你必须考虑到这一点,使用这种方式构建更小的声明,鼓励信息传递的精确性。特别的,你期望引用文章一定要在明确的在引用部分出现,就像你在写正式的新闻稿。例如:

仅仅是进度更新:我们计划在2005年8月中旬发布Scanley的2.0版本。你可以检查http://www.scanley.org/status.html的更新。新特性是正则表达式搜索。

其他特性包括: ...也会包含其他bug修正,包括 ...

第一段很简短,仅提供了最重要į