作者介绍

1. 参与本书的作者列表

2. L

李建盛 ,别名适兕,开源布道师,开源之道(opensourceway.community)发起者,ALC Beijing 成员。

3. J

姜宁 - 华为开源软件中心技术专家,前红帽软件首席软件工程师,Apache软件基金会成员,Apache软件基金孵化器导师,参与了绝大多个中国发起的Apache基金会项目的孵化。本人06年开始加入到Apache社区项目开发,就被社区开放协作的氛围深深吸引,成为开源深度信徒。现在致力于开源社区建设,以及开源文化推广,尽其所能帮助国内开源项目成功。

4. 贡献者列表

前言

这是一本通过开源的方式撰写的指导手册,在这里我们将依托社区的力量帮助大家了解开源协作的背景知识,介绍相关的协作开发工具,以及开源协作中的最佳实践。

在二十年前,开源(Open Source)这一词汇被 Open Source Initiative 提出。随着越来越多的开源项目成为我们信息化社会的基石,开源作为一个高效的软件协同开发方式逐渐被世人接受。开源的本质是开放与协作,人们可以借助开源的手段开发软件,开发硬件,编写手册。

以往我们作为开源的消费方,开源项目更像是一份免费的午餐,我们不需要知道午餐是怎么做出来的,我们只需要吃好这份午餐(了解开源项目是如何使用)就可以了;随着我们成为"免费午餐"的生产方,通过开源来为我们创新的步伐助力的时候,急切需要有一份详尽的开源手册帮助大家掌握开源项目实际操作的知识与技能。

  • 如果你刚刚接触开源,可以从手册中开源的文化背景,开源协作的社交礼仪入手,通过参与现实的开源社区项目来体验开源的魅力。

  • 如果你有一个不错的想法来解决业界的难题,并且想通过开源项目的方式邀请更多与你有同样想法的人与你协作的话,本手册将向你介绍如何依托市面的开源工具以及协作平台来提高开源协作效率。

  • 如果你正在为开源项目运营而苦恼,那通过本手册你将会了解如何通过透明公开方式来孕育社区项目,让项目具备持续发展的生命力。

  • 如果你有不错的开源项目运营经验想跟我们分享你的心得,本手册将是你展示自我风采的舞台,欢迎通过邮件,issue,PR的方式分享你的心得。

这是一本探讨社区协作的开源手册,我们也将会采用社区协作的方式来完善这本手册。如果你觉得这本手册的立意不错,欢迎加入我们的 讨论区,通过创建issue的方式反馈你的意见建议,通过PR的方式帮助我们修正手册中的错误。 最后希望这本手册很够帮助到更多想实际参与到开源项目开发的人们。

准备开源

5. 开源最佳实践

5.1. 上游优先的开发方式

开源项目之间是相互依赖包含构成了一个完整的生态体系。一个开源项目可能会使用到很多第三方的开源项目,这个开源项目也可能被第三方项目引用包含到其它的开源或者非开源的项目中。通常我们会把被依赖的项目称为上游项目,对上游项目产生依赖的项目为下游项目。上游项目提供了具体的功能实现,下游项目一般通过调用上游项目实现相关的功能。

上游优先的开发式是指开源开发者为了实现自己的需求把对上游项目的修改都回合到上游社区项目中,通过升级上游项目版本的方式获取最新的功能, 而不是只是在自己的项目中进行自己的需求修改。这样做有以下方面的好处:

  • 把代码修改合入上游,维护成本最低的协作方式。

开源项目的有很多的贡献者,大家之所以能够在一起协作的根基是代码开放的, 这样每个人都可以在别人的基础上添加自己的工作。为了达到高效的协作需要保证大家的相互修改不应该产生副作用,或者说我们需要有一个协调机制保证大家修改过的代码放在一起还能够工作。 如果大家把修改都提交到一个上游版本中,在代码提交之前只需要一次解决修改冲突问题,这是最省力也是最有效的协作方式。

Fork上游代码看上去挺简单的,我的修改我做主。但是从fork的那天开始你就要背负维护这个fork版本的生老病死的所有的责任。一旦你的代码与上游代码差异越大, 你的代码想要合并上游的更新的代价也就越大。这样带来的直接问题就是无法及时享受到上游代码更新带来的好处。 明智的开发往往会在自己修改代码之后,努力将自己的修改推进上游代码以降低自己的维护成本。

  • 回合上游代码之后,随时可以使用上游代码的最新更新。

上游项目发布新版本了,我能在第一时间将上游项目集成到我的扩展项目中吗?这个和你如何引用上游代码有很大的关系。 一般来说如果你只是片段引用上游代码或者直接fork上游代码, 你需要自己做所有的修改适配。如果上游项目发展不是很快的话,你可以能花几天的时间就适配好了,但是如果项目发展很快,三个月出一个版本的话,你的适配步伐很难跟上上游的开发速度的。 一般来说fork版本的维护只有一个人, 而上游的开发可能是4~5个人, 同时社区还会有很多贡献者也在合入代码, 在这种情况下fork之后的版本往往采用的方式就是不会合入上游新开发的特性和功能的而自己独自地走下去。

如果你还想继续享受到上游开发带来的好处, 请将你的代码回合到上游代码中,因为这样做你仍然可以以0成本的方式使用上游最新的代码。

  • 回合上游代码,可以让更多的人受益,推动项目成功。

众人拾柴火焰高, 一个成功的开源项目背后必然有一个蓬勃发展的社区。依托于社区我们可以做到很多平时一个人在公司无法实现的目标。 在开源项目社区中,大家共同的目标就是把这款开源软件做得更好。这里有用户报系统的bug,有贡献者将自己的使用心得转换成patch提到社区中了,有维护人员不断的添加新的功能并及时得到用户的反馈而又继续开发更炫酷的功能。开源项目依托于社区只所以可以不断发展壮大,正因为大家是相互协作的,力气都往一处使,每个人在贡献自己的力量的同时也为大家节省了很多开发协作的时间,依托于一个社区大家可以共享工作成果。 假如你想借助开源完善丰富你的产品的话,维护一个统一的社区比将社区分裂要好很多。

5.4. 撰写有吸引力README文档

README ,中文常常翻译为自述文件[1],在软件开发的历史上,自述文件出现的时期也算很早了,上世纪70年代就有人关注项目中的自我描述文件的重要性了。甚至这是作为一名hacker 必须做到的事情[3]。

当然在GitHub出现之前大家确实没怎么在意,即使有的项目做的蛮好的,比如Hacking,GitHub 的创始人之一Tom Perston-Werner曾经专门撰文描述[2]其对于自述文件的理解:

  • 最重要的是,你有了一次全面思考整个项目的机会,而不必额外去思考为了代码应该如何组织或者需要提供哪些具体的公共 API 所进行的代码修改。记住那种你第一次写自动测试脚本,并意识到你发现了很多将有可能进入你代码库 bug 的感觉。如果你在写具体代码之前写下自叙文档,你将拥有完全相同的感觉。

  • 作为为了知道你想实现什么而写下自叙文档的副产品,你的面前将会有一份非常棒的文档。你将发现你在项目开始前写下自叙文档会非常简单,因为当时你热情高涨。如果是项目开始后,追溯补充一个自叙文档一定是一个绝对的错误,这个时候你一定会错过所有重要的细节。

  • 如果你正在参加团队开发,你的自叙文档将获取更多里程。如果其他成员在你开发完成前获取了这些信息,他们可以更有自信的在别的项目上与你的代码进行交互。没有定义任何接口,你必须以串行的方式编码或者面对大量代码的重构。

  • 基于文档的讨论也会更简单。没有文档的讨论问题容易陷入无休止和绕圈。写下提议的解决方案这么一个简单的动作能让所有人都有一个明确的想法可以讨论和迭代。

随着GitHub 的日渐流行,自述文件成为了一个项目仓库的重要展示,无论从用户体验的角度,让第一次接触项目的人有一个良好的第一印象,还是从开发者自己打造归属感,都是非常 重要的,所以撰写一份优秀的自述文件,可以有效帮助项目的认可度、加强认同感,从而让项目成功的几率更高些。

cURL 是颇为经典的例子了:

440px README cURL

下面我们就来逐一说明一下,自述文件应该包含哪些内容,并举一个做的非常好的项目的例子。

Hacker’s-eye introduction traditionally included in the top-level directory of a Unix source distribution, containing a pointer to more detailed documentation, credits, miscellaneous revision history, notes, etc.

— Eric S. Raymond,The Jargon File: README-file

5.4.1. 项目名称

对,你的项目较什么名字,可以带上logo更佳。如 iSulad:

isulad project name

5.4.2. 徽章和标志

这些酷酷的小玩意,起到的作用是出乎我们意料之外的,正如现在社交媒体使用的Emoji一样:

build success
coverage process
  • 版本号

NPM verison
GitHub version
Bower Version

更多内容请参考 GitHub 徽章

5.4.3. 项目描述

这就到了最为精髓的部分了,请用一两句简短的话将你的项目描述清楚,项目是做什么的,愿景是什么?如 iSulad

isulad project description

5.4.4. 安装

就现代软件的供应链来讲,尤其是分布式的模块分布,以及包管理器的成熟,举个例子,比如 Mac OS 下的命令行工具 homebrew:

---
$ brew install wget
---

就直接完成了 wget 的安装。 诸如 go、npm、Pypi 等等均如此。

5.4.5. 使用实例

请在这里写上你如何使用,比如 现代开源手册 项目的用法就非常的言简意赅:

---
# 编译时通过调用 process-resources 生成 HTML5 文件默认 goal 已配置:
$mvn
---

用浏览器打开生成的 HTML 文件 “target/generated-docs/OpenSourceManual.html” 。

5.4.6. 文档

请在此列出项目的文档:

  • 上手指南

  • 开发者文档

  • API 参考

  • 用户手册

等等

5.4.7. 作者/贡献者

请在此列出所有的对项目有贡献的人名以及他们的邮箱地址,如果可以的话,将他们的社交账号一并列出如GitHub id、Twitter id等。

5.4.8. 许可证

通常情况下,项目的主目录下会放一个 License 的文件,表明该仓库的项目是在何种开源许可证授权的,当然你也可以在这里进行一定的说明。

此项为可选,不是必须。

5.5. 撰写贡献者指南

开源项目想要生生不息的发展下去,招募更多贡献者加入是必做的事情之一。请在这里写下项目的贡献者指南链接地址。

关于贡献者指南的模板,请参考:

本章将以举例的方式说明,一篇优质的贡献者指南应该有哪些内容,而且会举出一些业界典范。本文档大部分来源于 Nadia eghbal 所写就的 贡献者指南模板 并做了适当的补充。

5.5.1. 介绍

在此写一些友好的内容!

首先,非常感谢你正在考虑为 Active Admin 进行贡献,没错,正是像你这样的人打造了 Active Admin 这么精良的工具。

来自 Active Admin 贡献者文档

更多优秀的项目介绍说明,请参考 [参考文档] 中的[1]和[2]

告诉人们为什么应该读向导
了解向导的内容,有助于你和开发者的沟通,可以有效节省该开源项目的开发者管理和开发的宝贵时间。作为回报,他们会在回复你的issue、评估变更、以及完成你的 Pull Request 给予同样的尊重。

内容来自 Hoodie 贡献者文档

解释你期望的贡献类型

保持开放的头脑!改进文档、bug 筛选、以及为任何有用处的贡献撰写教程,都会大大的减轻维护者的工作量。

ElasticSearch 是一款开源项目,而且我们非常热心的希望收到来自共同体的——你——的贡献!有很多种路径实现贡献:撰写教程、撰写博客、改进现有文档、提交bug报告、提交新功能需求、以及提交代码,均是为 Elasticsearch 自身内部合作的一部分。

内容来自 Elasticsearch 贡献者文档,更多优秀的解释贡献类型说明,请参考 [参考文档] 中的 [3][4]

解释你不想看到的贡献类型(如果有的话)

再重复一遍,做这些工作可以大大的减轻维护者的工作量。如果有人忽略掉你的向导指南,并提交了一些你最不想看到的内容,那么这个时候你就可以正当的关闭它,并告诉ta你的规程。

请不要使用 issue 跟踪来获得问题支持。请到 Freenode 上的 IRC 频道找 #pocoo 来进一步获得支持。如果你的问题不是直接和 Werkzeug 或 Flask 相关,#python 频道是非常活跃的有可能帮到你的,另外 Stack Overflow 也非常值得考虑。

内容来自: flask 贡献者文档,更多优秀说明,请参考 [5][6]

5.5.2. 基本规则

设定期望的行为(你的和他们的)

此处的信息不仅包括如何和他人沟通(彼此尊重、考虑对方等),也要包括技术上的责任(测试的重要性、项目依赖等),如果有行为准则的话,提示并将链接地址释出。

责任:
  • 确保每次变更跨平台的兼容性都能被接受:Windows、Mac、Debian& Ubuntu Linux。

  • 确保进入核心的代码满足检查表中的所有要求: https://gist.github.com/audreyr/4feef90445b9680475f2

  • 任何主要的变更和改进都要创建issue,以透明的方式进行讨论,且要获得共同体的反馈。

  • 除非是绝对必要的情况下,否则不要为代码增加新的类,Err on the side of using functions.

  • 尽可能的保持特性版本最小化,理想的情况是一个版本只有一个特性。

  • 对新来这表示友好!鼓励多样性,任何背景的贡献者都是欢迎的。请参考 Python 共同体行为准则

内容来自: cookiecutter 贡献者文档,更多优秀说明,请参考 [7][8]

5.5.3. 针对初次贡献的说明

帮助刚刚接触到贵项目的新人,最佳之处就是了解他们哪里需要帮助。而这通常也是一个展示你项目是否适合新手的好时机。

例如 Atom 给出贡献者指南:

不确定如何开始为 Atom 做贡献?你可以先从那些标记为 beginner 或 help-wanted的issue入手: Beginner issues - 那些只需要几行代码就可以搞定,或者是做一到两个测试的 issues 。 Help wanted issues - 比 Beginner 更深度参与的 issues 。 上述 issue 列表,你可以将之按评论总数排序。虽然这么做有所缺陷,但是评论的数量可以合理地反映一个给定的变化将会产生的影响。

这就非常的清晰了,更多的优秀的关于针对首次贡献的说明,可参考:[1][9]

5.5.4. 为从来都没有为开源贡献过的人添加资源链接

这里有一些友好的教程或许有所帮助:

正在为你的第一个 Pull Request 做准备吗?你可以从这个系列文章中学习到: 在 GitHub 如何为开源项目做贡献

以上内容是 React 项目所提供的额外资源。简直是良心共同体。

5.5.5. 贡献者入门指南

给出如何提交贡献的快速路径

这部分的内容如何写取决于你自己,不过下面的内容最好是包含进来:

  • 告诉众人他们需要签署 CLA,同意 DCO,以及其它法律上的事情

  • 如果贡献需要测试,也让他们知道,并解释如何跑测试

  • 如果你使用了GitHub之外的issue管理工具(如JIRA、Trac),也请告诉他们如何去提交贡献

