如何优雅地参与开源开发?

文: 胡渊鸣 (yuanming-hu),2022 年 3 月

写在前面:最近疫情形势又逐渐紧张起来。我本人也因为一两周前去上海出差,回到北京后也被社区要求在家隔离。因祸得福,多出了一些时间思考、一个人想安静地写一些文章。打开知乎草稿箱,翻到这篇 2020 年中开始写的文章,居然因为种种原因鸽了快两年都没写完。看着窗外阳光明媚,门口贴着一纸封条,仿佛回到了 2020 年在波士顿躲新冠期间每天和网友们(比如当时同样悲惨地在日本东京隔离的 @k-ye)一起愉快地写 Taichi 的时光。既然出不去,干脆把文章这篇写完吧!也希望这波疫情能够快点过去,也祝大家都能够身体健康、早日恢复平淡而珍贵的正常生活。

Taichi 开源社区一直承蒙大家的关注,我们也在努力摸索如何能将社区建设得更好。本文为一系列中的第一篇(希望以后不要鸽…),主要聊聊参与开源社区之前需要了解的一些基本知识和跨国、跨文化团队合作技巧。部分内容来自 Taichi 的贡献者指南:

Taichi contribution guidelines

(基本上是 2020 年的时候写的了,居然一直用到现在… 我们社区也算不上最完善、成熟的社区,这些指南也仅仅是我们在实践中总结出的小 tips,本文权当抛砖引玉,欢迎各位开源大佬批评指正。)

Intro

和小规模兴趣项目 (hobby project) 不一样,开源项目随着开发者社区的成长,不可避免地会需要标准化工作流程与合作方式。对于合作方式的共识对于开源社区成员之间高效合作是非常必要的,但是刚刚加入开源社区的同学可能也会因为对社区规则和文化的不熟悉,对参与开源望而却步。

Taichi 项目的开发始于清华大学紫荆学生公寓 2 号楼。项目由我于 2016 年在 GitHub 以 MIT 协议的开源软件,至今已经过去 6 个年头,其源代码也会在未来永远保持公开。目前 Taichi 由全球近 200 名开发者共同开发、维护。既然是社区的项目,那么维护一个互相尊重、让人愿意参与的社区就是至关重要的。本文主要聊聊如何优雅地参与开源开发。

不同的社区工作流程上稍有差别,不过我相信本文大部分内容对参与别的开源社区、甚至日常生活中的别的类型的团队合作也有帮助。本文的适用范围既包括开源社区,也包括各类需要团队合作(特别是跨国、跨文化)的场景。

本文主要会浅浅地讨论三个问题:

  1. 为什么参与开源开发?
  2. (Taichi) 开源社区的文化是什么样的?
  3. 在开源社区如何做到有效沟通?

为什么参与开源开发?

不可否认,参与开源项目开发会占用很多原本可以用来打游戏、看动漫等娱乐项目的时间,通常也不会获得物质方面的回报。即便如此,还是有很多同学乐于参加开源开发,原因通常有以下几点:

提高编程能力。这一点大概是最为直接的收获了。开源社区的每一份贡献都会收到其他社区成员的代码评审 (Code review)。在这个过程中,能够收获到很多在学校里学不到的编程经验。

一些刚从学校编程作业转战 Taichi 社区的同学,第一个 PR 的几乎每一行代码都会因为规范性有待提升收到修改意见,一个 PR 里面有超过 50 个修改意见也不少见。千万不要受到打击,reviewer 只是在帮忙 🙂 但是他们在后续的 PR 中,代码质量就会有很大改进。这其实是一个很好的学习过程。事实上,在开源社区学到这一课,远比上班第一天被 leader 上这一课要好的多 🙂

在 Taichi 开源的几年之中,我们也见证了很多社区参与者的快速成长。社区 maintainers 也在一个个 PR 中投入了大量的精力,与开发者一起成长。这本质上是一种互惠互利的过程,而开源社区本身也在这种双向的发展过程中逐渐壮大。

