上周我们的项目 envd 静悄悄地开源了。
它希望能够帮助算法工程师更好地解决开发环境配置和管理的问题。数据科学家和算法工程师们平时经常为了配置开发环境需要跟复杂的 shell 脚本、conda 环境、CUDA 版本、Dockerfile、乃至于 Kubernetes 的配置打交道。envd 希望能够帮助算法工程师更好地解决底层基础设施带来的复杂度,让开发变得更加简单。
具体的项目介绍等项目更加成熟一些再来分享,今天想讨论的是在开源项目中的敏捷开发探索。我们认为除了源代码之外,一个开源项目本身的开发过程包括需求的讨论与确定、issue 的排期、roadmap 的制定等等,也应该是开源的。这不仅可以帮助用户更好地了解项目,也能够促进社区的发展,让对项目感兴趣的朋友们能够更加具有参与感。
这也是我之前在参与一些由公司维护的开源项目时感觉体验比较不好的地方。对于公司主导的开源项目而言,开发过程通常与传统的软件开发过程一样,是封闭的,也是外部贡献者难以了解到的。尽管这些项目的社区氛围可能也不会太差,但是总有一种淡淡的疏离感,让我觉得我是“局外人”。
所以今天想介绍一下,作为开源项目的维护团队,我们在努力确保贡献者的贡献体验的前提下,是如何魔改 Scrum 实践来保证开源项目开发的质量和速度的问题。也就是像标题一样,如何千方百计地讨好 🖥️ 前的“你”,项目的潜在贡献者们。
俗话说的好,一千个人眼里有一千种敏捷实践。在这个过程中我们也想找一些比较成功的开源项目进行参考,但是鲜有项目对自己的开发过程有书面的讨论或者文章。这次的分享也希望能够抛砖引玉,向各位学习。
开源项目有什么不一样
让我们回到问题的开始,无论项目的维护团队是怎样管理自己的开发流程的,我们一定不希望这一切是牺牲了贡献者的贡献体验的。这也是开源项目与闭源的项目开发最大的区别之一。如果是闭源的项目,那么开发的过程只需要能够让项目的团队和干系人(Stakeholder)满意就好了。
而对于一个开源项目而言,社区是非常重要的。所以一切软件工程的实践都应该考虑到社区这一特别的因素。从贡献者的角度而言,一个体验良好的开源项目,可以让我们可以在不关心项目维护的脏活累活(dirty work)的前提下,流畅地与项目的贡献者讨论自己感兴趣的特性或问题,进而为项目进行贡献。这就对开发过程提出了新的挑战。
state-of-art
在开发 envd 之前,我也与一些国内外开源项目的维护者们交流了一下他们在项目中都是如何管理开发进度的。总结下来可以分为两个主要的类别。并不完全准确,但可管中窥豹。
第一类是主要由社区驱动的项目。如果是比较成熟的社区驱动的项目,比如 Processing,通常会由社区中的 PM(开源社区中也有 PM 的角色哦)或者维护者确定下一个版本的期望功能与发布日期。接下来不同模块的维护者会进一步细化,确定自己维护的模块相关的特性和发布时间。这样的好处是贡献者的体验是良好的,与项目有关的所有讨论都是公开的。但是缺点也有一些,最主要的是时间很难把控。
第二类是由公司内部团队驱动的项目。这些项目并不一定不在基金会里,捐献给基金会的项目也可能是公司主导,尤其在不少基金会的捐献门槛越来越低的当下(个人观察,不一定准确)。如果实践比较好,那么可能项目会给出 roadmap,但是通常它的开发过程是不对外公开的。维护者内部的团队可能采取各种各样的开发实践,但是我们不得而知。
选择合适的软件工具
以我自己的理解,这两类不同的项目最大的区别,在于维护团队是一个非常相近的团队,还是一个分布式的团队。一个团队成员非常相近,都坐在相邻的工位里,物理的距离导致大家线下交流的成本实在太低了,那么很多事情确实没有动力去搬到线上以公开的方式进行。
从这个角度来说,第一个月的 envd 也属于是团队成员非常相近的状态。那时候只有我和金晶。而且那时候也在闭源开发,所以基本所有的开发过程都是私下进行的。后来随着一些同样对 envd 感兴趣的朋友以开源协作的方式加入,我们也开始了探索一些好的实践。
我们试用了不少朋友推荐的项目管理工具,这些工具也内化了一些开发过程的最佳实践,比如 linear.app 等。linear.app 对于软件开发过程有自己非常独到的理解,也就是 Linear Method。linear.app 可以当做是这一想法的具象化实现。
我非常喜欢 linear.app,但是如果要使用它,需要在当前的 workspace 下注册,才能看到对应的 issue 等。目前还是不支持 GitHub 登录的,因此并不合适。
后来跟素未谋面的贴心网友 xuanwo 交流,他推荐了 GitHub Projects Beta,这也是我们最终在工具层面上的选择。相比于 GitHub Projects Classic,GitHub Projects Beta 大大地增强了扩展性。在之前的 Projects 里,只有 kanban 的可视化方式。Projects Beta 里不止支持 kanban,还可以以表格的方式展示,这样对于 product backlog 的可视化就更加友好一些。
目前它还缺乏一些比较重要的特性,比如燃尽图等进度的可视化展示等。不过它的优势也非常明显:GitHub Native。它就像 GitHub Action 等 GitHub 提供的其他能力一样,与 GitHub 原生集成的体验,是难以拒绝的,尤其是对于早期的开源项目而言。
合适的开发过程实践
软件只是工具,我们还是要寻找适合的开发过程的实践。因为之前只有过 scrum 的经验,所以我们基于 scrum,结合我们对于开源项目和社区的理解,摸着石头过河,形成了一个可能已经完全称不上是 scrum 的开发过程实践。不管黑猫白猫,能捉老鼠的就是好猫。接下来就简单介绍一下我们的开发过程,希望能够抛砖引玉,学习一下好的实践是什么样的。
精简 Sprint 会议
在一次迭代开始前,我们会组织一次线上的视频会议。我们把它成为 Sprint Retrospective(Sprint 回顾会议)。但是,它的意义已经不只是回顾了,我们把 Sprint Planning、Sprint Review 和 Retrospective 合并到了一起。之所以如此,主要是有这些原因:
首先,我们的团队规模目前非常小,一直到现在都只有两个全职投入的工程师(马上就有第三个了!还是个大腿)。而且目前由于一些特殊原因,全职投入的两个工程师有非常多的会议时间。所以我们希望开发过程本身带来的同步成本尽可能地低。
其次,我们的迭代周期非常短。我们以一周为一个迭代周期。在最早时我们实验了两周一次的迭代速度,但是明显感觉不能跟上我们的需求变化。我们的项目本身横跨容器和机器学习领域,从技术选型到产品设计的不确定性都很高。而一周的迭代周期意味着每周都会进行 n 次与 sprint 相关的会议。缩小 n 的规模能够很大地降低事务性管理的成本。
那么,在我们精简化的 Retro 会议上,我们首先会回顾上一个 sprint 完成的 issue。目前我们通过 GitHub Discussion 来跟踪这个过程。比如 Weekly update on envd (2022.06.13-2022.06.17):
这个过程会花费大约 5-10 分钟的时间。接下来,我们会就这一次迭代中遇到的问题和风险进行讨论。这就是标准的 Retro 实践了。我们会统计一下完成的故事点的情况,随后总结一下过程里的问题。👇🏻下面是一个示例:
这个过程会花费大约 5-10 分钟的时间。最后我们会确定下一个迭代要做的事情,这个过程也是花时间最多的,可能要花费 20-30 分钟的时间。我们目前是不会提前预估 product backlog 里的需求所需时间的,因此在 retro 的时候,我们就需要确定要做哪些需求,以及他们对应的故事点是多少。在确定每个 sprint 要处理的需求和事务时,三个来源会被主要考虑:
- 首先是用户社区里呼声最高的问题,我们会根据问题收到的 👍 数量进行排序。比如之前对于 Julia 语言支持的呼声特别高,我们就会以非常高的优先级支持这样的需求。
- 其次是我们的企业用户提出的问题。目前有一些公司在试过 envd 后反馈不错,有意向把 envd 集成到公司内部的系统中,提高算法工程师在开发过程中的使用体验。但是在集成中会遇到一些只有企业用户才会遇到的问题,比如怎样与 Kubernetes 进行集成等。那么这些问题也是会以高优先级出现在 sprint backlog 里。
- 最后是工程师觉得我们应该做的事情。除了社区和企业用户的需求外,还有不少功能是需要项目维护者去思考设计的。
在把高优先级的需求和事务加入到 sprint backlog 中后,我们会预估一下它们的故事点,这个就与传统的估算方式并无二致。我们选定了一个之前完成过的需求作为单位,来估计新的需求或事务合理的故事点。那么接下来,如果一次迭代可以完成的故事点数没有被用尽,我们会再在 product backlog 里寻找一些优先级相对不高但是也有必要早点完成的工作,或者是代码重构的事务进去。
这就是我们一周一次的 retro 会议主要做的事情,一般一次 retro 大约花费 40-60 分钟。我们会把 retro 安排在周五的下午,作为一个迭代的结束,在最后一个工作日总结完,可以快乐地开始周末生活(开始下一个迭代的开发生活)
舍弃 daily scrum
在迭代过程中,传统的 daily scrum(每日站会)是一个我个人非常不喜欢的环节。
首先它会打断开发思路。站会需要大家同步地介绍自己的工作进展,因此需要约定一个大家都有空闲的时间,比如早上 10 点。但是有的团队成员早上 7 点已经开始工作了,早上无人打扰,在 10 点的时候可能正在写代码的兴头上。这时去参加一个哪怕只有 5 分钟的会议,也会非常影响状态。其次 daily scrum 在一些情况下,会给人一种汇报工作的感觉,而不是我们作为一组有共同目标(愿景)的人,在高度协作的环境中共事。
为此我们也学习了一些 daily scrum 的变种,其中我觉得比较合理的是以 backlog 中的故事为维度,而不以人为维度进行 daily scrum。
我们读过Jeff Sutherland的论文https://jeffsutherland.com/ScrumMetricsHICSS2013BWSubmissionFinal.pdf 并且非常喜欢关于改变每日站会的提议。Jeff提议在每日站会上检查Sprint Backlog中每个故事的功能,而不是每个团队成员的。作为教练,我留意到这篇论文,或许团队有兴趣学习一下。事实上,团队很高兴有这个提议,于是团队落实了行动计划,以在下一个迭代来验证这个变化。
改变的结果是,团队的效率几乎马上得到提升。假设这是由于这样的事实导致的,当讨论故事的时候参与的每个人都发言,从而提高了专注力。相比之下,传统的每日站会经常有干扰。比如,如果两个开发人员做同一个故事,团队不得不等到两个人在不同的回合中都说完了,才能充分地理解这个故事过去和将来的行动。
更重要的是,对故事专注力的改变,需要整个团队强化正在构建产品的知识,因此现在团队专心在产品上,而不是开发人员的任务。每个开发人员说话不做限制的事实,允许其他团队成员(他们可能在自己的故事中受阻,或只是完成了一个故事)尝试一起合作关掉正在讨论的故事,而不是去认领一个新的故事。
我们又基于这一变种进行了大幅度的简化,我们并没有同步的 daily scrum 会议。而是会在每天开始前,在正在处理的 issue 里评论一下当前的进展以及可能遇到的风险。这样的更新是公开的,社区中如果有人感兴趣,也可以一起帮忙与参与。同时我们也对进度有所把握,进展可以在 issue 内跟踪到。而且也可以照顾到不同成员的作息规律,尽可能少引入每天一次的会议,把时间花在正经地方。
结
我们的实践差不多就是如此了。它目前能够让我们花尽可能少的成本(每周一小时的同步线上会议)完成项目管理和开发过程跟踪的工作,同时也保证了贡献者和社区用户的贡献和使用体验。不过目前还是有一些问题:
- 一个小时还是太久了,我们还在探索有没有更异步的方式节省更多时间。比如通过 weekly update 的更新,省去每个 sprint 回顾完成的故事的时间等。
- 仍然不是完全公开的。每周一次的线上会议还是私下进行的,主要是涉及到一些企业用户相关的敏感信息。后面会探索如何在保证企业用户的隐私的前提下,让项目管理变得更加开放。项目管理和开发过程管理可能不是社区用户所关心的内容,但是我们还是认为一个开放的机制是对社区有好处的。
开源项目的项目管理是一个非常值得研究的工程话题,我们也只能抛砖引玉地介绍一下自己的实践,希望对你有所帮助。
License
- This article is licensed under CC BY-NC-SA 3.0.
- Please contact me for commercial use.