针对修改一两行内容之上的改动,应做到:
  1. 将代码fork到自己的账户

  2. 在自己的代码中进行修改

  3. 如果你认为修改很完善,且项目应该接受的话,要做到:

    • 确保代码风格是和项目一致的。

    • 和 jQuery 基金会签署了贡献者许可协议(CLA)

    • 知晓 jQuery 基金会的行为准则

    • 发送的 Pull Request 里包含 CLA 文件

以上是来自 requierjs 贡献者指南的良好实例,另外有心的读者还可参阅 [10][11][12]

如果您对小的或“明显的”修复有不同的流程,请让他们知道

关于此方面, chef 有着非常不错的描述

小的贡献(比如修正拼写错误),其内容小到不属于知识产权,可以由贡献者作为补丁提交,而不需要签署 CLA。

根据经验,如果更改没有引入任何新功能或创造性思维,那么更改就是明显的修复。只要更改不影响功能,一些可能的示例包括:

  • 拼写、语法错误修正

  • 单词更正、空格和格式的变更

  • 注释清理

  • 变更返回值或者静态存储了错误的代码的Bug修复

  • 增加日志信息或 debug 的输出

  • 改动‘元数据’文件,如 Gemfile、.gitignore、构建脚本等。

  • 从一个目录或包移动文件到另外的目录或包

另外也可参考 [13] 即Puppet 的做法。

5.5.6. 如何报告缺陷

说明披露安全问题是的首要法则

至少,包括以下句子:

如果你发现了安全漏洞,请不要新建 issue,请发送 Email 给 xxx。

如果你不想使用自己的个人联系信息,那么需要开通“security@”的邮箱地址。更大一点的项目需要更多正式的流程来处理安全披露,如加密通信等。

任何事关安全的 issue 请直接提交到 security@travis-ci.org

为了确定自己是否在处理安全问题,请问自己以下两个问题:

  • 我可以访问不是我自己的内容吗?或者说我应该访问吗?

  • 我可以将其他人禁止使用吗?

如果以上两个问题的任何一个问题的答案是”是“的话,那么就可以认为这是一个安全问题。

提示:即使以上两个问题回答均为”否“,也不代表你处理的不是安全问题,实在确定不了的话,还请直接发送问题给security@travis-ci.org

Travis-CI 给了我们一个非常好的例子,另外 [14][15] 也不错。

告诉你的贡献者如何撰写bug 报告

你可以准备好一些模板,这样人们就可以复制-粘贴(呵呵,再次节省你的工作)。Go 语言给了我们非常不错的范例:

当提交一个issue,请确保回答了以下这五个问题:

  1. 你使用的是Go的哪个版本(go verison)?

  2. 使用的是什么处理器架构以及操作系统?

  3. 你做了什么?

  4. 你原本期望是什么?

  5. 实际运行的结果?

一般的问题请到 golang-nuts 邮件列表中,而不是在此issue跟踪,在那里 gopher 们会很好的回答你的问题。

更多bug报告经常的描述,可参考 [14][16]

5.5.7. 如何为新的功能和改进提建议

如果有特定的 roadmap、目标、原则、开发方式等,分享到这里

这些信息可以帮助到贡献者了解上下文,进而避免他们提出不符合项目需求的建议。(节省彼此的时间)

Express 的哲学思想是为 HTTP 服务提供小巧的、稳定的工具集,为单个页面应用、web站点、混合、或者是公开的 HTTP API提供伟大的解决方案。

Express 不会强制你使用任何特定的ORM 或模板引擎,通过Consolidate.js ,Express 提供了超过14中模板引擎,你可以快速的构建自己的完美框架。

Express.js 这份原则声明就为我们提供了非常好的例子,[10] 做的也非常不错,供参考。

解释建议某个特性所需的过程

如果是前后来回需要确认的话,那么这个解释就很必要了。询问他们功能的范围,仔细思考为什么这个功能是必须的,以及其将如何工作。

如果你发现了Elasticsearch没有你意想中的功能,你并不是第一位,也不是最后一位,请相信自己,一定会有其他有类似需求的人。Elasticsearch 有很多功能都是因为用户的需要而增加的,请在GitHub上新建一个issue,描述清楚你需要的功能,以及为何需要它,最好也描述一下它应该如何工作。

来自 Elasticsearch 的实例。更多精彩请参考 [17][18]

5.5.8. 代码核对(review)流程

解释代码提交之后如何能够被接受的全过程

谁来核对?在被接受之前需要谁的签名?贡献者希望在什么时候收到你的消息?贡献者如何获得提交访问(如果有的话)?

我们的核心团队会在每周的分类会议上查看 Pull Requests,会议是使用公开的Google Hangout进行。每周状态更新会发送到 puppet-dev 邮件列表。所有的注意事项都会记录到 Puppet 共同体 community-triage仓库,Hangout 同时也会上传到YouTube上。

在收到反馈后,我们期望在两周内得到答复。两周后,如果没有显示任何活动,我们可能会关闭 pull request。

Puppet 为我们提供了非常好的范例。另外也可参考 [15][19]

5.5.9. 共同体(community)

如果你的项目除了 GitHub 之外还有其它的通道的话,一并在这里列出。还可以作者、维护者、亦或是贡献者都可以写上,或者是说明一下响应时间的期望。

你可以来 https://gitter.im/cucumber/cucumber 和我们的核心团队接触,我们会在周五提供专门的时间。

cucumber-ruby 就是最好的例子。另外也可参考 [20][21]

可选:代码、commit 约定、以及标签约定

以下这些内容并非必须项,但是对于简化贡献的流程等内容会有所帮助的。

如果项目的 issue 采用了标签约定的话,请解释一番

可参考:[26] [27]

[参考文档]

[1]. Read The Docs 贡献者文档

[2]. Mustache.js 贡献者文档

[3]. Devise 贡献者文档

[4]. Geocoder 贡献者文档

[5]. cucumber-ruby 贡献者文档

[6]. Read the Docs 贡献者文档

[7]. Celery 贡献者文档

[8]. geocoder 贡献者文档

[9]. Djongo 贡献者文档的向导部分

[10]. Active Admin 贡献者文档

[11]. node.js 贡献者文档

[12]. Ember.js 贡献者文档

[13]. Puppet 贡献者文档

[14]. Celery 贡献者文档

[15]. Express.js 贡献者文档

[16]. Atom 贡献者文档中关于报告 Bug 的部分

[17]. Hoodie 贡献者文档

[18]. Ember.js 贡献者文档提交功能需求

[19]. Meteor 代码review

[20]. chef 开源共同体

[21]. cookiecutter 开源共同体说明

[22]. requirejs 代码风格指南

[23]. elasticsearch 代码风格指南

[24]. Angular 的提交Commit注意事项

[25]. Node.js 的提交Commit注意事项

[26]. StandardIssueLabels 标签约定

[27]. Atom 标签约定做的非常不错。

5.5.10. 已知问题

Write your Readme first.

— Tom Preston-Werner,自述文件驱动的开发

6. 知识产权与合规

6.2. 开源License的选择

License是软件的授权许可,里面详尽表述了你获得代码后拥有的权利,可以对别人的作品进行何种操作,何种操作又是被禁止的。软件协议可分为开源和商业两类,对于商业协议,或者叫法律声明、许可协议,每个软件会有自己的一套行文,由软件作者或专门律师撰写,对于大多数人来说不必自己花时间和精力去写繁长的许可协议,选择一份广为流传的开源协议就是个不错的选择。

世界上开源软件协议OPEN SOURCE LICENSE的种类非常之多,并且同一款协议有很多变种,协议太宽松会导致作者丧失对作品的很多权利,太严格又不便于使用者使用及作品的传播,所以开源作者要考虑自己对作品想保留哪些权利,放开哪些限制。

6.2.1. 主流开源协议

1、 GPL

GPL,是GNU General Public License的缩写,为GNU通用公共授权非正式的中文翻译。我们很熟悉的Linux就是采用了GPL,GPL协议和BSD, Apache License等鼓励代码重用的许可很不一样,GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商业软件公司开发的免费软件了。

  • GPL1即最初的版本,发布于1989年一月,其目的是防止那些阻碍自由软件的行为,而这些阻碍软件开源的行为主要有两种(一种是软件发布者只发布可执行的二进制代码而不发布具体源代码,一种是软件发布者在软件许可加入限制性条款)。因此按照GPLv1,如果发布了可执行的二进制代码,就必须同时发布可读的源代码,并且在发布任何基于GPL许可的软件时,不能添加任何限制性的条款。

  • GPL2在1991年6月发布,与此同时第二个许可证程序库GNU通用公共许可证(LGPL,the Lesser General Public License)也被发布出来并且一开始就将其版本定为第2版本以表示其和GPLv2的互补性。这个版本一直延续到1999年,并分支出一个派生的LGPL版本号为2.1,并将其重命名为轻量级通用公共许可证(又称宽通用公共许可证)(Lesser General Public License)以反映其在整个GNU哲学中的位置。

  • GPL3正由斯托曼起草,由伊本·莫格林和软件自由法律中心(Software Freedom Law Center) 提供法律咨询。斯托曼在2006年2月25日自由及开源软件开发者欧洲会议的演讲上说在所有的改动中,最重要的四个是:解决软件专利问题;与其他许可证的兼容性;源代码分区和组成的定义;解决数位版权管理(DRM)问题。

GPL协议的主要内容是只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用GPL协议,即必须也是开源和免费,这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势,由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

2、 BSD

BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。但”为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

  • 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。

  • 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。

  • 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

3、 MIT

MIT许可证之名源自麻省理工学院(Massachusetts Institute of Technology, MIT),又称“X条款”(X License)或“X11条款”(X11 License),是一份简短而宽松的协议,只提供了版权保护和声明,它授予他人复制,修改,合并,发布,分发,授权和/或销售本软件的副本的权力,被授权人可根据程序的需要修改授权条款为适当的内容。作者只想保留版权,而无任何其他了限制,也就是说必须在发行版里包含原许可协议的声明,无论以二进制发布的还是以源代码发布。

4、 MPL

MPL是The Mozilla Public License的简写,是1998年初Netscape的 Mozilla小组为其开源软件项目设计的软件许可证。MPL许可证出现的最重要原因就是,Netscape公司认为GPL许可证没有很好地平衡开发者对源代码的需求和他们利用源代码获得的利益,同著名的GPL许可证和BSD许可证相比,MPL在许多权利与义务的约定方面与它们相同。(因为都是符合OSIA认定的开源软件许可证)。但是,相比而言MPL还有以下几个显著的不同之处:

  • MPL虽然要求对于经MPL许可证发布的源代码的修改也要以MPL许可证的方式再许可出来,以保证其他人可以在MPL的条款下共享源代码。但是,在MPL许可证中对“发布”的定义是“以源代码方式发布的文件”,这就意味着MPL允许一个企业在自己已有的源代码库上加一个接口,除了接口程序的源代码以MPL许可证的形式对外许可外,源代码库中的源代码就可以不用MPL许可证的方式强制对外许可。这些,就为借鉴别人的源代码用做自己商业软件开发的行为留了一个豁口。

  • MPL许可证第三条第7款中允许被许可人将经过MPL许可证获得的源代码同自己其他类型的代码混合得到自己的软件程序。

  • 对软件专利的态度,MPL许可证不像GPL许可证那样明确表示反对软件专利,但是却明确要求源代码的提供者不能提供已经受专利保护的源代码(除非他本人是专利权人,并书面向公众免费许可这些源代码),也不能在将这些源代码以开放源代码许可证形式许可后再去申请与这些源代码有关的专利。

  • 对源代码的定义。在MPL(1.1版本)许可证中,对源代码的定义是:“源代码指的是对作品进行修改最优先择取的形式,它包括:所有模块的所有源程序,加上有关的接口的定义,加上控制可执行作品的安装和编译的‘原本’(原文为‘Script’),或者不是与初始源代码显著不同的源代码就是被源代码贡献者选择的从公共领域可以得到的程序代码。”

MPL许可证第3条有专门的一款是关于对源代码修改进行描述的规定,就是要求所有再发布者都得有一个专门的文件就对源代码程序修改的时间和修改的方式有描述。

5、 Apache License 2.0

Apache License是著名的非盈利开源组织Apache采用的协议,该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:

  • 需要给代码的用户一份Apache License。

  • 如果你修改了代码,需要再被修改的文件中说明。在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。

  • 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache License。你可以在Notice中增加自己的许可,但不可以表现为对Apache License构成更改。

Apache License也是对商业应用友好的许可,使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

6、 LGPL

LGPL(亦称GPL V2)是GPL的一个为主要为类库使用设计的开源协议,和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL 允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。

但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品。

7. 项目命名与商标

基础设施

开源项目的需要基础设施的帮助。

8. 邮件列表

  • 为什么开源社区使用邮件列表进行交流

在Apache社区有一个不成文的规矩:“没有在邮件列表里面发生的事情就没有发生”。邮件列表已经成为开源社区比较流行的沟通习惯了, 以笔者的日常工作为例, 使用邮件列表来进行沟通?

由于社区的成员遍布世界各地,时差是大家在沟通的过程中需要解决的一个很重要的问题。在Apache社区大部分的开发人员都居住在欧美地区,如果要大家一起坐下来开会,基本选的时间都是在东半球的开发人员睡觉的时候。例如每年举办的Apache软件基金会成员大会基本上就选在了北京时间凌晨三点左右召开。 通过邮件列表这样异步的方式可以比较好的解决时区问题,因为邮件是异步的,发件者不需要等待接收者上线就可以发送邮件,而接收者可以选择他比较方便的时间回复邮件。

当然使用邮件列表还有一个好处就是,邮件存档检索都比较方便,这样可以让关心邮件主题的朋友随时跳进来参与讨论。 我经常可以看到在Camel的用户组里有人会就几个月以前讨论的问题接着发信寻找更好的解决方案。社区成员可以通过搜索公开的存档邮件及时获取到相关的问题的讨论上下文,通过邮件列表可以极大降低社区成员获取信息的成本,让知识能够沉淀下来,这对于人员流动性比较大的开源社区来说是非常重要的。

说了这么多使用邮件列表沟通的好处,那为什么国人很少用邮件列表问问题呢?简单分析一下,可能会涉及几方面的问题。

第一是语言问题,因为在Apache社区,大家都是用英语来进行沟通, 对于大多数的开发人员来说,他们想比较快的解决问题,往往会先选择使用Baidu搜索相关的中文解决方案,而很少尝试去邮件列表里面去用英文来问问题。对于大部分和用户使用相关的问题,使用中文来检索应该能找到相关的解决方案。但是如果我们想深入研讨软件内部的细节问题的时候,使用英文往往能获取到第一手的信息。

第二可能是大家觉得邮件会比较慢, 如果邮件的讨论方正好分布在东西两个半球,一次有效的来回讨论可能就会占据一天的时间。也许正因为这种慢可以让我们在写邮件的时候可以好好考虑一下上下文的逻辑关系,以及相关讨论人的认知以及感受等问题,让大家的讨论能够比较通畅的进行下去。

