中文摘要:Linux从诞生至今,已经快有30年了。这期间Linux一直延续着通过邮件来提交变更、审查、讨论直至批准的研发过程,这一流程非常费时费力,不仅成为新人的进入门槛,也成了可持续生产的障碍。那么,为什么Linux一直要坚持遵循这一过程呢,它能带来什么好处?存在哪些弊端?有什么解决办法吗?
正文:
本文最初发布于medium,经原作者授权由InfoQ中文站翻译并分享。
Linux从诞生至今,已经快有30年了。在早期,由Linus自己手工管理大家贡献的代码,不借助任何版本控制系统。而现在,已经使用git了。
然而,有一件事在整个过程中却从来都没有变过:代码被发送到一个(或多个)邮件列表中,然后直到做出最终判定之前,要进行一系列的审查和讨论。
尽管Linux是成功的,但这一过程却一直饱受诟病。微软的Sarah Novotny最近在社交媒体上发表了一篇文章,称Linux所使用的协作工具早已过时,如果这个社区想要吸引新鲜血液,最好换掉这些工具。
我认为我对此有一定的发言权:近十年来,我就在用类似的工作流程为Linux和其他项目编写代码。就职于Red Hat的时候,我为core x86基础设施、KVM管理程序和QEMU、Xen管理程序和其他系统贡献过代码。虽然,我因为把主要精力投入到了Seastar C++框架和ScyllaDB数据库上,在大约7年的时间里没有过多接触过Linux,但它们采用的开放方式却与Linux非常相似。现在我是一名Datadog公司的工程师,该公司遵循的流程与其他网络公司几乎完全不同。
那么我的立场是什么呢?首先,我的态度很明确:我不喜欢Linux的开发过程。我坚信,这一过程不仅是进入的门槛,是可持续生产的障碍(尽管并不是因为电子邮件),也是令人产生沮丧情绪的源头。我不打算在任何项目中遵循这一流程,如果我能决定这些项目怎么做的话。
但与此同时,似乎许多对Linux过程持批评态度的人认为,它的捍卫者之所以如此顽固地墨守成规,只是因为Linux充斥着一些不愿做出改变的坚守者。尽管我相信的确存在这样一些个别人,但事实上真正的原因并非如此。Linux所遵循的开发过程提供了一些独一无二的重要优势,这些优势对于任何其他组织也均有裨益。
除电子邮件以外,任何其他自以为是的工具化都会迫使Linux抛弃这些好处,大家不愿意舍弃的是这些好处,而不是电子邮件。工具化应可以降低进入的门槛,改正过程中那些令人沮丧的方面,同时能够让组织实现Linux所具备的真正推进软件开发的好处。
这样的优势有很多,但是由于时间的关系,我会着重来谈其中我认为最重要的那一个。我将尽最大努力向你解释它是什么,为什么尽管它有优点却又如此令人沮丧,为什么它只是对其他组织有益,但对Linux却至关重要。
Linux有一条规则,要求将变更的代码拆分为单独的补丁。每个补丁都必须做一件事,且只做一件事,而且每个补丁都应该有自己的描述性提交消息。提交消息比代码变更本身还要长得多的情况早已司空见惯。
透过这个例子,可以发现大多数组织往往忽视了什么。在GitHub上,我看到大多数现代项目的提交信息都类似于“8月25日,检查点”,或者稍微好一点(但也仅仅稍微好一点)的是“实现X函数”。如果别人之后需要查看这些代码,将无法理解为什么要按照当时的方式来完成这个变更。有些缺陷非常微妙,而且很容易重复出现。只看简短的、非描述性的提交消息,不一定有人能知道在什么条件下会出现错误。
举个简单的例子,看看我的好朋友Johannes Weiner的Linux提交,不难想象,一些其他项目可能只会草草写下“删除警告”之类的。而再看看这段信息,阅读它我能知道为什么删除这些警告很安全(说明了当前情况很安全的原因),以及如果我在未来更改这段代码时应该要做些什么。我相信,很多组织也会有人这么做。但是由于Linux过程是强制执行的,所以我百分百确信通过阅读提交消息能理解本次变更的所有相关信息。如果我们讨论的是一个bug,我就会知道它出现在哪些系统,发生在什么条件下,为什么没有影响到其他的系统,以及我应该做些什么来避免再次犯同样的错误。
无论对于哪个组织,这都是值得的:它能使别人(包括将来的你)更容易理解为什么要做这个变更,为什么代码以这种方式运转,这可以使新人更快速地成长,可以防止重复出现相同的Bug,减少因偷偷挟带无关的代码而造成破坏的风险。
而对于Linux来说,这却是至关重要的,原因有两个:
许多现代线上公司不需要保持产品线的兼容性,通常不存在Backport的问题。他们只关心交付即可。但是如果涉及到Backport,事情就变得比较复杂了。开发人员(很可能不是作者)可能必须要选择如何对代码进行微调,以适应略有不同的、较旧的代码库。若要将风险降至最低,可以只Backport大变更的某些部分,大家通常都这么做。假设,一个2,000行的代码变更中有5行修复了一个bug。再设,该bug的修复可能是在API重构之后。你是愿意基于一个大变更来做Backport呢,还是愿意基于一个文档非常完善、描述得很充分、做过合理拆分的补丁来做Backport呢?作为一个做过无数次Backport的人,我很清楚我的选择是什么。
Backport还是不Backport呢,它有好处,但也伴随着阶梯式的成本。现在程序员不仅要关心代码,而且还要关心如何重组和调整这些代码。
其中有一些重组很容易:你可以使用git add -p选择哪些部分可以添加到每个变更中。当开始发现代码片段之间出现循环依赖时,就变得有点复杂了。假设有一个函数,它返回的对象类型是以后才引入的。那么你不得不添加一些代码处理这一情况,这些代码最终并不会出现在这个项目中,它们只是作为临时粘合剂。
这一切的一切都很令人沮丧,但却也不是不可避免。假设,你将所有工作都进行了完美分解,使其很容易得以处理。当人们进行代码审查时,就开始出现真正的问题了。任何组织做代码审查都大同小异。大家阅读代码并提出修改建议(或要求)。
假设,评审意见是我在第一次变更中添加的方法应该有一个额外的参数。再假设,我在以后的所有补丁中都使用了这个方法。
现在我不得不回到第一个补丁添加参数,于是,所有后续的补丁都无法正常使用了。现在我不仅要开动脑筋找出原因,还要手动修正所有的错误。如果我以前已经测试过某个补丁了,那么现在那个测试已经无效了,我必须重新测试。
重组只是一个小问题。但为现有工作重新建立基线是一个真正的大问题。
我希望Linux社区和朋友们能够理解:显然,这么做并不是不行。但如果这都不算是进入的门槛,我就不知道什么才是了。大家不得不花费时间、精力、脑力和计算机来重组、重写、返工,没有人想做这些事情。我还发现有时大家会争论:“……但对于优秀的程序员来说会没有问题的”或者“但是它迫使你以这种或那种方式思考,优秀的程序员应该这么思考”,这种观点脱离实际毫无用处:上帝,我刚才已经承认了这个方法的所有好处,并且发现重组这些代码绝对是对灵魂的摧残和折磨。我们以打扫家庭卫生为例:一个人可以随时宣扬保持房间清洁的好处(我完全同意),并且完全有能力用吸尘器打扫房间(我也完全同意),但通常我不会这样做。原因很简单,我还有其他我认为更重要的事情要做。这就是为什么我对我的Roomba很满意,它让我实现了保持房间清洁的所有好处,但又不必我亲自动手。这引出了我下面的观点……
但是我也希望Linux圈外的人能够理解:Linux所遵循的过程有着切实的优势。没有一种工具能完全胜任这项任务。以GitHub为例,它的工作流程非常好,原则上总是基于现有代码添加新的代码。但它可以强行push分支,使commit 上的评论变得毫无意义,使讨论变得毫无意义。
现代开发工具使许多事情变得更容易:你可以触发动作、集成CI/CD流水线、给变更的相关人员发通知等等。但在客观上,它们使得我们更难拆分工作了。纯文本的电子邮件使许多事情变得更麻烦,但它也并不会妨碍施行能得到理想结果的过程。
即使可以客观、准确地说出Linux放弃这个过程将赢得多少、将失去什么,仅这一点它就是完美的,有理由继续贯彻这个一直运转良好的过程。
我由衷地相信,如果我们有工具可以让一个组织实现Linux过程中同样的好处,那将是每个人的巨大胜利。面对着这样的工具,甚至Linux也可能不再使用纯文本电子邮件了。
我不知道这样的工具会是什么样的。但也许我可以大胆地设想一下:
原文链接:The Linux development process: Is it worth the hassle?
译者简介:冬雨,小小技术宅一枚,从事研发过程改进及质量改进方面的工作,关注编程、软件工程、敏捷、DevOps、云计算等领域,非常乐意将国外新鲜的IT资讯和深度技术文章翻译分享给大家,已翻译出版《深入敏捷测试》、《持续交付实战》。
领取专属 10元无门槛券
私享最新 技术干货