当 Unix 实践最接近开放源码时,就欣欣向荣,反之则停滞不前。

#19.1 Unix 和开放源码

开源开发的规则很简单:

  1. 源码公开。别隐藏秘密。公开代码以及产生代码的过程。鼓励第三方的同行复审确保其他人能够自由地修改和重新发布代码。尽可能地发展合作开发者。
  2. 尽早发布,经常发布。快速的发布节奏意味着反馈迅速而有效。每次递进发布间隔越小,回应真实世界反馈的修改过程就越容易。
  3. 给贡献以表扬。如果不能够给合作开发者以物质奖励,就给予精神表扬。即使可以给予物质的奖励,也不要忘记人们往往是为展示才华而不是为钱努力工作。

规则 2 的必然推论就是,单一发布不应该视为重大的事件,无需伴随太多的附带许诺和准备。将发布过程无情地精简非常重要,这样就不再为经常发布而感到痛苦。在发布准备期,其余工作都必须停止的安排是个可怕的错误(值得一提的是,如果使用 CVS 或者类似的版本控制,处于准备期的发布应该同主干开发线分开,这样就不至于阻塞主线开发过程。)总的来说,不要把发布当作什么特别的大事;而应该当作是例行公事。
—— Henry Spencer

牢记:频繁发布的原因是为了缩短和加速同用户和开发者间的反馈循环。因此,精工细作,等一切完美了才发布的想法是要不得的。不要许太多愿。一步一步地来,承认和公布现有的 bug,并有信心随着时间的推移,一定会达到完美。发布点多一点儿不是坏事,不必为版本号的增加而烦恼。

抛弃秘密开发的习惯,转而支持过程的透明化和同行复审是炼金术成为化学学科最关键的一步。同样你也开始发现,开源开发标志着软件开发终于长成为一门学科。

#19.2 与开源开发者协同工作的最佳实践

#19.2.1 良好的修补实践

代码的质量很难判断,所以开发者往往通过提交的质量来评估补丁,在提交者的风格和交流行为中寻找线索——该提交者是否设身处地为他们着想,是否知道评估和合并新的补丁究竟该怎样。

这是鉴定代码质量相当可靠的方法。在许多年处理来自数以百计陌生人补丁的过程中,我很少看到一个考虑周全、尊重我的时间的补丁会是技术上的赝品。反过来看,经验告诉我们,看起来马马虎虎或是打包很疏懒的补丁往往实际上就是赝品。

#19.2.1.3 不要包含可生成文件的补丁

在发送补丁之前需通览一遍,对于一旦维护者采用补丁、重新 make 后就能重新生成的文件,其补丁段应予删除。

#19.2.1.6 在补丁中包含文档

针对改动做好文档体现了一些好习惯。首先,已经为试图说服的维护者设身处地考虑过了。其次,表明对改动后的效果了如指掌,可以向其余不能查看代码的人解释清楚。第三,表示了对软件最终用户的关心。

良好的文档常常是区分“可靠的贡献”和“匆忙而邋的改动”最显著的特征。

#19.2.1.7 在补丁中包含解释

补丁应该包含一份说明,来解释为什么补丁是必须和有用的。这个说明并不直接给软件用户而是给接受补丁的维护者。

正确的态度非常有帮助,是对维护者时间的尊重,也是从容而谦逊的自信。表现出对所修补的代码充分理解,展示对维护者问题的认同,这些都是有益的。

一些经验丰富的开发者所发送的各种解释示例:

  • “我已经发现代码中有两个问题,X 和 Y。我改掉了 X,但是我并没有试图去解决 Y 问题,因为我对牵涉到的代码还不理解。”
  • “修改了一个当输入过长时的 coredump。我在修改的时候,试图寻找另外的溢出错误。我发现有一个可能在 blarg.c 中,在第 666 行附近。你能确定在每个传输中发送端产生的字节不会多于 80?”
  • “你是否已经考虑使用 Foonly 算法来解决这个问题?在http://www.example.com/~jsmith/foonly.html处有个好的实现。”
  • “补丁解决了当前的问题,但我意识到内存分配被不恰当地复杂化了。在我这里可以工作,但在发布前你应该进行重负荷测试。
  • “这可能太过于花哨,但无论如何我还是提交了。也许你会知道一个实现这种功能的更简洁的方法。”

#19.2.3 良好的开发实践

#19.2.3.6 推荐的 C/C++ 移植性实践

在移植层之外的任何地方,注意这条建议:

#ifdef 和#if 是最后一招,这通常是思路不当、产品过度差异化,无理由“优化”或是无用垃圾聚集的先兆。在代码中,它们就是诅咒。GNU 的/usr/include/ stdio.h 就是典型的悲剧。
-Doug Mcllroy

在移植层 #ifdef#if 的使用是允许的(如果控制得当)。在此之外,应该尽量限制使用,只用于有条件地触发 #include

严格地坚持编码规范,代码的一致和干净优先级最高,而编码规范自身的细节倒远在其次。

#19.2.4 良好的发行制作实践

#19.2.4.3 尊重和遵从标准文件命名实践

这里是些标准的顶级文件名及其含义。当然,并不是每个发行版本都需要所有文件。

  • README:最先被阅读的路标文件。
  • INSTALL:配置、编译和安装指导
  • Authors:项目贡献者列表(GNU 惯例)
  • NEWS:最近的项目新闻
  • HISTORY:项目历史。
  • CHANGES:修订版本之间重大更改的日志。
  • COPYING:项目许可证条款(GNU 惯例)。
  • LICENSE:项目许可证条款。
  • FAQ:项目常见问题解答的纯文本文档。

#19.2.5 良好的交流实践

#19.2.5.4 提供项目邮件列表

通告列表应严格控制。通信量最多一月几条:这个列表的整体目标是,向希望知道某些重要事情何时发生的人们提供信息,但并不需要知道日常繁冗的细节。如果这个列表在他们的邮箱中开始带来严重的混乱,许多人会立刻取消订阅。