现在国内的开源社区发展地也非常迅猛,大家大多会选择QQ群或者微信群等这样的及时通讯群来进行交流。这样的交流的好处是大家可以随时随地进行沟通,由于大家在这样及时通讯工具里的沟通没有相关的存档检索功能,大家的讨论很难沉淀成为能被后续加入的成员所使用的有效信息。这样表面的繁荣很难提供开源社区需要的持续发展动力。

最近在Apache孵化项目社区中就有这样有关项目建立中文QQ群的讨论,有兴趣的同学可以通过 邮件列表存档获取相关的内容。 当然由于这个主题涉及到多方面的内容,大家讨论的方向会比较多: 有讨论Apache是不是应该鼓励多语言讨论的,有讨论是不是邮件列表讨论是必须的。 就从方便让大家围观,及时全面了解问题的上下文的角度来说,大家应该能够体会到邮件列表的强大威力了。

  • 邮件交流的礼仪

在国内大部分开源社区的交流可能会发生在微信或者QQ群,或者是其他的论坛。为了积攒人气,有些人可能喜欢刷屏,或者灌水。但这样灌水的情况在邮件列表里面却很少发生,难道大家不喜欢凑热闹吗?

开源社区的交流是建立在志愿服务的基础上的,参与讨论的人没有任何义务要回复你的问题,大家投入时间参与讨论,是建立在一个共赢的基础上的。只要讨论的问题是大家关心的问题,大家觉得这样的讨论是有价值的,自然就会有人参与进来。试想一下,如果你通过灌水,刷屏来寻找存在感,这样的行为会让人觉得你是在浪费大家的时间,你不尊重这个讨论问题的环境,长此次下来就没有多少人愿意回答你的问题。

在开源社区中,你的名声不是靠你职位来获得,而是靠你在社区里面赢得的影响力。影响力的大小和你在社区中贡献大小有很直接的关系。如果你长期在邮件列表里面高质量地回复问题,那你在邮件列表里说话的分量就很重,你在社区的影响力就很大。正是这个原则让我们在寻找社区帮助的时候看到了很多热心的帮助者,他们不计回报地帮助你解决棘手的问题,帮助你成长。对于这样的帮助我们应该心存感激,而不是想当然的认为他们必须要帮助我。

开源社区的交流是公开的,存档的。任何人可以通过搜索引擎或者其他检索工具检索到绝大部分的交流内容来。这就意味这我们发的邮件或者是提交的评论会被很多人看到(可能是成百上千),而且我们写的内容会在很长时间内帮助其他人很快速了解事情的来龙去脉。为了提高交流的效率,在我们在问问题之前,应当检索一下是否有类似的讨论。如果有类似的讨论,我们可以选择在之前的邮件上进行回复;如果没有类似的讨论,我们可以发起一个新的邮件讨论,言简意赅地表述与主题相关的内容。

为了能让我们的问题讨论能让更多的人受益,我们应该选择用公开的邮件列表来讨论问题,而不是单独私信他人。也许你认为自己问的问题比较初级,担心在公开的邮件列表里面问这样的问题会显得自己比较业余。其实这样的担心是多余的,开源社区不会因为你问的问题简单就嘲笑你。如果你问问题之前使用搜索引擎做过一些功课之后,还是没有找到答案的话,那你的问题含金量就比较高了。如果你能问出这样有技术含量的问题的话,我相信社区大牛会很乐意回复你的问题的,很多时候开源社区的大牛要证明自己牛是需要靠这样的问题衬托出来的。

接下来和大家聊一下为什么在开源社区我们要站在中立的角度上去讨论问题。

开源社区的交流就好像是我们在一个大厅里说话一样,我们所有交谈的内容大家都能听见,而且有可能会被大家反复播放。如果这个时候我们在吵架,很有可能吸引很多的围观者。在吵架的过程中,我们可能会说出一些让我们后悔说出的话。在平日里这些话可能不会那么刺耳,因为大家可能会很快忘却。但是如果在开源社区,这样伤人的话会作为永久的记录保存下来,而且会被大家随时检索出来。为了让我们的描述足够客观,避免被别人错误理解, 我们也需要注意表达的语气。如果我们在写信的时候,情绪比较激动话,可以选择把过半天或者一天之后在自己情绪不那么激动的时候写信。如果我们在邮件列表里面看到相关的攻击,不要选择加入类似的攻击,而是站在一个比较客观的中立角度来阐述问题。

  • 依托的服务

9. 版本控制系统

9.1. 版本控制系统简介

git 的官方的书籍中如此定义版本控制:版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。

我们的每一个人都需要版本控制,无论你做什么,如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。 使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。 但额外增加的工作量却微乎其微。

假设有这么一位喜欢厨艺的爱好者,最近喜欢上的烤面包,光是看说明书总是会出错,也是将各种因素来回的搭配,并记录,并随时进行重新的编排和组合。

有人说版本控制系统是根据人类的记忆来发明的,因为只有人类才有记忆,并形成经验、知识,正如Eric Sink在其著作《实例讲解版本控制》所说,版本控制系统的三大功用:

  1. 让我们相互之间的协作并行起来,而不是串行——某个时间只能有一个人在工作。

  2. 在协作的过程中,最好是能够各得其所,尽量避免冲突,实在无奈,能够方便的解决冲突。

  3. 我们能够将所做过的所有事情都归档,并可恢复,谁在什么时间做了什么,以及为什么这么做。

9.2. 为什么会有差异?

在软件开发过程中,大多涉及到多人开发和协作,同一份文件,在不同的开发者的工作台会出现差别,即使是单独的个人,在不同的时间,也会产生不同的版本,日积月累,差异、改进、删除等等都会发生,换句话说:为了应对这种变化,或者是记录变化本身,我们需要记录差异。

记录差异在人类的发展史上有着非常悠久的良好传统,可以说,差异产生知识,因为可以比较不同,在能够知道变化,在面临熵增的世界,寻找有序。

差异,是以时空为根本前提的,不同的空间在相同的时间可以对比,同一空间在不同时间也可以进行对比。以代码开发为例,在多人参与的情况下,错综复杂,二者都是可以发生的。

在理解了差异之后,我们就可以说明版本控制的意义了:

  • 用于记录和跟踪差异,以便于协作、合并、回退、整合源代码文件。

9.3. diff 和 patch

we have been able to connect the three different development stages of Linux development: pre-version control, BitKeeper, and Git. During the pre-version control stage, we use each of the releases of Linux as a snapshot of its development. ---- 2020 Linux Kernel History Report

diff 是在 UNIX 系统上的一个工具程序,它可以比较两个文件之间的不同。通常它被用来比较同一个文件,在不同版本间的差异。它可以产生一个扩展名为.diff或.patch的文件,这个文件可以被另一个工具程序 patch 来使用。

下面我们就以一个实例说明一下这两个程序的使用,这其实是最好的解释和说明。

现在我们有一个 hello.c 的C 语言经典入门的程序:

---
#include <stdio.h>
int main(void) {
    printf("Hello World\n");
    return 0;
}
---

按照如下步骤,使用 diffpatch 来了解源代码版本的差异:

1、 为 hello.c 复制一个副本

---
$ cp cello.c cello.c.orig
---

2、 修改 hello.c 文件为:

---
#include <stdio.h>
int main(void) {
    printf("Hello World from my very first patch!\n");
    return 0;
}
---

3、 使用 diff 来生成差异的文本,

% diff -Naur hello.c.orig hello.c
--- hello.c.orig        2020-09-14 13:34:20.000000000 +0800
+++ hello.c        2020-09-14 13:34:50.000000000 +0800
@@ -1,6 +1,6 @@
 #include <stdio.h>
 int main(void) {
-    printf("Hello World\n");
+    printf("Hello World from my very first patch!\n");
     return 0;
 }
---

4、 重定向到文本文件,并以后缀 .patch 为命名:

---
% diff -Naur hello.c.orig hello.c > hello-first-patch.patch
lee@lees-MacBook-Pro code % cat hello-first-patch.patch
--- hello.c.orig        2020-09-14 13:34:20.000000000 +0800
+++ hello.c        2020-09-14 13:34:50.000000000 +0800
@@ -1,6 +1,6 @@
#include <stdio.h>
int main(void) {
-    printf("Hello World\n");
+    printf("Hello World from my very first patch!\n");
    return 0;
}
---

5、 生成 patch 之后,我们就可以换一台机器,可以预想的场景就是,已经将 hello.c 分享给来其他人,现在也将这个patch发送给对方,让对方能够生成新的文件,以和我们保持一致。

---
$ cp cello.c.orig cello.c
---

6、 使用程序 patch 将差异修改到源文件。

---
% patch < hello-first-patch.patch
patching file hello.c
lee@lees-MacBook-Pro code % cat hello.c
#include <stdio.h>
int main(void) {
    printf("Hello World from my very first patch!\n");
    return 0;
}
---

7、 编译、执行即可

---
% gcc -g -o hello hello.c
% ./hello
Hello World from my very first patch!
---

这就是差异比较,然后合并的最基础的、最本质的原理所在,现代化的版本控制系统如Git、SVN 等都自带这两个程序,我们后续会进一步的给大家做介绍。

9.5. Git 之前的版本控制系统

9.5.1. RCS

RCS 是由普渡大学的 Walter F. Tichy 教授在1982年所开发。主要语言采用的是C语言。

RCS对文件进行集中式管理,主要目的是避免多人合作情况下可能出现的冲突。如果多用户同时写入同一个文件,其写入结果可能相互混合和覆盖,从而造成结果的混乱。你可以将文件交给RCS管理。RCS允许多个用户同时读取文件,但只允许一个用户锁定(locking)并写入文件 (类似于多线程的mutex)。这样,当一个程序员登出(check-out,见RCS的co命令)某个文件并对文件进行修改的时候。只有在这个程序完成修改,并登入(check-in,见RCS的ci命令)文件时,其他程序员才能登出文件。基本上RCS用户所需要的,就是co和ci两个命令。在co和ci之间,用户可以对原文件进行许多改变(change, or file delta)。一旦重新登入文件,这些改变将保存到RCS系统中。通过check-in将改变永久化的过程叫做提交(commit)。

9.5.2. 古老的 CVS

要弄明白为什么 Git 的分布式特性是对以前的版本控制系统的极大改善的话,除了折腾 CVS 外,没有更好的办法。 — Two-bit History

接下来我们引用《CVS精髓》一书当中对于CVS 的解释:

CVS 是一种版本跟踪系统,它可以在软件开发过程中保持文件的各种记录以及取出文件的任何已被存储的版本,制作出各种版本的软件。CVS 可以让多名开发人员同时编辑单一文件而不会遗失任何数据。每名开发人员各自编辑自己所拥有的该文件的副本,最后所有的修改会合并到单一的主“副本”中。CVS 所提供的功能可以协助项目经理跟踪项目随时间而变的轨迹。

9.5.3. 拥有完整权限控制的 SVN

SVN 真正的项目名称叫做: Subversion,目前是 Apache 软件基金会下的顶级项目,在分布式系统Git流行之前,SVN 是开源当中最佳的选择。至于其为什么被业内人士经常简称为svn,大约是命令行为svn 的缘故吧,我们在下文或本书中也会多次提到SVN, 它没有特别申明的情况下就是指 Subversion。

SVN 由 CollabNet 公司于2000年资助并开发,目标就是创建一个更好用的版本控制系统以取代CVS,

9.5.4. 参考资料

  1. 《CVS精髓》,Jennifer Vesperman 著,东南大学出版社,ISBN: 9787564102555,出版年: 2006-4

9.6. Git

the stupid content tracker git 的宣传语

9.7. Git 的“八卦”

在Youtube上有一个视频,是Linux 创始人 linus 在为Google的一次内部分享会上讲解Git,其中有一句话的表达特别让人印象深刻:I Hate CVS, 这也是我们在这章开头引用Linux29周年的报告的一句话,在2002年之前,Linus 都是使用patch这个程序来维护所有 Linux的开发代码的。

但是Linux 不是linus一个人的事情,在2002年,Linus在众多人的压力之下,选择了一个商业的版本控制系统,也就是我们在Kernel的历史上有三年是BitKeeper的原因所在。这也充分说明了Linus是有多么的痛恨集中式的版本控制系统,宁愿选择工具本身闭源也不要选择CVS、SVN 等。所谓的分布式版本控制系统,就是没有集中式的中心版本库,每个人都工作在通过clone建立的本地版本库中。也就是说每个人都拥有一个完整的版本库,查看提交日志、commit、打tag、branch等均在本地完成,而毋需通过中央网络连接和请求。这样的话,每位在其本地的库都是 完全属于自己的,再也不需要获得谁的许可才能操作。正是这样一个变化,再加上更友好的协作模式(版本库之间的pull、merge、cherrypick),从而让开源项目的参与有了前所未有的方便,也预示了更多的可能性。

2005年,发生了一件颇有戏剧性的事件,反编译微软Windows 网络文件系统的Samba项目的作者 Andrew Tridgell 不知道因为什么将目光瞄准了 BitKeeper,欲将其进行逆向工程,进而像Samba那样访问windows 文件一样,开发一个能与BitKeeper交互的开源工具。但是 这种情况是 BitMover,即BitKeeper所有者的商业公司不想看到的局面。他们要求收回为Linux kernel提供免费使用的授权。迫不得已、万般无奈之下,因为不想付费,再说了价钱也确实太高了点,Linus决定自己动手写一个分布式的版本控制系统,

这个项目和历史上很多卓越的项目一样,充满了智慧与神奇:

  • 2005.4.3 Linus 开始开发Git

  • 2005.4.6 项目发布

  • 2005.4.7 Git 作为自身的版本控制工具

  • 2005.4.18 多分支合并功能实现

  • 2005.4.29 性能实现预期

  • 2005.6.16 Linux 2.6.12 全面采用Git

  • 2005.7.26 Linus 将Git 的开发和维护工作交接给Junio C Hamano

嗯,你看的没错,三个多月的时间,成就了这个世界上目前来说最伟大的合作协同工具。

9.8. Git 的常见使用

如果你不是专业的代码仓库维护者的话,或许像笔者这样,通常执行如下操作即可:

---
$ git config --global user.email lijiansheng@ocselected.org user.name lijiansheng
$ git clone https://github.com/WillemJiang/open-source-manual/
change or add some files.
$ git add
$ git commit -s -m 'add new file.'
$ git push origin draft
---

Git is “expressly designed to make you feel less intelligent than you thought you were.”  — Andrew Morton

10. 代码仓库

11. 项目资料

11.1. 创建网站

项目本身是需要向世人展示的,在互联网如此发达的今天,如果一个开源项目没有相应的可以使用搜索引擎搜得到的站点,那么很可能潜在的用户和开发者都找不到你的项目。鉴于目前代码协作平台如GitHub等强大的功能,我们特别说明建立网站通常有三种方式:

一、 GitHub Page

二、 自行搭建

三、 第三方托管

  • 网站工具

一、SEO (搜索引擎优化)

  • 编写用户手册

要为你的项目最终的输出物:软件,编写用户使用手册。

12. 持续集成系统