别怕,社区的同学带你一起学… (source: reddit)

通过设计决策解决实际问题的能力。俗话说“小孩子才做选择,大人根本没得选。” 稍微复杂一些的实际问题中完美的解法往往是不存在的。悲观点说,设计决策就是权衡利弊,特别是项目具备一定规模以后。软件开发者需要在 “这也不行,那也不行” 中找出最不差的解决方案,从全局视角以最为实用主义(pragmatic)的精神进行设计,从而 解决问题。即使在开源社区,要真正做出有人关注的软件,大家通常想的也是解决问题,而不是炫技。

领域特定知识。在 Taichi 社区主要的领域特定知识是编译器、计算机图形学、高性能计算等等。不同的社区有不同的领域特定知识,如 TiDB 社区很明显就是围绕数据库展开的。毋庸置疑,每个社区都聚集着相应领域的大佬。

团队合作能力。我们汉字文化圈自古以来就强调集体为先,但是教育中却相对缺乏关于合作的教育(毕竟各种考试的时候一定是单兵作战嘛)。这意味着我们在 GitHub 上与世界各地的伙伴合作时,更要注意充分沟通、有效合作。

朋友。比如 Taichi 开发者社区中既有潜力无限的中学生,也有身经百战的工程师。其中不乏清华/北大/MIT/CMU 等学校的本科生、研究生和研究人员、Google、Facebook 的专业软件工程师、IOI/NOI 金牌获得者等等。“三人行必有我师”,GitHub 作为 “全球最大(同性)交友平台” ,自然有不少自带闪光点的程序猿、程序媛出没,与他们合作本身就是一种乐趣。

我和匡冶(@k-ye)就是在 GitHub 上认识的,经过一年时间我们在 GitHub 上一起编写了大量代码,建立了深厚的信任,最后决定出来创业,在此之前我们线下没有见过一面。Taichi 社区早期的绝大多数开发者都相互之间成了很好的朋友。毕竟程序员最喜欢的就是以码会友嘛。

成就感。为流行的开源项目贡献代码,本身就是一种有成就感的事情,因为你的代码会被大量的用户所使用,为社会创造出价值。

从实用主义的角度来说,如果成为知名开源项目的贡献者,这个经历会成为简历上的一个亮点。我相信不少公司的技术团队在招聘的时候是会看应聘者的 GitHub 的。我们就收到过一份海外图形学研究者的简历上赫然写着 “给 Taichi 社区开过 30 多个 issues。”


开源社区的文化

不同的开源社区有不同的文化,但是 同理心、相互尊重、坦诚交流 可能是开源文化中很重要的一点,也在很多社区被反复提及。

首先要明确的是,开源社区其实并 没有 强制社区参与者回复 issue、review PR、merge PR 的能力,因为绝大多数贡献者都是被热爱驱动来参与社区贡献的。即使项目的原作者,往往也有自己的本职工作(比如我在开发 Taichi 的时候是在校学生),除了对项目和社区本身的热爱之外,没有人能够强制他们参与开源活动。

很多开发者开发开源项目也只是为了在工作之余做一些自己真正感兴趣的事情,获得成就感。当然,对于项目的 “亲生父母” 来说,开源项目往往倾注了他们大量的心血,他们也选择了为社区 “捐出” 代码,出于责任心也会把项目维护好,为社区留下一个好项目。

在这个前提之下,维护一个让人能够乐在其中、身心愉快的社区至关重要,甚至直接影响到社区的发展:谁愿意在自己原本可以自由支配的时间中,参与一个自己不那么喜欢的社区呢?


具体来说,类似其他开源社区,在 Taichi 社区我们会遵循如下文化:

