高效参与开源的诀窍

| 设计:张千禧

夜天之书 #32 Effective Open-source Participant

Maintainers

Nominate new maintainers selectively

Maintainers 比起 contributors 需要关注的更多的事情。随着开源项目日渐复杂,开源 区逐渐成长,单靠一个人的力量很难处理好所有的事务。这个时候,就需要 maintainer 适时地发展项目维护的队伍。

首先需要理清 maintainer 头衔的定位。实际上,大部分项目的维护是个苦力活,而 maintainers 就是一群承担这些工作的 区成员。Maintainers 可能会拥有合并 PR 的权限,在 区治理中能投票做决策,确定项目发展的方向。但是,这种权限并非特权。在一个健康的 区里,任何 区成员都可以做技术讨论,也可以就 区发展话题提出自己的观点。对于技术观点,客观上更加合理的方案理应被采纳。对于 区发展话题,maintainers 也一定会考虑建设性的提议。

可能有不少人把成为 maintainer 当成参与开源 区的目标,这是很好的。如果你理解了 maintainer 的职责,通过 contribution 积累了足够的信誉,成为 maintainer 为开源 区服务,这个头衔是一个显式的认可。不过,大可不必过分纠结于 maintainer 头衔。这只是对 contribution 认可形式的其中一种,而不是唯一一种。

Maintainers 的职责并不轻松,所以 Python 区和 Apache 软件基金会下的项目 区都会有一个询问 contributor 是否愿意成为 maintainer 的流程。也存在 contributor 拒绝邀请的情况,因为就像前面提到的,健康的开源 区里,只要提议是合理的,就能凭借其客观的优势胜出。成为 maintainer 并不意味着在方案选择上有特权。

对于 contributor 的感谢,也可以通过宣传渠道发布。比起一个模糊的 maintainer 头衔,作为技术人员,我会更在意这个人实际在开源 区里实际完成的事情。

基于上面的认识,我们引出下一个观点。Maintainers 发展新成员,必须是有选择性的。

这种选择性的主要依据是维护项目的需要,而不是追求数量或者过分在意 diversity 等等。这可以类比到开发软件的目的是提供技术价值,而不是代码行数或者所采用的编程语言的数量。

一个典型的错误案例是出于自己同时是公司员工的身份,被命令将 maintainers 的人数发展到某个数字。这种指标只关注数字而不关注具体的人,而且往往定得脱离实际。公司员工迫于指标压力很容易降低 maintainers 的标准,逮到一个算一个的凑人头,或者为了 diversity 对不同背景的 contributor 采取不同的标准。这样发展出来的 maintainers 不仅不能分担项目维护的职责,还很有可能因为不胜任而产生新的问题。

另一个典型的错误经常出现在个人项目上,当个人项目发展壮大,唯一的 maintainer 想要发展新成员时,很容易陷入到要找一个自己的分身的误区。也就是说,新的 maintainer 必须和自己一样能够关注到项目的方方面面。这是不对的。没有两个人完全相同。只要一个 contributor 有足够的信誉,并且能在项目或 区的维护的某个方面上承担职责,他就是一个好的 maintainer 人选。

不过,这里讲到的信誉是一个非常主观的概念,提名 maintainer 的倾向每个项目也各有不同。

?Perl 区最初由 Larry Wall 独裁。近年来,随着他逐渐淡出核心成员圈子,Perl 区的治理实际上已经变成由 28 人组成的 core team 负责。?PostgreSQL 区由 7 人组成的 core team 和 28 位 committers 处理所有工作。?ASF 治下的项目有一套比较固定的治理模型[7]。具体到每个项目,例如 Apache Pulsar[8] 和 Apache Flink[9] 会有自己具体的要求和倾向。?Spring Project 区的 committers 都是 Pivotal 公司或 VMWare 公司的员工。但是它显然也是诞生于开源协同的作品。?Linux Kernel 基本上还是由 Linus 独裁。同时,海量的驱动和架构支持有各自的 maintainer 进行维护。参考 Linux Kernel Maintainers 页面[10]。?Netty 区没有明确的规则。Trustin Lee 发起项目并独自维护了三年。随后,Norman Maurer 和 Scott Mitchell 等少数几个人持续参与,成为 maintainer 并共同维护 Netty 项目至今。