12.3. Travis,Github Actions 在线服务

随着web的发展,越来越多的服务可以通过友好的API来进行实现,相比于 Jenkins 部署本地的服务,对于很多项目其实是没有必要的,‘随需随用’、毋需维护基础设施成本、和GitHub等开放式开发平台无缝集成,为什么要拒绝了呢?下面我们就以两个实例为说明持续集成的在线服务。

13. 问题追踪系统

14. 现代开源项目开发集大成者 GitHub 平台介绍

14.1. Git 与 GitHub

我们在版本控制系统一节中详细介绍了Git ,那么基于 git 之上再做些事情,是所有想为开发者做事情的出发点。让我们将时间再往回拨一拨,拨回到围绕 Git 之前的版本控制系统所做的服务 或产品。

14.1.1. SourceForge

说起古老的代码托管站点,我们是无法绕过SourceForge的,该站点于1999年由VA 软件公司投资开发,在整个2000~2010年都是开源开发者和用户的主要站点,也诞生了很多知名的开源项目:

  • JBoss

  • PhpMyAdmin

  • FileZilla

支持 CVS、SVN 等中心化的版本控制系统,SourceForge 还有一个重要的特点,就是支持二进制分发,且嵌入广告。这可能为它后来的衰败有很大的关系。

14.1.2. Google code

Google 在2009年推出了开源项目托管平台: Google Code,支持的版本控制系统包括 git SubversionMercurial,还有问题跟踪系统、Wiki用于 记录文档。

已经于2016年1月永久归档:https://code.google.com/archive/

14.1.4. GitHub

终于轮到介绍GitHub了,GitHub 服务是由四名 Ruby On Rails 开发者: Chris Wanstrath、P. J. Hyett、Tom Preston-Werner 以及 Scott Chacon 共同开发,在2008年二月开始撰写, 同年4月10号发布上线,首次较大规模发布是在2009年的2月24日,地点选择是在Yahoo!的总部。

14.2. GitHub 上手指南

首先你需要访问域名为: http://www.github.com 的网站,然后根据指示注册,需要输入可用的邮箱、登陆密码等信息,注册完成后,就可以登录了。

登录之后,你可以随意的逛逛,或者完善自己的个人资料:酷酷的头像、自己的状态、社交账号、邮箱等。

在GitHub 有两件事非常的重要:

  1. 通过熟悉的开发者,找到更酷的项目,然后分享代码

  2. 通过协作的项目,找到优秀的开发者,建立联系

如果你只是将GitHub 当作一个文件打包或者是存放文件的服务器的话,那么建议还是找当地的网盘服务,是对GitHub最为错误的认识。

总结起来,就是要适应起来开源代码的动态性、流动性,fork到自己的仓库的那部分代码,如果没有进一步的探索其实是没有任何意义的。当然,这也是GitHub最为吸引人的地方。

14.4. GitHub 公司、GitHub 平台闭源与商业伦理

GitHub 是一家商业公司,在美国注册,总部位于加利福尼亚州的旧金山。在世界的其它地区,在日本也有相应的办公室,如印度也设立有分部,本来中国是增长非常之大的,首席运营官还在2019年专门来中国低调的进行了实地考察[4],但是终究还是没有来。在2018年,GitHub 公司被微软以高达75亿美金 收购,在2020年三月,GitHub 收购了JavaScript的包管理 npm 公司。

GitHub 本身平台所使用的技术,绝大多数是闭源的,GitHub之外可以看到的仓库:https://github.com/github ,这些开源的部分,要么是fork其它开源项目,要么就是规模较小的“toy”型的。作为以网站的形式提供服务的站点,GitHub 绝大多数代码是没有以开放源代码的形式发布。

是的,这看起来有点矛盾,甚至在某种程度上有点讽刺:”在互联网的世界拥有最多开源项目集散地的平台本身是闭源的。” 但是仔细想想,这也不是历史上的组合,我们不妨回顾一下历史上那些开源和闭源共同进步的组合:

  • Kernel 在Git 发明之前,使用过的版本控制系统是商业的 BitKeeper。

  • Apache 软件基金会旗下的开源项目,使用的bug 跟踪系统是由 atlassian 公司提供的 Jira 系统。

  • 更早些时候,GNU 下的项目如Emacs、GCC 均是运行在商业的Unix系统之上的。

在如今的技术栈组合,闭源和开源相互融合,目前主流的技术云计算服务提供商采用闭源的方式提供服务,然而,运行其上的技术栈开源组合占据很大一部分,据Azure、Amazon、Google cloud等统计,Linux 占据期75%以上。对于用户来讲,可能更加关注的是当下要完成的任务,而对于整个技术 栈是否必须是开源,考虑的不是最重要的。

当然,有一些开发者就特别的在乎,在《working in public:The Making and Maintenance of Open Source Software 》一书中提及Unicorn 项目的维护者 Eirc Wang 对与平台的敏感:[5]

No. Never. Github is [sic] proprietary communications tool which requires users to accept a terms of service and login. That gives power and influence to a single entity (and a for-profit organization at that). . . . The reason I contribute to Free Software is because I am against any sort of lock-in or proprietary features. It absolutely sickens me to encounter users who seem to be incapable of using git without a proprietary communications tool.

伴随着GitHub的壮大,也不时的出现一些伦理、政治等问题,如:

  • 禁止伊朗、北韩等国家的开发者访问私有仓库。

  • ICE 合同的争议

  • 遭受DDoS攻击等

甚至在中美贸易战升级,中国的工信部购买了商业的Gitee产品,据说是为了防止GitHub封禁中国的开发者访问的后备,这真是一个憋脚的理由。

GitHub 提供免费的服务,以优质的现代软件开发过程而赢得了众多开发者的青睐,截止笔者撰写此文,已经拥有注册用户4千万,Alex排名也一直在100以内,每天都有大量的开发者使用GitHub提供的Git仓库服务、自动构建Action服务、npm仓库、社交化的相互follow等等,让更多的代码工作者有了充分的时间去进行 创作,如果用web2.0的社交思路来理解Github,和 YouTube、Facebook、Twitter、Medium等站点是没有区别的,本质是简化了相应工作者的流程:喜剧短片、朋友状态、短文字。

GitHub 本身是否开源,这个是合理合法的,也不违反任何的伦理。作为开发者可以选择,也可以不选择,全在开发者自己。比如知名的自由软件基金会旗下的GNU项目,是绝对不会选择GitHub平台的,因为GitHub 是私有的、记录开发者隐私的。

开源质量

15. 自动持续构建系统

  • 搭建自动化构建的意义

在早期的软件开发过程中,”谁破坏了编译过程”是一个罪证,尽管这里透露的是关于团队协作的过程,在大规模协作平台GitHub发明之前,软件开源是一个痛苦而低效的过程,其中包含的一个环节就是 编译,随着软件工程的壮大,项目的规模扩大,构建成为了软件工程中至为关键的部分。

有了自动化构建,作为开发者可以随时验证自己的代码,而不必要等到合并之后,在实际的环境中进行验证。

  • 常见的构建工具

那些规模较大的软件项目,通常组织的非常有序,

  • maven/groovy

Maven 用一句话来描述的话,就是针对 java 项目的 make 程序,其对应的 makefilepom.xml 。或者这样描述:`Maven`是一个构建工具,一个项目管理工具,一个运行构建任务抽象容器。其实`Maven`能够做的要比这个描述还要多,如管理项目的生命周期。

我们以一个简单的实例来为大家展示一下 Maven,在一个崭新的目录下执行下面命令:

 $mvn archetype:generate -DgroupId=edu.encu.osbook -DartifactId=opensource -Dpackage=edu.encu.osbook -Dversion=1.0-SNAPSHOT -Dfilter=org.apache:maven
 [INFO] Scanning for projects...
 [INFO]
 [INFO] ------------------< org.apache.maven:standalone-pom >-------------------
 [INFO] Building Maven Stub Project (No POM) 1
 [INFO] --------------------------------[ pom ]---------------------------------
 [INFO]
 [INFO] >>> maven-archetype-plugin:3.1.1:generate (default-cli) > generate-sources @ standalone-pom >>>
 [INFO]
 [INFO] <<< maven-archetype-plugin:3.1.1:generate (default-cli) < generate-sources @ standalone-pom <<<
 [INFO]
 [INFO]
 [INFO] --- maven-archetype-plugin:3.1.1:generate (default-cli) @ standalone-pom ---
 [INFO] Generating project in Interactive mode
 Choose archetype:
 ....
13: remote -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)
 ....
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 13:
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
7: 1.3
8: 1.4
Choose a number: 8:
[INFO] Using property: groupId = edu.encu.osbook
[INFO] Using property: artifactId = opensource
[INFO] Using property: version = 1.0-SNAPSHOT
[INFO] Using property: package = edu.encuosbook
Confirm properties configuration:
groupId: edu.encu.osbook
artifactId: opensource
version: 1.0-SNAPSHOT
package: edu.encuosbook
 Y: :
注:archetype 有1400多种生成的模板,我们过滤掉了大部分。

archetype-quickstart 会帮助开发者生成对应的文件,有源代码、测试用例、 mavenpom.xml 等:

---
# tree opensource/
opensource/
├── pom.xml
└── src
         ├── main
         │   └── java
         │       └── edu
         │           └── encuosbook
         │               └── App.java
         └── test
                         └── java
                                         └── edu
                                                         └── encuosbook
                                                                         └── AppTest.java
 9 directories, 3 files
---

而生成的`App.java`,就是我们常见的`hello,world!`程序:

---
# cat opensource/src/main/java/edu/encuosbook/App.java
package edu.encuosbook;
/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}
---

这个时候就可以编译使用`maven`管理的程序了:

---
# cd opensource/
# mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< edu.encu.osbook:opensource >---------------------
[INFO] Building opensource 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ opensource ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /root/opensource/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ opensource ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /root/opensource/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ opensource ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /root/opensource/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ opensource ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /root/opensource/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ opensource ---
[INFO] Surefire report directory: /root/opensource/target/surefire-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running edu.encuosbook.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.045 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ opensource ---
[INFO] Building jar: /root/opensource/target/opensource-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ opensource ---
[INFO] Installing /root/opensource/target/opensource-1.0-SNAPSHOT.jar to /root/.m2/repository/edu/encu/osbook/opensource/1.0-SNAPSHOT/opensource-1.0-SNAPSHOT.jar
[INFO] Installing /root/opensource/pom.xml to /root/.m2/repository/edu/encu/osbook/opensource/1.0-SNAPSHOT/opensource-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.640 s
[INFO] Finished at: 2019-08-21T02:00:19Z
[INFO] ------------------------------------------------------------------------
---

我们可以看到`maven`对程序进行了测试,并打包为jar,并放到`target`目录下。

> 如果遇到错误,则输入`mvn install -X`,根据详细输出定位问题。

验证程序:

---
# java -cp target/opensource-1.0-SNAPSHOT.jar edu.encu.osbook.App
Hello World!
---

Maven 在企业级 Java 的世界起着举足轻重的作用,是事实上的构建、管理标准,Maven 背后的主要贡献者 Sonatype 公司,在安全、仓库管理、制品管理方面已经在商业方面印证了该软件的流行程度。伴随着 DevOps 的流行趋势,旗下平台 Nexus,即 Maven 的仓库管理,更是成为软件开发中必不可少的组件。

在Java的世界里,能读懂 pom.xml 文件,会让你事半功倍。反之,如果则会把团队带入一篇混沌状态。

  • make

在软件开发中,make 是一个工具程序,经由读取叫做“makefile”`的文件,自动化建构软件。它是一种转化文件形式的工具,转换的目标称为“target”;与此同时,它也检查文件的依赖关系,如果需要的话,它会调用一些外部软件来完成任务。它的依赖关系检查系统非常简单,主要根据依赖文件的修改时间进行判断。大多数情况下,它被用来编译源代码,生成结果代码,然后把结果代码连接起来生成可执行文件或者库文件。它使用叫做“makefile”`的文件来确定一个`target`文件的依赖关系,然后把生成这个`target`的相关命令传给`shell`去执行。

绝大多数的项目一般均会选择以`make`,即撰写`makefile`来定义整个工程,这也是为什么将之列为阅读源代码的首席工具的重要原因,`makefile`关系到了整个工程的编译规则。一个工程中的源文件不计其数,并且按类型、功能、模块分 别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译, 哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为`makefile`就像一个Shell脚本一样,其中也可以执行操作系统的命令。

make`是一个命令工具,是一个解释`makefile`中指令的命令工具,一般来说, 大多数的IDE都有这个命令,比如:Delphi的`make,Visual C++的`nmake`,Linux下GNU的`make`。

就像其他和make有着悠久历史的软件一样,make有着很多的拥护者和反对者。它的很多问题因现代大型的软件项目的出现而暴露出来。但是很多人争论说它在常见的情况下可以很好的工作,而且使用非常的简单,功能强大,表达清楚。无论如何,make仍然被用来编译很多完整的操作系统,而且现在替代品们在基本的操作上与它没有太大差别。

随着现代的集成开发环境(IDE)的诞生,特别是非Unix的平台上,很多程序员不再手动管理依靠关系检查,甚至不用去管哪些文件是这个项目的一部分,而是把这些任务交给了他们的开发环境去做。类似的,很多现代的编程语言有自己特别的高效的依赖关系的设置方法。

下面就以一个简单的 GNU make 为例说明make的好处。

  • GNU make

以下是撰写的一个简单的`Makefile`:

---
hello:
    gcc -g -o hello hello.c
clean:
      rm hello
      install:
      mkdir -p $(DESTDIR)/usr/bin
      install -m 0755 hello $(DESTDIR)/usr/bin/hello
---

将`Makefile`和`hello.c`放在同一个目录下,则有如下的输出:

$ make
gcc -g -o hello hello.c
$ ./hello
Hello,World!
$ make install
$ make clean
rm hello

GNU make 有着强大而复杂的功能,详情请参考其 官方文档,或者直接在任意安装有`make`的Linux发行版中执行`man make`。

  • npm

SouthEast

根据官方的申明解释,npm 是一个包管理器,它让 JavaScript 开发者分享、复用代码更加的方便。在程序开发中我们常常需要依赖别人提供的框架,写 JavaScript 也不例外。这些可以重复的框架代码被称作包(package)或者模块(module),一个包可以是一个文件夹里放着几个文件,同时有一个叫做 package.json 的文件。一个网站里通常有几十甚至上百个包,分散在各处,通常会将这些包按照各自的功能进行划分(类似我们安卓开发中的划分子模块),但是如果重复造一些轮子,不如上传到一个公共平台,让更多的人一起使用、参与这个特定功能的模块。

SouthEast

npm(全称 Node Package Manager,即“node包管理器”)默认是包含在`node.js`当中的,npm 完全用 JavaScript 写成,最初由艾萨克·施吕特(Isaac Z. Schlueter)开发。艾萨克表示自己意识到“模块管理很糟糕”的问题,并看到了 PHPPEARPerlCPAN 等软件的缺点,于是编写了 npm