团队为先。Again,开源的软件开发与单兵作战式的小项目有所不同,往往需要多考虑合作者的感受,而不能只顾自己“写得爽”。某种意义上说,代码是写给别的程序员看的,而不是写给自己或者机器看的。前者是专业软件开发的指导思想,后者是在学校或业余软件开发的指导思想。虽然两种指导思想都在各自的领域解决了问题,没有高下之分。但是如果希望将自己喜欢的编程作为安身立命之本,特别是要参与开源社区、和别的开发者合作,不妨在编程的时候注重代码质量。这其中就包括遵循命名规范、代码风格,编写清晰可读的 PR 描述和 commit message 等。

质量大于数量,珍惜社区资源。Reviewer 的时间就是社区最宝贵的资源之一,因此在 PR 被要求修改的时候尽量一步到位。举个例子, review 提出修改意见 apple 要换成 banana ,结果代码里改了,文档没改;又 review 一轮,文档改了注释没改;又 review 一轮,注释改了文件名标题没改。长此以往,reviewer 内心也很崩溃,很快就不乐意继续主动 review 你以后的 PR 了。(“社区还有这么多有意思的事情可以做,为啥要在一棵树上吊死呢?”)

谦逊、包容、冷静、理性,尊重社区的每一位成员。 有话好好说 🙂 极端情绪、语言大多数情况下是不必要的。开源社区参与者就事论事,基于事实进行理性讨论,而不是诉诸情感。千万不要因为一些很小的分歧就中伤、攻击其他社区成员。实际上,任何形式的人身攻击(不管是社区内还是社区外),都是不可接受的。这一点几乎所有开源社区的 Code of conduct 都会提及。

礼貌、有效地沟通。进行开发之前,需要与社区(通常是相关的 maintainer)及时沟通,这样才能避免重复开发、防止误入歧途,最好地利用自己和社区的宝贵时间。这一点文章后续也会提到。

充分讨论,尊重决策机制。某些时候做出决定本身比决定的内容更重要。与其无止境地争执,不如在有限的信息下基于决策机制勇敢决策。独断制,如 Linus 之于 Linux Kernel、退休前的 Guido 之于 Python;committee 制等等都是好的决策机制。这里无关独裁与民主孰优孰劣:无论如何一定要有一个最终拍板(并为结果负责)的人或团体来推动决策的进行,不然任何事情都会止步不前。

我作为 Taichi 项目原作者和目前的主要 maintainers 之一,有构建、维护良好社区秩序和文化的职责,因此保留关闭(或要求修改)不友好或不符合社区文化、发展路径的 Issue / PR / comment 的权力。当然,迫不得已使用这些权力对于 maintainer 来说往往也是比较痛苦的过程,属于开源活动之中最不愉快、但又不得不面对的事情之一。和其他项目的维护者一样,我希望这些权力永远不被使用 🙂

参与开源社区绝大多数时候是非常让人享受的过程,其中与社区其他开发者、用户的交互扮演了重要角色。有效的沟通其实还是需要不少技巧的,下面就这一点展开谈谈。


与社区的有效沟通

了解了参与开源的意义、开源社区的文化,应该不少同学都对加入开源社区有了一定的兴趣,也期待能够为开源软件提交自己的代码,造福社区和用户。在开源社区,有效沟通的能力是和技术实现能力同等重要的。只有掌握了沟通技巧,才能确保自己的参与方式在正确的道路上,才能确保自己付出的努力最终能够成为开源软件的一部分。因此这部分值得单独讨论。

开源项目的开发往往是通过提交 Pull request (PR) 来实现的。一个 PR 说白了就是一个代码片段,有的地方也叫做 Merge request (MR)。每个 PR 都会被 reviewer 评审,质量合格、符合社区 roadmap 的 PR 就会被合并到代码的(主)分支中,成为一个 commit。这些概念我会在下一篇文章中详细介绍。这里主要讲讲有效沟通在开源社区的重要性。

沟通技巧