如果让我对 maintainer 提一个基础要求,我会希望他在项目或 区中做出了卓越的贡献,并且当前的 maintainers 团队乐于和他一起工作。

Structure processes

除了增加项目维护的人员,另一个基本的减少时间浪费的手段就是结构化流程。我们分点介绍其内涵。

第一点是直觉大于文档。对于托管在 GitHub 上的项目来说,help wanted 和 good first issue 标签是一个众所周知的约定。合理标记 issue 能让 contributor 按照过往的经验快速找到切入点。我在修订 TiDB 区的治理方案[11]的时候,也是以跟 GitHub 开箱即用的功能亲和为主要目标之一。如果参与一个开源项目有太多新东西要学,那么 maintainers 就有的是要解释的东西了。大部分人效率最高的路径是完全凭直觉做事,并取得好的结果。所以如无必要,请勿设立复杂的规则。

第二点是文档大于口述。直觉毕竟只能解决部分问题,对于特殊的或者需要强调的内容,明确记录下来作为文档绝对是个好主意。

不过文档首要的还不是记录流程,而是项目的目标或者叫定位。这是每个对项目感兴趣的人都会问的问题,高水平的 contributor 尤甚。他们不仅仅是想在开源 区里做简单的工作,更想成为一个伟大的或富有价值的项目的缔造者。如果你想为你的项目吸引到高水平的开发者,那么最好是确定一个清晰且令人振奋的目标,并将它展示在最显眼的地方。例如,Apache Flink 的定位是数据流上的有状态计算,其中有状态这点是开源世界里开创性的工作。例如,PostgreSQL 的定位是世界最先进的开源关系型数据库。例如,Elixir 语言的目标是构建可扩展和可维护的应用。

其次是约定俗成的文档,包括 README 和 CONTRIBUTING 等等。其中一般包含项目的简介,开始使用的方法,参与贡献的基本流程,和指向更多文档的链接。大部分 contributor 会尝试寻找和阅读这些文档。如果他们能从其中解决自己的问题,就不需要 maintainer 花时间说明了。至少,在有人提问的时候,直接发一个文档的链接,也能省不少事儿。

另一个值得强调的是 Code of Conduct 即行为准则。提名新的 maintainer 之前最好确保被提名人知悉和理解 区行为准则。行为准则通常是一些涉及平等、尊重和避免冒犯的原则。虽然大多数开源 区很少遇到严重违反行为准则的情况,但是 maintainers 应该对此保持敏感。这类问题一旦处理不当,很容易演变成政治斗争,甚至导致 区分裂或项目停摆。

最后是设计文档。Contributors 要深度参与技术贡献需要了解相关代码的设计背景和演进过程,设计文档就是最好的参考材料。良好的代码质量有助于避免 contributor 阅读源码时受挫,但是项目固有的复杂度还是需要设计文档来辅助解释。如果代码质量和设计文档都缺位,想要深度参与技术贡献的 contributor 就不得不指望 maintainer 花费大量的时间解释和指导了。这点对于 maintainer 自己也是一样的。当你想要做一个新的功能,如果没有好的技术文档,你也得懵圈,也得拉人反复对齐。

第三点是避免私下讨论。有关项目和 区的讨论,唯一的信源应该是一个公开的渠道。例如,ASF 治下的项目要求所有有效的讨论都应该发生在邮件列表上。例如,大部分托管在 GitHub 上的项目隐含了讨论应该发生在 GitHub 平台上。 区成员可能还会通过其他的沟通渠道辅助交流,例如即时通信软件。但是这些辅助渠道的讨论需要被抄送到唯一信源上才实际生效。这样,contributor 才能在无需了解诸多渠道的前提下有能力获取所有有价值的信息。

这些公开讨论的内容以及表现出来的做事方式,就是 区当中的“活文档”。模仿是人类的天性,如果你希望别人遵循某种做事方式以减少冲突,那么最好以身作则,再带动更多的人跟随。前面讨论 contributor 的参与技巧时候说过,加入 区并首先观察别人是怎么做的,是一种避免浪费时间的好方法。那么与之相对的,maintainer 也要在项目维护和日常交流方面为此提供方便。