npm 会随着 Node.js 自动安装。 npm 模块仓库提供了一个名为 “registry” 的查询服务,用户可通过本地的 npm 命令下载并安装指定模块。此外用户也可以通过 npm 把自己设计的模块分到 registry 上面。

16. 自动测试代码

  • 单元测试基础框架

  • 常见的单元测试方法

17. 功能测试代码

  • 验收测试基础框架介绍

  • 如何使用docker模拟多系统

18. 代码风格检查

  • 代码风格是什么

  • 常见的风格检查工具

19. 第三方依赖跟踪

  • 第三方依赖License检查的意义

  • 常见的第三方依赖检查工具有哪些

开源协作

20. 什么是开源共同体?

根据开源之道的定义如下:

为了实现一个开源软件项目,基于互联网,由企业、个人、非营利组织等形成的团体成员(接受过现代计算机科学的训练),在文化上能够达成一定共识,来去自由,进行一定的社会治理、活动、交流等,所形成的合作共同体。

既然为一个社会现象下了一个定义,那么我们就需要为之进行代入式的解释,那么具体的、典型的开源共同体有那些,笔者在这里给大家根据不同的类型进行概要的介绍,不过首先提醒大家的是,开源的共同体大大小小的,犹如现实生活中的生活社区,非常之多,错综复杂、纵横交错,

21. 开源共同体的角色构成

作为一个存在的社会团体,了解其内部的角色分类是必须要做的事情,否则就无法进一步了解和参与。组成社会团体的是每一个个体,这些个体恰是作为开源发起者特别需要争取的对象,但是对于某一类文化来说,比如奉行集体主义的东方文化里是极难发展个体的,必要的时候还是要将目光

21.1. 开源共同体中的作为个人的角色分类

21.1.1. 领袖

在人类的历史上,从来就不曾缺失过哪些一心致力于自身对于事物的驾驭的追求与能力,古希腊戏剧《普罗米修斯》或者是罗马的建筑大师维特鲁威,在开源共同体中,也不乏这样的人,我们这里不妨列举几位:

  • 林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds),Linux和Git创始人

  • Larry Well ,Perl 语言创始人

  • Tim O’Reilly , “open source” 一次的推动者,出版了数以千记的开源技术、文化相关的图书

  • Guido van Rossum Python 语言创始人

  • Brian Behlendorf Apache 基金会创始人之一,Apache web服务器主要发起者

  • Eric Raymond ,著名书籍《大教堂与集市》的作者,OSI 的发起者之一

  • Jim Zemlin Linux基金会执行董事

  • Henry Zhu Babel 项目维护者

  • …​…​.

更多开源共同体中的领袖或Hero们,请关注开源之道的系列文章:

21.1.2. 核心贡献者

每一款开源项目,除了发起者之外,都有核心的贡献者参与,或者提供设计、代码补丁、文档撰写,这是构成开源共同体的核心主力,换句话说:如果不能理解核心贡献者,那么就无法理解开源共同体。他们是主要的生产力!

想要了解项目的核心贡献者,分为两步:

  1. 到每个开源项目的发布版本日志里,找出贡献者名单。

  2. 下载源代码,使用版本控制系统,如git shortlog -c ,对应出名字来

  3. 根据2找到ta写的代码、注释、设计

  4. 只有理解了3,才能感同身受地体会ta解决问题的过程,以及为这个问题所花费的时间和精力。

21.1.3. 律师

在自由/开源软件发展的历史上,知识产权相关发挥了重要的作用,也就是说法律才是开源的支柱,在这个共同体当中,维护者开发者的权益,至少不被侵犯,从天才般的Richard Stallman 创立的GPL ,到各式各样的许可证,以及OpenChain、开放发明网络(OIN)等机构的诞生。

法外之地,开源将不复存在,因为这是人类的高等文明,需要克服人类基本之人性。律师帮助我们、一路同行,做到了这一点。他们是这个开源共同体中不可或缺的重要角色。

21.1.4. 拥护者和布道师

这个世界需要诉说者,著名作家伍尔夫写过“没有被叙述的就等于没有发生过”,开源想要联结成为强大的共同体,最终展现在世人面前“可见的”,是能够提供实用功能的运行在计算机当中的软件,不是每个人都具备上述探索核心贡献者,评估他们的工作成果的能力的。那么传播开源、宣扬开源价值的人就有了ta存在的意义。而随着开源在社会中的地位提升,做这些事的人也越来越紧俏。

关于布道的意义,在此我想没有比法国著名社会学者托克维尔在《论美国的民主》一书中所描述的更为精准的了:

一个社团要想有力量,就必须人多。而由于成员的人数太多,所以他们只能分散在广大的地区,每个人仍然要留在原来的地方,去过他们的哪种比上不足比下有余的生活,为成千上万的小事而操劳。因此,他们必须找到一个使他们不用见面就能彼此交谈不用开会就能得出一致意见的手段。这个手段就是报刊。

对比我们现在所处的互联网时代,报刊替换为媒体:社交平台、即使聊天、邮件列表等更为先进的媒介手段!

21.1.5. 用户

根据开源共同体的定义,这里的用户,我们要除却不懂计算机的其它行业的人士,在如今的信息社会,几乎没有人不是开源软件的使用者,我们如果把这个定义套用到他们身上的话,那简直是过于泛泛了,所以我们这里要区别出来:

知道自己在有意的使用开源软件,或自行编译开源项目的用户,最重要的是这些用户在选择软件的时候,会偏向使用开源软件,或者是因为经济、法律、喜好、社交等原因。无论是处于什么原因在使用开源软件的人,意识到自己在使用这种属性至关重要,这里主要是想和盗版区别开来。

软件生产出来就是被人用的,如果一款软件没有用户,那么就其意义就需要另外商榷。

21.1.6. 搭便车者

我们不可以强制要求邻居或朋友参与到贡献当中来,或者通过劝诱、胁迫等手段去要求ta人。

如果光是用户也还罢了,开源软件是可以解决一些实际问题的,一旦能够解决实际问题,那么它就有了经济利益,那么如果这些人,利用了开源项目,有了其它的商业目的,做了类似投机倒把的事情,那么我们不妨称这类人为搭便车者。

现实中的搭便车者,比比兼是,由于软件的商业创新,使用的是信息授权模式,所以将开源项目编译为二进制软件之后,是有商业利润存在的。但是呢,这些人虽然从中渔利了,但是并没有考虑其所利用的开源项目的持续性发展的问题,无论是人员的投入,还是金钱上的支持,甚至是宣传活动也是掩盖的。有的时候,一眼就可以看出来,有的时候却需要内行人去仔细的甄别。

21.1.7. 反对者

反对开源的人也不在少数,尤其是传统上利用专有软件授权赢得了非常高的利润的公司的员工,称开源软件为“搅屎棍”,损坏了他们的利益,违反了知识产权,最有名的就是微软公司的第二任CEO 史蒂夫·鲍尔默(Steve Ballmer)称Linux为癌症的论断了。

这里笔者想阐述一个特别的群体,那就是盗版者,由于开源的免费特性,会让传统专有软件授权的盗版者打着开源的名义堂而皇之的进行专有软件的盗版行为,以迷惑用户,或者以低于专有软件价格很多倍的形式进行非法行为。这其实也是开源的反对者,而且这个更具破坏力,主要是混淆视听。从道德上讲这一类人是要被谴责的,在法律上讲是严重的违法。

21.1.8. 开源相关研究的学者