有效沟通的最重要的一点是:应该尽可能站在读者(而不是写者)的角度考虑表达方式。比如:

  • 对方能否理解我的表达?(准确)
  • 我的表达是否会冒犯对方?(礼貌)
  • 我的表达是否对解决问题有帮助?(建设性)
  • 进阶技巧:对方是否容易回答我的问题?(在自己这边预先进行充分的思考,不为难对方)

常见缩略语:

  • LGTM: looks good to me (“看起来好对我”/ “我觉得这看起来不错”,一般用于表示批准PR)
  • SGTM: sounds good to me (“听起来好对我”/ “我觉得这听起来不错”,一般用于表示赞同观点)
  • IIUC: if I understand correctly (“如果我理解正确的话”,表示略微弱化结论)
  • IIRC: if I remember correctly (“如果我记得对的话”,表示略微弱化结论)

值得注意的是,在使用别的缩略语之前,请确认它是否是英语环境中广泛接受的缩略语。通常没有必要发明新的缩略语,因为那样做只会让读者感到困惑,并不能让沟通更有效。每一位社区成员都应该明确的是,我们打了多少字不重要,重要的是其中有多少能够被读者理解和接受。

Taichi 社区的贡献者来自地球上的各个角落,大家都用英语沟通。这里的一个技巧是使用一个 spellchecker。(我一般使用 Grammarly,如果大家有别的推荐的 spellchecker 欢迎在评论中指出。谢谢!)实际上,即使是 native speaker 也需要 spellchecker。

及时和社区交流

大部分情况下,及时和社区交流能够消除很多误解。开 PR 的大忌,就是看到社区用户或者自己有需求,就开始自己一声不吭地暗暗开发一个大功能,不和社区讨论,几天之后开出一个大 PR。开动之前至少要和社区打声招呼呀,哈哈 :-)

事实上这样不但不能给社区一个”惊喜“,反而会导致 PR 难以被 review、无法被 merge。这种 “憋大招”、只顾自己写得爽的参与方式,往往是不可取的。这样事情经常在各种社区发生,是一个常见的误区,因此值得仔细讨论。比如,Linux Fundation 就专门讨论过这个问题:

Include the community early and often. Some organizations make the mistake of developing big chunks of code in house and then dumping them into the open source project, which is almost never seen as a positive way to engage with the community. The reality is that open source projects can be complex, and what seems like an obvious change might have far reaching side effects in other parts of the project. Any significant change is likely to require some community discussion before it moves to implementation to make sure that there are no side effects and that the solution is aligned with the broader goals for the project. While you discuss it with the community, it can help to focus on the problem, rather than a specific solution, before you invest too much time in the creation of a body of code. (See Jon Corbet’s guide on How to Participate in the Linux Kernel Community)

翻译成中文:(大意)

(贡献者应该)尽早和社区建立关系。很多组织和贡献者会犯的错误,是闭门造车开发大量的代码,然后把它们 “倾倒” 进开源项目。这几乎从来不被认为是参与社区的正确方式。事实上,开源项目往往比较复杂,即使是看起来很显然的改动也会对项目其他部分产生深远的影响。任何较大的改动往往偶需要先和社区讨论好,再开始实现,以确保改动没有副作用并且和项目更长远的目标所吻合。和社区讨论的过程也能帮助开发者们专注于问题本身而不是一个解法,这可以有效地防止开发者们投入太多(无效的)时间编写一大段代码。