Open Communications: as a virtual organization, the ASF requires all communications related to code and decision-making to be publicly accessible to ensure asynchronous collaboration, as necessitated by a globally-distributed community. The Apache Way[12]

第四点是考虑自动化。结构化的流程更容易自动化。当你的流程越来越结构化,那么是时候考虑自动化它了。显然,无需 maintainer 亲自动手的自动化流程能够减轻项目维护的压力。

同样,最好的自动化是符合直觉的。GitHub 平台提供了一系列自动化的支持。尤其是 GitHub Actions[13] 发布以后,自动化的灵活性得到了进一步的提升。利用项目代码托管的平台提供的开箱即用的能力做自动化,能够最大程度的避免各种冲突。

自动化还应该建立在现有的成熟流程上,而不应该凭空生造一个流程。好的案例包括提交文档变更后自动部署文档页面,利用 merge bot 提高 pull requests review 和 merge 的效率等等。

其中,后者的采用是有两面性的。许多代码提交极其活跃的开源 区也仍然不需要引入自动化流程。当然,测试基本是自动化的,至少有脚本。不过 review 和 merge 还是可以人工完成的。我比较认同 merge bot 的地方是有些实现了排队合并功能以及 roll up 打包测试功能。这两个功能在保证合入主分支的代码是基于最新的主分支测试过的前提下,减少了需要进行测试的次数和人为协调的负担。但是,有些 merge bot 强制要求 review 和 merge 走非常严格的审批流程,把这个过程变得复杂不堪,这是我非常反对的。所以在引入 merge bot 之前,请确保你清楚地知道它如何改善协作效率,并保留回滚的能力。

另一个典型的错误案例是 stale bot 的自动关闭功能。真的,没人喜欢这个功能。开发者来到 区是为了和人建立联系,共同开发好的软件,而不是为了被机器人支配。应对 issue 或 PR 的积压问题,首先应该尽可能的及时处理。其次,大部分积压的 issue 是无效的内容,例如愿望清单和模糊的想法,这些只需要快速关闭即可。对于低优先级的 bug issue 的积压,既然问题是实际存在的,也不是 wontfix 的情形,凭什么关掉呢果当前的 maintainers 积极主动地处理 issue 和 PR 还是处理不过来,那么是时候寻找一个新的 maintainer 了。

Users SHALL NOT log feature requests, ideas, suggestions, or any solutions to problems that are not explicitly documented and provable. The ZeroMQ Community[14]

流程自动化的标杆案例包括 Kubernetes 区[15]和 Rust 区[16]。在学习这两个 区的做法的时候,需要强调的是

1.请关注这两个 区为流程自动化投入了多少人力。2.请关注这两个 区是在什么时候引入了何种自动化逻辑。3.请关注这两个 区的成员如何利用自动化流程。4.请关注这两个 区在流程自动化上的异同。5.请关注这两个 区推行流程自动化时的讨论,尤其是争议。6.请勿货物崇拜,直接照抄它们的方案。否则你会死得很惨。

既然 Rust 区都不抄 Kubernetes 区的方案,你为啥贸贸然就要抄/p>

Manage day-to-day events

前面讲的是一些整体的做法,回到每个 maintainer 身上,实际的项目维护工作其实是日常事务。

最常见的问题是开发的风险控制。开源项目通常会有自己的版本发布周期。有时候你希望下个版本能交付某几个关键功能或改进,而这些工作并不都是由你一个人完成。尤其是,你之所以想交付这些变更,是因为公司的要求,而开发团队包括并非公司员工的成员。这个时候就需要你做好项目的风险控制。

从公司员工的角度,我介绍过开源项目和商业公司独立运营的协同模型。运用这个模型,可以把商业上紧急的需求实现在 fork 仓库上,交付 hotfix 应对紧急情况。稍后,把改动 contribute back 到开源项目当中。这样就可以把商业要求和软件开发的工程要求隔离开来,避免向开源 区倾倒粗糙的补丁。Stream Native[17] 就在公司组织下有 Apache Pulsar 的 fork 仓库。我没有仔细研究过他们的具体做法,但是显然他们把一些公司关心的内容都放在 fork 仓库上记录。让上帝的归上帝,凯撒的归凯撒。这是好文明。