就开源这个现象而言,它太过于迷人,以至于很多学科的学者们都为之倾倒,经济学、社会学、人类学、软件工程、心理学、管理、法律等诸多学科都在围绕开源这个主题进行相关的拓展和研究,有兴趣进一步研究的读者可以关注[开源之道论文阅读计划](https://github.com/OCselected/ttoos/projects/8),会涉及到很多相关论文的阅读和作者们的介绍。

目前整理成册的开源研究论文集,可以参考开源之道图书共读2019年11月的图书:[Perspectives on Free and Open Source Software (The MIT Press)](posts/paper_or_book_reading/book_review_of_mitfoss/),聪明的读者你可以顺藤摸瓜,可以找到各位教授在自己的领域里就开源这个主题所研究的成果,如Audris Mockus、Siobhan O’Mahony、Eric von Hippel…​…​

另外国内的学者大家可以关注北京大学周明辉教授、华东师范大学王伟老师、南京大学王宇、以及国防科技大学研究集体智慧的几位学者。

21.2. 开源共同体中的作为机构的角色分类

21.2.1. 拥抱开源的商业公司

有了上面个人的理解,再来理解商业公司就会好很多。一个主要的甄别点就是,商业公司直接雇佣核心贡献者或项目领袖,让这些人发挥自己的智力和能力,至于商业公司如何赢得商业利益,那是另外一件事情,这方面做的非常不错的公司,首屈一指的就是 RedHat 公司,当然还有互联网巨头如Google、Facebook、Linkedin、Netflix等。

也就是说,一家商业公司是否为开源共同体中的好公民,也是靠其员工的贡献值来进行衡量的。千万不要以为是PR就可以,将自己嘴上吹个天花乱坠,然而没有实质的贡献,那纯粹是扯淡。

21.2.2. 为项目共同体服务的基金会或类似机构

开源项目的共同体是一个基于互联网的虚拟组织,并不具备现实的法律实体,也就是说当项目需要资金、或者权益受到伤害到时候,在国家这个层面上,是没有可以维护的,尤其是涉及到多人的时候,然而,这个共同体主要是生产软件的,很多其它的社会性事务是不擅长的,比如组织会议、法律、接受捐赠、寻求赞助等等。那么这样的服务机构应运而生。

21.2.3. 打压开源的商业公司

从比尔.盖茨参加完家酿俱乐部之后发表的《至电脑爱好者的一封信》之后,软件以二进制分发授权的商业模式一发不可收拾,至今仍然是软件商业帝国大厦的支柱。

和很多事物一样,如果有了替代品,威胁到了既得利益者,那么这些既得利益者就会打压,其中以微软臭名昭著的“万圣节备忘录”为最,当然Oracle也是坚定的打击开源的厂商之一,收购SUN公司之后,一系列开源项目被迫停止开发就是例证。

还有就是公有云提供商,采用完全兼容开源的模式,对开源进行一些锁定的定制,然后通过捆绑的方式来进行销售相关计算、存储、网络资源。这些云厂商未必对开源共同体有贡献,但是它可以进行下游的定制,这其实是在削弱开源共同体,搞到开源项目不可持续。这些云提供商是实至名归的打压开源的商业公司!作为消费者其实应该认识到这一点。

21.2.4. 行走在开源和专有软件授权模式之间的灰色地带

上面提到,软件以二进制分发授权的商业模式已经发展了近40多年了,绝大多数以及主流媒体都对这样的模式是视之为默认的,那么开源的商业创新其实产生革命性的变化可能性不太大,那么介于这二者之间的,必然是大家都能够接受的方式,比如2019年开始火起来的“Open Core”模式,这个模式不能说是开源,但也不能说和开源没有开源,它确确实实是部分开源了,只是在功能或性能上商家做了区分。分两步走:

  1. 依靠开源软件的分发渠道和模式,让用户消费者适应,并产生锁定。

  2. 再更一步的模式采用授权模式

21.2.5. 脱离开源共同体的商业公司开源

开源共同体,是一个想象中的概念,现实当中并没有一个类似政府的机构代表这一实体,也就是说,任何人都可以称自己是开源的一份子。那么对于商业公司来讲,搭上开源分发的便车是个不错的营销手段,那么就有很多新的公司有效的利用到了这点,它有可能是刚刚打进软件这个市场,并没有在技术上和开源共同体形成一个有效的技术栈(参考上面提及的产业链的视角看开源软件),或者说在现有的开源共同体中是一个新的实体,从来没有人听说过他们,他们也没有对现有的共同体下的项目做任何的贡献。即使是这样,他们“开源”自己的产品,使自己始终处于游离的状态,使自身是处于一种“孤岛”的状态,虽然开源了,但是并没有融入到开源共同体当中,从技术、文化等诸多角度来看都是。

这类公司,我们也会常常遇到,大多是创始人在遇到经营困难的时候,突发奇想,对众包、免费劳动力、庞大的消费者群体等吸引,于是,幻想着自己的产品能够通过他们自己理解的开源一炮打响。这些人当然往往也找不到宣传的途径,最明显的特征就是寻找传统的媒体来进行PR,然而也只是共同体之外的人看热闹而已。对于开源共同体来讲,这些所作所为显然不是他们所关心的内容。

22. 开放式开发平台的崛起

当然,伴随着开源的崛起,大大小小的开源共同体所生产的开源项目水涨船高,逐渐的开始被社会所认可,并获得了更多的资助。那么人类这么聪明的物种,从来不会放过任何能够可以复制成功的机会。于是有人开始总结开源项目的开发模式,并进行了整理。并开发了相应的平台:

GitHub 我们在本书中会进行专门的叙述,请移步[GitHub 详解],其它平台我们就在这里给大家简单的叙述一番。

GitHub 作为开发平台,凭借着简化的流程、更易分享代码、更加容易识别高超技能的人,GitHub 作为目前世上汇聚开发者最多、托管代码最多、提交次数频繁的服务平台,值得专门仔细的讲解。

Launchpad 是颇为完善的软件开发协作平台,由知名Linux 发行版 Ubuntu 的母公司 Canonical发起和维护,提供了非常完善的功能:

  • Bug 跟踪系统

  • 支持分布式版本控制系统 Bazaar 和Git

  • 支持在线 Code review

  • 邮件列表

  • 支持Ubuntu 包的构建和托管

  • 在线翻译

  • 问答和FAQ

由非常多的开源项目在该平台上托管,如:

首先你需要在该网站上注册一个id,然后登录,登录之后就可以根据具体的项目进行代码开发、Bug 提交、Review代码、撰写文档等等日常工作。

进一步的操作可以参考其 用户文档,该文档详细的说明了

GitLab 是由 GitLab Inc.开发,一款基于 Git 的集大成的软件开发平台。 另外,GitLab 且具有wiki以及在线编辑、issue跟踪功能、CI/CD 等功能。 GitLab 由乌克兰程序员 Dmitriy Zaporozhets 和 Valery Sizov 开发,它由 Ruby 写成。后来,一部分用 Go 语言重写。截止 2018 年 5 月,该公司约有 290 名团队成员,以及 2000 多名开源贡献者。 GitLab 被 IBM,Sony,Jülich Research Center,NASA,Alibaba,Invincea,O’Reilly Media,Leibniz-Rechenzentrum (LRZ),CERN,SpaceX 等组织使用。

GitLab 从开始建造的哪天起就是走 GitHub 的模仿路线,且以GitHub 本身服务不开源为竞争策略,一路走来也赢得了很多私有化部署的口碑。GitLab 具备GitHub 的几乎所有功能。

Google Android 除了在Android 本身之外,在代码项目之外,也有非常多的创新,如此之大的项目规模,repogerrit 就是其中的翘楚。 Gerrit 是作为代码审核、讨论之用的,严格说来不能算是一个平台。但是它代表了一种典型的软件开发方式,故 在此特别列出。Gerrit 为 Git 引入的代码审核是强制性的,也就是说除非特别的授权设置,向Git版本库的推送必须要经过Gerrit服务器,修订必须经过代码审核的一套流程之后,才可能经批准并纳入正式的代码库中。[6]

android workflow 0

首先贡献者的代码通过Git命令(或repo封装)推送到Gerrit管理下的Git版本库,推送到Gerrit管理下的Git版本库,推送的提交转化为一个一个的代码审核任务,审核任务可以通过refs/change/下的引用访问到。代码审核者可以通过 web 界面查看审核任务、代码变更, 通过web界面做出通过代码审核或打回等决定。测试者也可以通过refs/change/之下的引用获取修订然后对其进行测试,如果测试通过就可以将该评审任务设置为校验通过(verified)。最后经过了审核和校验的修订可以通过Gerrit界面中的提交动作合并到版本库对应的分支中。

有兴趣的读者,可以进一步的到Google 的Android 代码平台,进行实践或只是观看也好。 Android Gerrit

在2017年,danvet 撰写了一篇为什么 GitHub 无法托管 Kernel 的文章[7],当然这也不是 Danvet 一个人说的,在 Linus 本人在2015年接受一次关于 Git 10周年的采访中也坦承 GitHub 并不能满足 kernel 复杂的开发需求。[8]

无独有偶,基于Linux 的发行版,GitHub 等简化开发流程等平台,也并不是理想之所。上面提及等Launchpad 即是 Ubuntu 根据自身的需求而量身定做的,其PPA项目即是这个平台的产物,那么我们来看看Fedora 发行版使用的代码托管平台。

当然,Pagure需要和其它的平台进行配合,方能实现Fedora —— Linux 发行版的打造流程,如Bug 跟踪系统 https://bugzilla.redhat.com/、rpm 构建平台 Dojo、Git代码协作平台 src.fedoraproject.org以及日常的邮件列表和IRC ,以及最具特色的 Fedora Wiki系统,共同构造出来的发行版开发平台。其中代码部分是上下游链接的关键所在。

Trac是一个为软件开发项目需要而集成了wiki和问题跟踪管理系统的应用平台。Trac以简单的方式建立了一个软件项目管理的web应用,以帮助开发人员更好地写出高质量的软件,并力求不影响团队现有的开发过程。

Trac提供了访问Git、CVS、Subversion等版本控制系统的界面,内置wiki和方便的报告生成工具。

Trac允许在问题描述和提交信息中使用wiki标记创建链接,可以很方便地在缺陷、任务、变更集、附件、wiki页面之间进行相互引用。时间线(timeline)按照时间倒序的方式显示项目上发生过的所有事件,使获知项目概况和跟踪项目进展变得很容易。路线图(roadmap)显示前面的道路(road ahead),列出即将到来的里程碑(milestone)。

等平台的开发模式,上述这些平台基本会覆盖软件开发中所有的系统,而且还和其它系统有着友好的集成。

GitEE 是OSChina 旗下的代码托管协作开发平台,类似于GitHub、GitLab 的定位,但是 Gitee 相对集成的现代 CI/CD、DevOps、以及第三方插件的功能弱一些,由于其定位在中国本土,所以和即时通信工具如微信之类的非透明内容集合的颇为紧密。

Gitee 最初是基于 GitLab 开发,像绝大多数的 fork 项目一样,在不久之后就分道扬镳了,按照自身的理解、为满足客户的需求、对于技术的理解等有了不同的思考和行动。

Gitee 针对个人开发者是比较友好的,完全免费,可以拥有私有仓库。

22.1. 小结

分布式带来的人类协作,从来没有像 Git 这样彻底解放了人类的限制,就软件开发这件重要的信息时代的生产力,完完全全的释放了! 围绕 Git 的生产工具水涨船高,一路高歌猛进,不仅获得了几乎全世界所有的开发者的青睐,也赢得了资本、商人、创新者的关注。

最终,我相信软件开源作为人类协作更加文明高效的方式,一定会是软件开发的未来,而对于开源的深刻理解,也终将会成为我们未来进一步去推动整个人类社会演化进程中最重要的基础认知。[10] --- 赵生宇,同济大学开源博士

例如项目 hypertrons,就是试图将开源文化、制度等人类等思维认知的内容工具化,试图将开源共同体的最佳实践以技术和自动化的方式植入上述的这些平台,从而让开发者能够在潜移默化的过程中将下章所谈及的内容就做了,开发者可以专心到代码上,而毋需为这些事情操劳。 类似的围绕Git协作平台的工具、人工智能、数据分析等创新正在不断被开发和激活。

开放式开发平台的星火燎原之势,对于生产者来说是极度友好的,各种工具简直是魔法般的存在,可以说是伸手即来、挥手即去,这在十年前是无法想象的。十年前的软件,无论是开源还是闭源,基本上仍然受限于其它行业的工程和管理理论来治理整个项目,例如组织结构的设计、项目周期的制定、里程碑的想象等等,现在看来这些 均是摸索路上的必要损耗。

但是,这些平台之间的竞争,也成为了开发者们彼此隔绝的阴影,没有人能够在孤岛中实现自由,而这些平台的演变也成了开发者们至为关心的内容,此时仍然要借助世界的其它力量来制约这些平台之间的彼此孤立,甚至是恶性的竞争。当然,即使是最坏的情况,开发者仍然有选择的权力。

23. 开源社交礼仪

因为是共同体,没有强约束关系,所以全凭是人类的高级认知来进行沟通、协商,进而形成默契。所以一些基本的,人类进化到目前为止的所有优秀的内容都应该在此得到最好的展现。

中国古代著名哲学家孔子有云:

“非礼勿视,非礼勿听,非礼勿言,非礼勿动。”

开源共同体毕竟是由现代人构成的,凡是人组成的社会,都是由一定的规矩,否则的话,就会处于熵增,陷入无序而混乱的状态。

23.1. 开源共同体中鼓励和倡导做什么?

人类社会是复杂的,划分的边界也是五花八门,常见的有文化、国家、地域、城市、宗教、风俗、种族、民族等等,如果是讲究差别的话,那么就根本不用谈合作,什么基于互联网的全球化简直是不可能的事,但是我们终究是人类,再大的差别也能找到共同的元素,尤其是良善的内容。

23.1.1. 使用开源共同体所倡导的语言

此处的语言可以理解为两层意思,第一个意思是我们所使用的文字描述,如汉语、英语等,第二个意思是某些文化类型的风格。下面一一进行说明:

===

如何学习

所谓的“物以类聚,人以群分。” 是说人是会自己自动划分出

23.1.2. 保持开放、透明

includ::keep-open-stupid.adoc[]

23.1.5. 学会提问

尽管在开源的世界里,关于如何提问这个问题的最佳描述,我们有着无法逾越的巅峰描述和解答,即Eric Steven Raymond 所撰写的如何指挥的问问题[1],中文也有非常好的翻译。[2]。但即使是这样,仍然有非常多的不是那么优质的问题存在。这是一个更为复杂的关于教育的问题, 我们不妨在这里引用一句话:

每一代人必须为自己再造一遍民主,民主的本质与精髓乃是某种不能从一个人或一代人传给另一个人或另一代人的东西,而必须根据社会生活的需要、问题与条件进行构建。 ———— John Dewey ,哲学家、教育家

在搜索引擎如此发达的今天,社交2.0、大数据、等高度发达的今天,作为一名有志于学习开源软件开发的人,如何智慧的提问显得略微的有点不合时宜,但是,笔者认为恰恰是因为这样,我们才更加的应该重新提倡提问,提问并不是为了当下的答案,而是希望和开源的某一位维护者、专家建立联系 建立一种对话的精神,让那些隐性的知识能够渐渐的显露出来。

据各种不完全的调查和直觉[3],有人下结论说本土的人们极少提问,和老师和同学难以形成一种互动和对话。当然这可能和成长的环境,如家庭,也可能和受到的教育有关。大部分的科学结论,都提到这个人后天的成长有关,也就是说是可以习得的一种技能。

23.1.6. 使用Google 和 Wikipedia

这个世界的复杂远远超出了我们的想象,比如内容审查制度的存在,这些内容有兴趣的读者,可以自行查阅相关资料。这里不打算为大家阐述其好处坏处。尤其是作为互联网的入口处:搜索引擎的重要性。

这里只是重点强调,请使用 Google 进行搜索, 比如“开源之道”这四个字,Google会在第一个位置上定位到 http://opensourceway.community/站点,而在其它搜索网站则根本找不到这个站点。

googel opensourceway

有关更多Google 的介绍,请访问相关的书籍和资料,尤其是《Google Hacks》这套图书,当然,最重要的还是要使用Google的服务。如果你是一名专业的技术人员,Google 很可能是你无法离开的工作、学习、生活的助手。

很多时候,在使用Google 搜寻资料的时候,会在第一个检索结果给出 Wikipedia 的词条,没错,作为全球最大的知识集散地,有着非常不俗的中文名称:维基百科。这是一个自由内容、公开编辑的网络百科全书的协作计划。通过 Wiki 技术, 让包括读者你在内的所有人都可以编辑和修改其内容,只需要一个可以上网的浏览器就可以了。Wikipedia 这个词 是由 Wiki 和 encyclopedia 混合后的新词。

抛开其它行业的知识不谈,光是信息技术,Wikipedia 绝对是可以让一名新手从生到骨灰找到相应的路径的,wikipedia 不仅能够给出想尽的解释,还给出具体的出处。比如我们想了解计算机编程语言 go,Wikipedia 的 https://en.wikipedia.org/wiki/Go_(programming_language) 的页面会给出非常详尽的关于go 编程语言的所有知识:

  • 为什么要开发Go这门编程语言

  • 是谁主导开发的

  • 经历过那些变化

  • 有何新的特性

  • 有那些应用领域

  • 设计的新颖之处

想要了解的背景知识都在这里了,甚至还能往回追溯,计算机编程语言的类型,Ken Thompson 是谁?如果进一步学习,应该去哪里?简直是一副全景式的上帝视角的知识图谱。

维基百科不是一部百科全书。它是一座虚拟城市,这座城市对世界的主要贡献就是上面的百科文章,不过这座城市本身也有自己的内部生活。这所有的页面——交流页面、…​…​、共同体页面和文章页面——都反映了维基百科内部的关键任务,并帮助运行一部百科全书这样庞大的工作拆分成了许多更小的任务。而且,正如一座运转良好的真实城市一样,这种分工并不是某个中央委员会能够提前决定的,它是根据维基百科”居民“——维基百科的编辑者们——的需要和欲望而有组织地涌现出来的。 ———— [美]迈克尔·尼尔森(Michael Nielsen),《重塑发现》

当遇到一个问题,使用了上述的两个人类伟大的杰作之后,还有什么疑问的话,那就是和人的交流了。

23.1.7. 何为隐性知识

隐性知识(Tacit knowledge)是迈克尔·波兰尼(Michael Polanyi)在1958年从哲学领域提出的概念(同年他出版的《个人知识》一书中有详细的描述)。他在对人类知识的哪些方面依赖于信仰的考查中,偶然地发现这样一个事实,即这种信仰的因素是知识的隐性部分所固有的。波兰尼认为:“人类的知识有两种。通常被描述为知识的,即以书面文字、图表和数学公式加以表述的,只是一种类型的知识。而未被表述的知识,像我们在做某事的行动中所拥有的知识,是另一种知识。”他把前者称为显性知识,而将后者称为隐性知识,按照波兰尼的理解,显性知识是能够被人类以一定符码系统(最典型的是语言,也包括数学公式、各类图表、盲文、手势语、旗语等诸种符号形式)加以完整表述的知识。隐性知识和显性知识相对,是指那种我们知道但难以言述的知识。

  • 默会性:不能通过语言、文字、图表或符号明确表述:隐性知识一般很难进行明确表述与逻辑说明,它是人类非语言智力活动的成果。这是隐性知识最本质的特性。

  • 个体性:隐性知识是存在于个人头脑中的,它的主要载体是个人,它不能通过正规的形式(例如,学校教育、大众媒体等形式)进行传递,因为隐性知识的拥有者和使用者都很难清晰表达。但是隐性知识并不是不能传递的,只不过它的传递方式特殊一些,例如通过“师传徒授”的方式进行。另外,这里需要区别“个体性”与“主观性”。波兰尼认为,和主观心理状态之局限于一己的、私人的感受不同,个体知识是认识者以高度的责任心(responsibility),带着普遍的意图(universal intent),在接触外部实在(external reality)的基础上获得的认识成果。可见,个体的不同于主观的,关键在于前者包含了一个普遍的、外在的维度 。

  • 非理性:显性知识是通过人们的“逻辑推理”过程获得的,因此它能够理性地进行反思,而隐性知识是通过人们的身体的感官或者直觉、领悟获得的,因此不是经过逻辑推理获得。由于隐性知识的非理性特征,所以人们不能对它进行理性地批判。

  • 情境性:隐性知识总是与特定的情景紧密相联系的,它总是依托特定情境中存在的,是对特定的任务和情境的整体把握。这也是隐性知识的很重要的特征。

  • 文化性:隐性知识比显性知识更具有强烈的文化特征,与一定文化传统中人们所分析那个的概念、符号、知识体系分不开,或者说,处于不同文化传统中的人们往往分享了不同的隐性知识“体系”,包括隐性的自然知识“体系”,也包括隐性的社会和人文知识“体系”。

  • 偶然性与随意性:隐性知识比较偶然、比较随意,很难捕捉,所以获取的时候就比显性知识要困难。

  • 相对性:这里的相对性有两层含义:一是隐性知识在一定条件下可以转化为显性知识,二是相对于一个人来说是隐性知识,但是同时对另一个人来说可能已经是显性知识,反之亦然。

  • 稳定性:与显性知识相比,隐性知识与观念、信仰等一样,不易受环境的影响改变;它较少受年龄影响,不易消退遗忘;也就意味着个体一旦拥有某种隐性知识就难以对其进行改造。这意味着隐性知识的建构需要在潜移默化中进行。

  • 整体性:尽管隐性知识往往显得缺乏逻辑结构,然而,它是个体内部认知整合的结果,是完整、和谐、统一的主体人格的有机组成部分,对个体在环境中的行为起着主要的决定作用,其本身也是整体统一,不可分割的。

在软件开发的过程中,存在大量的隐性知识,这也是为什么作为开发者需要受训多年才能在项目中发挥作用的重要原因所在。软件开发有几个特征是无法用显性知识覆盖的:

  • 实践性非常强的知识劳动

  • 需要大量的沟通,即大规模的多人协作

  • 软件是流动的、动态的

  • 需要即时的反馈,因为源代码到软件执行和使用,是有一个需要跨越的过程的

  • 需求的提出,和开发者的理解,中间需要大量的正式、非正式的沟通

这就是为什么我们在前面特别提到一定要保证开放和透明的重要原因,因为隐性知识的存在,所以需要开发者们进行大量的沟通,以及日常的交谈,显得尤为的重要。

那么想要学习到这些“意会”,需要躬身亲自动手,也需要找到合适到导师,那么赢得导师本身就是最大到提问,一个好的问题,可以获得导师的青睐有加,然后建立长时间的信任和”师徒”关系,进而在实践中获得隐性知识。这就是开源的诀窍所在。

23.1.8. 对话的精神

对话的社会是人类的关键所在。 ———— Raymond Aron ,法国知识分子

是的,当下对于如何智慧的提问要比 Eric S.Raymond 写下的指南要更加的艰难,那个时候的互联网和今天的爆炸式的知识和信息不可同日而语。在已经完成了相应的准备工作之后,那么接下来要做的其实就是形成一种对话。每个人的成长路径都是不一样的,兴趣点也是不同的。在知识的获取过程中 也有着不同的诉求。

针对计算机知识的相关问答目前也有对应的站点,如:

另外,随着开源的崛起,很多开源项目背后都有着充足的资源支持,其知识体系建立的也是非常的完善,以 Kubernetes 为例,为了和开发者和用户建立联系,Kubernetes 搭建了如下的渠道供大家建立对话:

那么问题来了,如此之多的工具,如此之多的方式,我们该如何处置?其实,万变不离其宗,这些都是现实的连接需要,也就是说需要建立人与人之间的对话,形成沟通,让知识流动起来。

23.2. 开源共同体中不可以做什么?

我们先来说说通常的开源项目所建立的共同体,需要大家遵守的一般法则,这意味着作为要参与的你不能够做什么,这是一个非常清晰的边界:

通常的行为守则的描述遵循如下几点:

  • 行为守则在哪里有效 (只在issues以及pull requests,或者社区活动?)

  • 行为守则适用于谁 (社区成员以及维护者,那赞助商呢?)

  • 如果有人违反了行为守则会怎样?

  • 大家如何举报违规

  • 无论你们在哪里,请使用已有的行为守则。 贡献者盟约 是一个被超过40,000个开源项目(包括Kubernetes, Rails和Swift)所使用的行为守则。

Django行为守则Citizen行为守则都是非常好的行为守则。

请将 CODE_OF_CONDUCT 文件放在你们项目的根目录,并在README中附上其链接,这样对你们的社区是可见的。

24. Community (共同体)治理模型

我们在这里讲述共同体的治理模型,其实很难和项目相区分开来,正如我们在本章开头所为开源共同体下的定义一样,离开了开源项目,开源共同体的意义就不复存在。

一千个人眼中就有一千个哈姆雷特,几乎是每有一个开源项目,就会有一个相应的开源策略,正因为此,关于项目的各项细节如政策、战略等,要准确无误的传递给对于项目有产出的潜在用户和开发者。一个清晰的治理模式可以让潜在的贡献者能够如何参与到项目中来,以及能够获得什么,甚至是提供哪些保护措施以确保大家的贡献始终是可用的。此外,它描述了有助于确保潜在用户项目可行性的质量控制流程,清晰简洁的开发沟通是开放式开发实现 可持续性的最重要的步骤。

治理模式涉及范围颇广,从中心化的控制,无论是单独的个体还是组织(仁慈的独裁者),到基于贡献度认可的分布式控制,都会有所涉及。这中间有个类似光谱的范围,在这个范围内容的任何一点都会有相应的治理模式,而且随着项目的成熟,项目所选择的治理模式还会有所变化。下面一节图中所示的内容即是FOSS的项目示例,以坐标的方式所表达,该图还说明了这些项目是否鼓励来自广泛来源(市集式)的贡献,或者是否是仅针对一小部分人的专门贡献(大教堂风格)。关于贡献的模式的进一步的信息,请阅读 Eric Raymond 的大名鼎鼎的文章《大教堂与集市》,这里蛮耐人寻味的是,特定的治理风格并不会一定和某个贡献模式挂上钩,有的时候会出现,在项目的开始阶段,是采用的大教堂的仁慈的独裁者模式,但是随着时间的转变,项目的成熟,会转变为市集式的贡献或精英式的治理(或两者兼而有之)。

governancevcontrib
  • Linux 项目就是 Raymond 提及的经典的集市模式,鼓励任何人都可以做出贡献,尽早发布,经常发布,该项目由其创始人 Linus Trovalds来治理,Linus 对发布中包括哪些贡献拥有最终的决定权。

  • GNU Emacs 是Raymond 论及的所谓的大教堂模式,由一个小的团队所组成的贡献者,而且发布的频率并不是那么的频繁,项目早期由 Richard Stallman 治理,不过值得注意的是,在Raymond 完成它的文章之时,Stallman其实已经不再管理这个项目了,而当前的维护者采用的是更加开放的贡献模式。

  • Apache HTTPD 项目是 Apache 软件基金会的项目,遵循正式的精英结构,Apache面向全球所有人,任何人都可以在上面贡献代码。

  • Apache OODT ,同样也是 Apache 软件基金会的项目,采用的是Apache精英模式,然而,它的开发模式是大教堂风格的,并不会积极的邀请他人作贡献。当这些核心团队成员觉得可以保证一定质量水平时,才会发布具体的版本。

  • Ubuntu 则是一个典型的仁慈的独裁者模式,即项目的把控者是其创始人和资助者:Mark Shuttleworth,然而,实际上的许多决定是由社区委员会和技术委员会决定的,而委员会的组成是由社区通过选拔来任命的,Ubuntu系统的核心部分是在 Canonical 内部开发,采用的是大教堂的风格,然而,也有社区社区的开发人员会被邀请去开发系统的关键部分,比如Ubuntu收集平台的核心应用程序。

我们来适当的分析一下这些典型的治理模式。首先,来看看 Ubuntu 的治理模式,根据Ubuntu的描述,更加侧重于描述社区的结构以及与该结构的每个组件相关的职责,以及项目中决策过程的概要描述。Ubuntu项目是将开发人员信息和治理文档中的信息是分开的,但是其技术管理流程是被明确所记录的。

Apache 软件基金会为每个项目设置了两份治理文档,首先是基金会本身的治理文档,如组织结构的规定,另外的文档还专门介绍了诸如决策的关键过程的内容,然而,由于每个项目都是自由的,内部有一些限制条件,为了定义好各自的这些具体的变化,Apache软件基金会的很多项目都有自己的治理文档。有关示例,请参阅 Apache Forrest治理说明。

我们列举的第三个关于治理模式的例子是关于 Taverna项目,该项目是一个属于学术界内发展开源的例子,因此展示了一种在学术环境中发挥作用的模式。Taverna 的模式和上述Ubuntu以及Apache软件基金会一样,侧重于项目的结构和管理流程。

不妨写个治理文件,有了此文件,无论是对于共同体现有的人员或发起人,还是对于新到来的潜在贡献者,有了文字性的正式描述,大家均有章可循:

一旦你建立了自己要采用的模式,接下来要做到事情就是制定一份友好的治理文档,从而详细的说明制定决策和对贡献的识别等过程,下面的内容就是介绍一个创建项目治理文档的一般框架。该框架会描述要文档设计的主要方面,以及解释为什么这些内容是重要的,在最后,我们还给出了一些案例模板的链接。

一个典型的治理文档应包含如下章节:

  • 概览

  • 角色和责任

  • 支持

  • 决策流程

  • 贡献流程

24.1. 概览

治理文档的概览部分,应该提及的有项目的目标、项目管理方式等简要概述,而且要将它们适当的联系起来。另外就是一些关键的信息,如项目最终采用的许可证、版权的所有者、以及用户该如何参与项目的开发等。

概览要尽可能的简短,目的就是让观看的人们能够迅速了解他们参与项目相关的期望。

24.2. 角色和责任

本节内容描述了项目中的正式角色及其权限。它还应该涵盖所需要的承诺水平以及每个寻求参与的角色。本部分的目标是明确谁管理项目、谁可以贡献、以及如何贡献,乃至于如果希望直接影响项目的话,该如何积极的表现。

定义角色的时候,可能都是大家耳能生详的名称,如“用户”、“贡献者”、“提交者”、或“项目管理委员会成员”。当然,也可以非常的具体,如“发布经理”、“测试经理”、“社区经理”、“产品经理”等等,通常情况下,所提供的细节越多,人们就越有可能识别出他们可以做出贡献的事情。谨记,请注意不要限制人们可以做出的贡献。例如,拥有“发布经理”头衔的人可能会觉得他们不适合协助管理项目路线图,这似乎是“产品经理”角色的一部分。出于这个原因,许多项目选择了描述各种活动的广泛标题。举例来讲,管理发布和管理路线图的任务可能均由一个角色来承担——如“提交者”,该角色中的个人将自行选择他们希望贡献的活动。

反过来讲,如果没有对某些人承担特定的责任可能会导致在特定活动领域就会缺乏贡献,当然,还需要与如下一些事实相平衡:指示社区成员执行已定义的任务这事不是总能行得通的,因为社区并非是雇佣关系,没有人喜欢被颐指气使。可以参考这份单独的关于角色的[文档](http://oss-watch.ac.uk/resources/rolesinopensource)。

24.3. 支持

本小节描述了关于项目内部的支持流程,对于绝大多数开源项目来讲,支持的渠道也是项目用户的主要联系方式,这些用户在未来可能会成为项目的贡献者,也可能成为商业提供商的客户,这些都是项目获得可持续性发展的关键之所在,开源项目尤其要照顾到这些用户。

治理文档的支持部分还应描述关于可用的支持渠道以及每种渠道的使用方式。它还应提供防止在多个渠道去提供支持,那样会导致过于的分散,过于分散的风险在于一旦某个单一的地方出现大量的问题,则会显得力不从心,因为,我们要尽量的去建设和寻求可以进行自我支撑的社区。

24.4. 决策流程

对于开放式开发来讲,做决策的方式是项目成功的关键因素,一个过于耗时的流程会导致决策的延迟,从而导致整个项目的延迟,更为糟糕的是,这个流程可能会被忽略,进而社区的一部分权力被剥夺了。另外,一个定义不够明确的流程,可能会导致关于决策是否有效的争论,再次导致社区内的延迟和分裂。

决策过程的效率和透明度应该是治理文件中的主要重点。恰是这个决策的过程确保了潜在的贡献者,他们的努力将会得到项目公平的处理,并能够在未来保持价值。关于创建正确的控制结构的方法,在文章的前面我们有做过详尽的谈论。

24.5. 贡献流程

本小节介绍人们应如何为项目做出自己的贡献,关于贡献流程的文档应该介绍各种类型的贡献是可以接受的,以及让这些贡献可以被管理的工具等,本节不应提供工具的完整描述,而应提供工具提供支持的过程的清晰说明。

与贡献相关的明确流程是必要的,原因有两个:

  • 指导项目的贡献者

  • 向潜在的用户保证,所有贡献的质量控制和法律监督足够强大,从而可以生产出可靠的、精良的软件

因此,治理文件的这一部分应描述项目对版权管理,编码标准和文档的期望。它还应该描述清楚贡献后会发生什么,包括当贡献被认为是不适合项目时所遵循的过程的详细处理。

25. 开源开发协作流程

这里提及这章其实是因为顾及一般单独的开发团队,尤其是传统软件工程的做法,在开放式开发当中,是没有固定流程的。理想的状态是,所有人都是根据自身的努力和获得的社会资本来进行相应的贡献的。

这里要区别于典型的墙上挂的哪种金字塔式的组织架构图,来进行任务分工和分配的。这一点是特别注意的,没有任命或天生这一说法。

26. 维护者的最佳实践

维护者是非常关键的角色,不仅是技术上的,还有共同体方面的,可以说是集多种角色于一身,是“Hub”式的关键人物所在。 具体的技术笔者在这里就不和大家多谈了,要根据具体的问题具体去谈,这里和大家主要介绍的还是一些基本的沟通的问题。

归根结底,仍然是底层价值观的选择。  — 匿名

26.1. 免责申明

我们在市面上经常会看到,《如何做一个好爸爸/妈妈》、《十招教会你做一个好父亲/母亲》之类的,笔者并不知道这些书能不能帮到那些可怜的父母亲们,但大致翻翻他们书里的内容,觉得基本上说的都是有用的废话。

其实我们这个章节也差不多类似,身为项目的维护者,才是真正热爱自己项目的人,也是更愿意想尽一切办法让项目茁壮成长的人,他人最多是对他们经验的总结。以下就是为数不多的开源项目维护者们所分享的所谓的他们自身的一些最佳实践。

26.2. 身为一名维护者意味着什么?

作为一名维护者有什么显著的变化了呢?这里给大家举一个例子:来自 APISIX的创始人—— 温铭在2018~2020三年的 GitHub Profile 变化即是最好的说明:

wenming github profile 2018
温铭在2018年主要还是提交issue和代码
wenming github profile 2019
2019年则主要集中精力做合并
wenming github profile 2020
2020年的工作则基本就是在review他人的代码了

如果你维护着一个非常流行的项目,而你偶然意识到自己写代码的时间变少,而花费在回答 issue 的时间越来越多。恭喜你,你已经是进入维护者行列了。

在项目的起步阶段,你会不断尝试着实现自己的新想法,也能够基于自己想要的作出决定。随着项目逐渐的开始流行,就会发现你的大部分时间都花在了与用户、贡献者打交道上。

维护一个项目需要的不仅仅是写代码的能力。有些时候会有一个你意想不到的的事情要应付,但是这对一个项目的成长也很重要(相对于代码来说),我们收集了一些小技巧来让你的维护工作变得稍轻松些,这些技巧,涉及范围颇广,从写文档到管理社区都有所涉猎。

26.3. 将流程撰文档化

对于一个项目的维护者来说写文档是最重要的事情之一。

文档不仅说清楚了你的想法是什么,而且还帮助别人在问问题之前理解你需要什么和接下在希望做什么。

将一些东西写下来,当遇到不符合项目预期的内容时,可以轻松的拒绝。同时,它对于人们的参与提供了指导。最有意思的是,撰写文档的人可能永远也不知道是谁读了他写的文档,或者是谁是项目的使用者。

即使你不想长篇大论,对要点略说一二也比啥都不写要好。

26.4. 写下你的项目的发展方向

请在项目启动时就写下项目目标,并将之加到 README 文件中, 或者创建一个单独的 VISION 文件,其它的内容,如项目管理路线图,也可以帮助人们了解到更多的信息,最好是也把他们公开发布。

拥有一个清晰的愿景,且明确的使用文档来将之公开,可以保证项目的动向不会跑偏,同时也能保障不会因为其他的贡献者增加的奇怪的需求而使项目变质。

比如,@lord 发现项目有一个明确的愿景能够帮助他决定哪个 PR 值得花时间。作为一个维护者的新手,他甚至还后悔当他接到第一个关于 slate PR的时候没有坚持项目本身的原则。

26.5. 和大家交流你自己对项目的期望

制定规则是很伤脑筋的。有时候你可能觉得你像是在限制别人的行为,或者说把好玩的东西都搞没了。

制定了规则,然后严格执行,当然啦,好的规则会让维护者更轻松。它可以把维护者从做自己不愿意做的事情中解脱出来。

大多数知道你项目的人对你或者你的处境都是一无所知。他们可能会觉得你做这个项目是有钱拿的,特别是你的项目是他们经常用的而且某种程度上有点依赖的时候。其实你只是偶尔会在项目上花很多时间,你可能现在正在忙着安置新工作或者照顾刚出生的儿子。

这些都是再正常不过的事情!所以确保让别人也知道这些。

如果你维护某个项目是利用空闲时间或者完全自愿的,能花多少时间就花多少时间。而不是你觉得项目需要你花多少时间或者别人想让你花多少时间。

这里是一些值得你写进项目里的东西:

  • 怎样的贡献才会被复查和接受(需要测试吗?提Issue有模板吗?)

  • 你本人会接受什么类型的贡献?(你是不是只希望在某些部分的代码上需要别人的帮助?

  • 在合适的时候跟进项目(比如说 如果你在七天之内没有收到 maintainer 的回复,而且依旧没有其它任何的响应,那么就直接@Ta。

  • 你会在这个项目上花多少时间(比如说 "我们每星期只会在这个项目上花5个小时")

Jekyll、https://github.com/CocoaPods/CocoaPods/wiki/Communication-&-Design-Rules[CocoaPods]、以及 Homebrew 均是为维护者和贡献者提供了很好的基本规则的项目,都乃业内典范。

26.6. 保证所有的交流都是公开进行的

不管是什么时候,保证你的交流是在公共的场合(就是大家都能看到的地方)。如果有人尝试和你私聊,哪怕是讨论一个新的需求或者功能,请礼貌的引导Ta到公共的交流场合,比如邮件列表或者iuuse tracker。

在此特别提醒的一点就是不要使用诸如微信(WeChat)、钉钉之类的工具,这类工具的特点就是无法做到所有的事情在公开的场合下进行。除了无法检索之外,对于新加入的新人而言极为的难堪,因为ta查不到任何的信息。

如果你和别的维护者面基了,或者在私下做了一个很重要的决定,把这些信息告诉大家,即便哪怕只是把你的笔记发上去。

这样的话,每个新加入到社区的人和已经呆了多年的人是站在同一起跑线上的,因为了解到的信息是一致的,即提供平等的沟通机会。

26.7. 学会拒绝他人

把所有的事情都写下来,当然,对于你个人来说,执行自己制定的规则的时候客观分析实际情况也有帮助。

拒绝别人确实不是很好玩,但是也要表现出专业程度,比如使用“你的贡献不符合这个项目的标准”而不是“我不喜欢你的贡献”这样显得粗鲁的语句。

作为一个维护者,在很多情况下,你都要拒绝别人,例如:

  • 不符合项目规则的PR

  • 某个人脱离了讨论的重点

  • 给别人做无关紧要的工作

  • 等等

26.8. 保持友好沟通

你要学会拒绝的最重要的地方就是 issue 和 PR 请求。作为一个项目的维护者, 你会不可避免的收到你不想接受的建议。

可能某个贡献并不在项目的范围或者与你的期望不合。又或者是可能想法很好,但是实现的却很烂。

不管是什么原因,在处理这些不符合项目标准的贡献的时候都要婉转。

如果你收到了你不想接受的贡献,你的第一反应可能是忽略或者假装没看到。但是这么做会严重伤害到别人而且可能会让你社区里的其他贡献者失去动力。

别因为自己感到内疚或者想做一个好人就把你不想接受的贡献继续保留。随着时间的流逝,这些你没有回答的 issue 和 PR 会让你觉得越来越不爽。

更好的方式是马上关掉你不想接受的贡献。如果你的项目已经饱受积压的 issue 的折磨,@steveklabnik 可以给你点儿建议,http://words.steveklabnik.com/how-to-be-an-open-source-gardener[如何高效的解决 issue]。

第二点,忽略别人的贡献等于是在社区传递了一个负面的信号。让人感觉提交一个贡献是蛮恐惧的事情,尤其是对于刚加入的新手来说。即使你不接受他们的贡献,告诉他们为什么,然后致谢。这会让人觉得更舒服。

如果你不想接受某个贡献:

  • 感谢他们 的贡献

  • 解释为什么他们的贡献不符合 项目的需求范围,然后提供清楚的建议以供改善,如果你可以的话,和蔼一点,但同时也要讲原则。

  • 引用相关的文档, 如果你有的话。如果你发现你反复收到你不想接受的贡献,把他们加到文档以免你在将来重复叙述。

你不需要用超过1-2两句话来回复。比如,当一个 celery 的用户报告了一个 window 相关的错误,@berkerpeksag 是https://github.com/celery/celery/issues/3383[如此这么] 回复的

如果你感觉拒绝别人很不好意思,也很正常,其实很多人都是这样。就像 @jessfraz 说到的:

我和很多来自诸如 Mesos, Kubernetes, Chromium等不同开源项目的维护者交流过,他们都异口同声的觉得做一个维护者最难的就是拒绝你不想要的补丁。

对于不想接受别人的贡献这件事不要感到愧疚。如 [@shykes](所说(https://twitter.com/solomonstre/status/715277134978113536)开源的第一原则就是 "拒绝是暂时的,接受是永远的。” 当然啦,认同别人的热情还是一件好事,拒绝他的贡献和拒绝他这个人是两码事。(要做到对事不对人。)

最后,如果一个贡献不是够好,你没任何义务接受它。对那些想对你的项目做贡献的人保持和蔼和积极的态度,但是只能接受那些你确定会让你的项目变得更好的提交。你说拒绝的次数越多,对你来说拒绝别人就越容易。谨记!

26.9. 保持主动

要想减少你不想接受的贡献的数量,首先,在你项目的贡献指南中解释如何提交贡献以及描述清楚什么样的贡献会被接受。

如果你收到太多低质量的贡献,让那个贡献者先多做做功课,比如:

  • 填写一个 issue 或者 PR 的模板/清单

  • 在提交PR之前先开一个 issue

如果他们不遵从你的规则,马上关掉 issue 并引用你的文档。

当然啦,这么搞一开始是不太舒服,但是你主动一点确实对双方都好。它减少了某个人花太多时间到一个你不想要的 PR 上的可能性。而且还会让你管理起来更轻松。

26.10. 成为导师

可能在你的社区里有人不断提交一些不符合项目需求的贡献。对你们双方来说,不停的拒绝他的提交,会令双方都很尴尬。

如果你发现有人对你的项目很上心,但是就是需要调教,那就耐心一点。给他解释明白每次它的提交为什么不符合项目需求。尝试着让他先做一些简单一点的事,比如那些标有_"good first bug"_ 标签的issue,以此让他慢慢习惯。如果你有时间的话,考虑教Ta怎么完成第一次贡献,或者在社区找一个人教Ta。

26.11. 有效利用社区

你不需要凡事亲力亲为。这就是社区存在的原因!即使你没有一个活跃的贡献者社区,但是如果你有很多用户的话,拉他们来干活儿。

26.12. 分担工作量

如果你正在寻找其他人来参与, 从身边的人开始。

当你看到新的贡献者不停的提交贡献,通过分配给他们更多任务来表示认可。如果别人愿意的话,记录下别人是怎么成长为领导者的过程。

鼓励别人来[一起管理项目](../building-community/#share-ownership-of-your-project)能很大程度上减轻你的工作量,就像 @lmccart 在他的项目 p5.js 上做的那样。

如果你需要暂时或者永久的离开的项目,请找人来代替你,这并没有什么不好意思。

如果别人认同项目的发展方向,给他们提交的权限或者正式把项目所有权转移给他。如果有人fork了你的项目而且在保持活跃的维护中,考虑在你的原始的仓库放上这个fork版本的链接。如果大家都希望你的项目继续的话这不失为一种好办法。

@progruim 发现 由于它给他的项目 Dokku 写一个关于项目发展方向的文档,即使在它离开这个项目后他的那些目标仍然会被实现。

我写了一个wiki来描述我想要啥和为什么。不知道为啥,项目的维护者就开始推动项目朝这个方向发展,这对我来说还是有点惊讶的。他们会丝毫不差的按照我的意愿去做这个项目吗?不总是这样,但是总是会把项目推动到离我的理想状态更近的位置。

26.13. 让别人尝试他们自己想要的解决方案

如果有贡献者关于项目有不同的意见,你可以礼貌的鼓励它在他自己 fork 的版本上继续工作。

fork 一个项目不什么坏事情。能复制并且修改别人的代码是开源项目最大的好处之一。鼓励你的社区成员在他自己 fork 的仓库上继续工作,这是在不和你的项目冲突的基础上,给实现他们的想法最好出口。

这对于那些强烈的需要某个你没时间实现的解决方案的用户来说也是一样的。提供 API 或者自定义的钩子帮助他们更好的实现自己的需求而不需要改动源码。 @orta 发现 鼓励在 CocoaPods 上使用插件导致了很多有趣的想法的诞生。

一旦一个项目变大之后,维护者对怎么增加新代码变得保守是不可避免的事情。你可能会拒绝别人的需求,但是很多人提的都是合法的需求。所以,你最后不得不把你的一个工具变成平台。

26.14. 使用机器人

就像很多工作别人可以帮你做一样,也有很多工作不需要人来做。因为有机器可以替代人工,尤其是那些重复、无聊的工作,用好它们能够让你的生活变得更轻松。

26.15. 引进测试和别的检查来改善你的代码质量

让你项目自动化的最重要的方法之一就是引进测试。

测试能够帮助贡献者得知他们没有弄坏什么。测试也让你复查代码和接受别人的贡献的过程更加容易。你反应的越多,社区参与的就越多。

设置自动化的测试让所有新来的贡献者都可用,而且保证你的测试可以很容易在贡献者的本地运行。保证所有的代码贡献者在提交之前都运行你的测试。你还得为所有的提交设置一个基本的标准。

如果你添加了测试,确保在 CONTRIBUTING 文件里面解释他们是怎么工作的。

26.16. 用工具来自动化日常的维护工作

对于维护一个流行的项目来说,一个利好消息是别的维护者也可能遇到过类似的问题而且已经找到一个解决方案。

这里有 各种各样的工具帮你自动化一部分的维护工作。这里仅列举一些常见的例子:

对于bug报告和其他常见形式的贡献,Github有 Issue 模版和 Pull Request 模版, 你可以用来降低沟通成本。你也可以设置 邮件过滤 来管理你的邮件提醒。

如果你想更加的先进和高效,代码风格指南能帮助你的项目收到的提交更加规范,而且更容易复查和被接受。

当然啦,如果你的标准太复杂了,反倒会增加了贡献的难度。所以保证你只添加那些让每个人工作起来更容易的规则。

如果你不确定用什么工具,看一看别的流行项目是怎么做的,特别是和你在一个生态系统的。比如,其他的 Node 模块的贡献流程是怎么样的?用相似的工具和方法,能够让你项目的贡献流程对于开发者来说是很熟悉的。

26.17. 不干了也没关系

开源项目曾经让你开心,但可能现在开始让你不开心了。

可能当你想到你的项目的时候,感觉到"压力山大"。而同时,issue 和 PR 又纷至沓来。

疲倦在开源工作工作中是一个常见的问题,特别是在维护者中间。作为一个维护者,你做的开心对项目的生存来说是一个没有商量余地的条件。

虽然你不需要跟谁请假,但是也不要拖到自己疲倦不堪的时候才去度假。https://github.com/brettcannon[@brettcannon] 就是非常典型的例子,他是一名 python 语言的核心开发者,决定在14年的义务劳动之后 休一个月的假

就像其他工作一样,有规律的休息会让你对工作保持舒适愉快的心情。

有时候,当你感觉大家都离不开你的时候,请假去休息是一件蛮困难的事情。甚至你自己会因为离开而感到愧疚。

在你离开项目的时候尽可能的在用户和社区中间寻求支持,如果你找到支持你的人,还是休息吧。在你不工作的时候还是要保持和别人交流,这样人们不会因为你的失联而感到奇怪。

休假不仅适用于度假。如果你周末不想做开源项目的工作了,或者在本该工作的时候不想干活了,和别人说,这样他们知道什么时候不该打扰你。

26.18. 首先照顾好自己!

维护一个大型项目时,相比早期的增长阶段,是需要更多的不一样的技能,作为一个维护者,你会将自己的领导力和个人能力提高一个层次,而这是很少人能体会的到的。但是与此同时,要挑战管理项目,以及设定清晰的界限。只做你感到舒服的事情,能够让你保持开心、充满活力、且高效输出的状态。

27. 参考资料

Appendix A: 术语表

开源 (Open Source)

开源隶属于开放这个大的范畴,意指一款产品或制品,其不仅提供最终可用的实体,还应该提供源代码、设计文档、交流过程等,最初的意思来自于[#开源软件]的模式,随着开源软件运动的逐步胜利 和崛起,开源这个词汇的范畴也在扩大,在社会中的其它行业也有了较为广泛的应用,如开放式协作、开放内容、开放设计等。

在中国本土,开源还有另外的一个意思:“开源节流”,通常指的是让自己的收入有尽可能的多样化,与非软件行业的人交流的时候要特别的注意。

A.1. 开源软件(Open Source Software)

我们这次选择了两种解释风格,一种是正式的、举世公认的定义,即开放源代码促进会(Open Source Initative)的定义:

  1. 自由再发布

  2. 源代码

  3. 派生作品

  4. 作者源代码的完整性

  5. 不能歧视任何个人和团体

  6. 不能歧视任何领域

  7. 许可证的发布

  8. 许可证不能针对某个产品

  9. 许可证不能约束其他软件

  10. 许可证必须独立于技术

可参考: OSI定义

另外一个就是较为通俗的版本,引用自 Wikipedia

又称开放源代码软件,是一种源代码可以任意获取的计算机软件,这种软件的著作权持有人在软件协议的规定之下保留一部分权利并允许用户学习、修改以及以任何目的向任何人分发该软件。 开源协议通常符合开放源代码的定义的要求。一些开源软件被发布到公有领域 开源软件大多采用公开协作的方式进行开发,开源软件是开放式协作的典范。开源软件是开放源代码开发的最常见的例子,也经常与用户生成内容做比较。 开 源软件的英文“open-source software”一词出自自由软件的营销活动中。开源软件同时也是一种软件的分发模式。一般的软件仅可获取已经过编译的二进制可执行档,通常只有软件的作者或著作 权所有者等拥有程序的源代码。

A.2. 开源软件共同体 (Open Source software community)

为了实现一个开源软件项目,基于互联网,由企业、个人、非营利组织等形成的团体成员,在文化上能够达成一定共识,来去自由,进行一定的社会治理、活动、交流等。该共同体由计算机相关 专业领域中的工作者组成。在一种绝大多数其他领域无法比拟的程度上,他们都经受过近似的教育和专业训练。

A.3. 开源软件基金会( Open Source software Foundation)

由非政府的、非营利的、自有资金(通常来自单一的个人、家庭或公司)并自设董事会管理工作规划的组织,其创办的目的是为了支持发展开源软件项目,以服务于公共福利,主要途径是通过对其他 非营利机构的赞助。自身的资金来源主要是通过接受捐赠、监管下的营销、举办会议等。