刨去一次提交大量代码难以 review、保证正确性以外,这种独自开发的行为本质上和 ”开源“ 的原则是矛盾的。(感谢 tison 的博客指引我到这段经典的话,很推荐对开源有兴趣的同学阅读 tison 的文章:https://tisonkun.org/

遇到这样的 PR,maintainer 也会被迫处于一个三难的境地。他们

  1. 要么花费大量的时间和精力去和 PR author 沟通来确保 PR 内容符合项目未来发展的蓝图;
  2. 要么不情愿地合并偏离开发路线的 PR;
  3. 要么直截了当地说明 “请按照社区的开发规则来进行开发以确保项目的健康发展”。

不论是哪种情况,对于参与者的体验都是有损害的。我们社区的 maintainers 通常比较 nice,不好意思拒绝别人,因此通常会采用前两种方式处理,但这样往往会伤害 maintainers 的开源体验(别忘了 maintainers 自己也是开源贡献者)、使得项目偏离既定的发展路线。因此,作为开发者应当做好有效的沟通,才能最大程度上用好自己宝贵的时间和能力。这也是同理心的体现之一。

最后,为了开源项目的健康发展,maintainer 必须有所判断、有所取舍。不少 PR 注定是要面临无法被 merge、 被 close 的命运。这在每个社区都是很正常的事情。Maintainer 必须有大局意识,如果真的遇到了上述情况,不能为了一个开发者的感受牺牲项目长远的发展,这一点也几乎是所有成熟开源社区的共识。Maintainer 要有明确的方向感,不能为了短期的情感被开发者带偏。当然,只要大家都遵守合理的规则(比如做到有效沟通),这样的情况就会很少发生。另外,作为开源贡献者,也完全有 fork 出一个自己版本的自由。

技术好当然是很重要的,但是确保项目能够沿着正确的方向发展,或许更加重要…

总结

开源社区因为贡献者出于兴趣参与,没有强制机制,所以理想中每一位成员都应该维护社区的参与体验,才能让社区健康发展。这其中,同理心是开源社区正常运行的关键。推己及人,将心比心:你怎么对待别人,别人也会倾向于以同样的方式对待你。社区成员应当保持积极、友好,珍惜他人的时间。同时也要对社区伙伴有足够的包容(别忘了很多同学有自己的主要工作)。

当然,Taichi 主仓库目前也就 166 个开发者,相对来说还不算是特别大的社区。我们也在不断努力提高开源社区的质量,也欢迎大家积极参与进来,和我们一起成长。也欢迎其他开源社区的小伙伴来我们社区逛逛。


扩展阅读

不知不觉居然写了个万字长文,其实还有很多内容没有涉及到。如果想进一步了解开源社区,在知乎、各个博客上也有很多很棒的文章,这里列举一些。其中的不少对本文的撰写也起到了很大的启发作用:

本系列的下一篇文章会详细讲解 Issue、Pull request (PR)、Code review、Continuous integration (CI) 等入门开源社区常见的概念,并手把手带大家在 Taichi 社区 开一个简单的 PR。


最后也介绍一下 Taichi。Taichi 是一个嵌入在 Python 中的开源并行编程语言,面向 GPGPU 等并行计算应用,力求实现优雅开发,高效运行,随处部署。更多技术介绍可以参见 GitHub网站。想了解 Taichi 背后的故事,请移步99行代码的《冰雪奇缘》

还没有用过 Taichi 的同学欢迎安装 Taichi:

python3 -m pip install --upgrade taichi

并执行

python3 -m taichi gallery

体验各种 Taichi demo 呀!(需要最新的 v0.9.2 版本)

0.9.2 版本的 gallery 功能。点击即可运行各种 Taichi demo 并打印相关代码到终端。

如果你已经迫不及待想要来一起写代码了,最近手上还真有一个适合 CUDA/LLVM 玩家上手的小任务欢迎大家来搞一搞:[RFC] [SIMT] Add CUDA warp-level intrinsics to Taichi · Issue #4631 · taichi-dev/taichi

(内容:给 Taichi 加入 CUDA warp-level intrinsics,每个 PR 应该 10-30 行代码就能写完。第一次贡献 PR 的同学会获得 Taichi 周边哦!)

也可以关注一下我们的 good-first-issueswelcome-contribution 🙂

Most importantly, have fun! 🙂

来源:知乎 www.zhihu.com

作者:知乎用户(登录查看详情)

【知乎日报】千万用户的选择,做朋友圈里的新鲜事分享大牛。
点击下载