如果评估出来更合适的做法是把改动直接做在上游,那么我会建议在需要严格控制风险的情况下,直接由公司员工组成开发团队。当然,这些员工得靠自己的努力在开源 区当中赢得信誉,而不是只根据职位就被允许直接提交代码。如果同样的需求已经有其他团队在做,那么沟通就是必要的。如果信得过这个团队,保持关注并提供帮助即可。否则,可以尝试接管项目开发。Flink 区的 FLIP-85[18] 提案是我和 Uber 的工程师分别独立提出的。经过几轮邮件列表上的讨论,最终由阿里的工程师主导实现。我参与了 review 和提供了部分参考实现。

上面讲的是一个好的案例。其实对于一个活跃的开源 区来说,PR 冲突的情况不会太少,种类也很多。

TiDB 区发生过一起有名的 Xuanwo 事件[19]。完全相同的两个补丁,后提交的反而先被合入,导致先提交的被迫关闭。尤其是这个事件发生在并不繁忙的仓库上,并且两个补丁提交的时间相差一个月。这是一种非常典型的情况,需要 maintainers 保持对项目范围内发生的活动的关注。

Flink 区有不少经典的乐子。FLINK-10052[20] 作为我从 2019 年就和 @lamberken 配合修复完成并经过生产环境验证的高严重性问题,在过去的三年里提交的三个补丁都因为缺乏响应最终没有合并。这也导致不少用户被迫手动打补丁。FLINK-11937[21] 是另一个例子。两家员工提供了不同的方案,其中一方缺少 区话语权,无力单独推进合并,另一方有能力但是无意推进,也不允许其他人推进。同样的案例还有 FLIP-44[22] 和 Queryable State[23] 等等。

Flink 的例子其实证明了商业公司需要通过 fork 仓库的来应对商业需求。另外也可以看到这些讨论的发起人是如何被 stale bot 二次伤害的。

从开源协同的角度,contributor 不是程序,而是真实的人。上面提到的沟通手段,去掉公司员工的背景也同样适用。商业公司要做风险控制,开源 区也是一个组织,也可以做风险控制。只不过,开源 区是一个开放式组织。在这个环境下控制风险的手段不是管控,而是协同。前面讲到的文档和结构化的流程在这里同样可以起作用。信息在 contributor 之间自由流通,就不会有 FUD 产生的伤害。平时保持和其他 contributor 的联系,就能知道当前的工作最应该找谁一起做。

大部分情况下,contributor 是能够自我驱动和自我激励的。他们爆发出的创造力不可小觑。单就时间上的风险而言,如果你在开发文档里明确写下开发周期和发布模型,contributor 是乐于见到自己参与或主导开发的工作随新版本一起发布的。越是自我驱动参与开源 区的 contributor 越重视积累信誉。这个过程中,如果你作为 shepherd 指导或参与进去,只需要切实地关注和解决开发团队成员遇到的困难,并在需要时帮助他们管理好进度。

其他的沟通技巧和 maintainer 的最佳实践这里不再展开。Open Source Guides 提供了这个话题非常有益的补充,推荐延伸阅读。

?Best Practices for Maintainers[24]?Leadership and Governance[25]?Building Welcoming Communities[26]

你不该错过的2021中国开源年度 告,填开源开发者问卷,成为国内开源的见证者

庄表伟:我们需要建立“开放式架构”的思维模式

开源 简介

开源 成立于 2014 年,是由志愿贡献于开源事业的个人成员,依 “贡献、共识、共治” 原则所组成,始终维持厂商中立、公益、非营利的特点,是最早以 “开源治理、国际接轨、 区发展、开源项目” 为使命的开源 区联合体。开源 积极与支持开源的 区、企业以及政府相关单位紧密合作,以 “立足中国、贡献全球” 为愿景,旨在共创健康可持续发展的开源生态,推动中国开源 区成为全球开源体系的积极参与及贡献者。

2017 年,开源 转型为完全由个人成员组成,参照 ASF 等国际顶级开源基金会的治理模式运作。近七年来,链接了数万名开源人,集聚了上千名 区成员及志愿者、海内外数百位讲师,合作了近百家赞助、媒体、 区伙伴。

e27c0239ce5c7dc0b62e2105e044a0ff.gif

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92454 人正在系统学习中

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年10月20日
下一篇 2021年10月20日

相关推荐