在 2025 收官前,看清 Data + AI 的真实走向,点击查看 BUILD 大会精华版 了解详情
写点什么

Linux 开发过程那么麻烦,是否值得?

  • 2020-10-09
  • 本文字数:4321 字

    阅读完需:约 14 分钟

Linux 开发过程那么麻烦,是否值得?

中文摘要: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 来说,这却是至关重要的,原因有两个:


  1. 很多人有着不同的背景、来自于不同的公司,这些公司有着不同的动机和议程。公司内部的大型项目可以使用其他机制来传递信息和确保职责。很少有开源项目能像 Linux 那样庞大、长寿,受着这么多人的影响。

  2. Backport:鉴于其规模和重要性,分支一直是 Linux 的常态。即使是现在(2020 年),一些发行版也可能是在它们视为 LTS 的版本上加上自己的补丁。即使现在这种情况相比 2000 年初有所下降,也只是因为 Linux 本身开始有了自己的 LTS 系列,发行版可以以这些版本为基础了。


许多现代线上公司不需要保持产品线的兼容性,通常不存在 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 也可能不再使用纯文本电子邮件了。


我不知道这样的工具会是什么样的。但也许我可以大胆地设想一下:


  1. Git 是一个源代码控制系统,本质上源代码控制系统希望添加历史,而不是重写历史。然而,GitHub 中的开发过程却把两者混为一谈了,开发和评审以 git 提交为准,而纯文本 Linux 开发人员是在他们自己的本地 git 树中开发的,不断在重写历史。也许我们需要将其一分为二,允许在单独的工具中进行开发和评审,这样本质上周期会更短暂,代码更容易得到处理。Git 用来存储结果。一个很好的类比是,CSS 允许 HTML 开发人员将表示层与逻辑层分离。还记得 CSS 出现之前的 HTML 吗?不好,我是不是暴露年龄了……

  2. 接上述内容继续扩展,可能逐行描述补丁差异会使每件事情都很难开展。我们是否可以有一个系统,在这个系统中,我们可以在更高的层次上描述我对代码所做的那些更改,并明确这些变更能够应用到其他什么地方?例如,我可以说“将 create_bar()函数移到 create_foo()之前”或者“在 create_bar()参数列表最后添加一个名为 y 的整型参数”。即使后续的变更会在代码环境中添加一些东西,破坏了逐行差异,这样系统仍然能够将变更应用到虽被修改但只是版本稍有不同的代码库上。也许我太天真了,这是不可能的,但 GPT-3 取得了一些令人大开眼界的进步,看到这些我觉得可能也并不遥远。

  3. 或者如果没有那么大的野心,也许有一种中间解决方案,那就是总是对追加的代码进行代码审查。如果所有部分都得到了认可,那么此时此刻,也仅在此时此刻,历史才被改写。更简单、更易用的工具可以帮助维护者确保与已批准的代码不存在差异,以核实所做的变更都是围绕重组进行的。


原文链接:The Linux development process: Is it worth the hassle?


译者简介:冬雨,小小技术宅一枚,从事研发过程改进及质量改进方面的工作,关注编程、软件工程、敏捷、DevOps、云计算等领域,非常乐意将国外新鲜的 IT 资讯和深度技术文章翻译分享给大家,已翻译出版《深入敏捷测试》、《持续交付实战》。


2020-10-09 12:362787

评论

发布
暂无评论
发现更多内容

山东青岛推进平安小区建设!源中瑞智慧社区平台解决方案

源中瑞-龙先生

解决方案 山东 源中瑞 青岛 智慧社区

EEPROM CAT24CXX实现分页读、写数据

不脱发的程序猿

28天写作 CAT24C08 EEPROM 嵌入式软件 单片机

Git学习游戏化,从Learn Git Branching 开始

程序老王

git 学习 学习方法 git 学习

华为云原生数据仓库GaussDB(DWS)深度技术解读:融、快、大、稳、易

华为云开发者联盟

数据库 云原生 华为云 GaussDB 数仓

刷屏洗脑的“吗咿呀嘿”,到底是个啥?

架构精进之路

商业模式 28天写作 3月日更

技术案例 | 云原生微服务落地难?百度自用CRM这样做

百度开发者中心

微服务 CRM #百度智能云#

技术解析 | Doris Compaction机制解析

百度开发者中心

百度 apache doris

树莓派上的家庭监控中心

冯骐

运维 树莓派 监控系统 Open-Falcon 物联网,

QA视角看数据匿名化

BY林子

数据安全 测试右移 用户数据 数据脱敏

程序员之禅(一)

每天读本书

读书笔记

元宵节元宵钱,不买元宵买云资源! | 2核4G低至0.79元/天

京东科技开发者

云主机 云服务器 云存储 云硬盘

海豚调度dolphinscheduler SQL脚本初始化流程

cloudcoder

海豚调度 调度引擎 分布式任务调度

极限编程技术实践

Teobler

敏捷 敏捷开发 TDD 重构 极限编程

【LeetCode】区域和检索 - 数组不可变Java题解

Albert

算法 LeetCode 28天写作

程序员专属“灯谜”大挑战,答对六题算你赢!

京东科技开发者

编程语言 集群

使用 pyVmomi 采集 vSphere 监控指标

冯骐

Python 运维 监控 Open-Falcon vpshere

MySQL字段默认值设置详解

Simon

MySQL 数据库

搭建一个 802.1x 的 web 测试服务

冯骐

网络 监控系统 Open-Falcon radius eduroam

OS命令--shell中数组的操作

cloudcoder

数组 Shell 循环引用

LeetCode题解:123. 买卖股票的最佳时机 III,动态规划,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

从0到1建立数据分析指标体系底层逻辑

小飞象@木木自由

数据分析 数据指标 数据分析体系

Wiki.js 配置 LDAP 认证

东风微鸣

wiki

GaussDB(DWS):非侵入式备份及其在NBU上的应用

华为云开发者联盟

架构 GaussDB 集群 备份 NBU

工作两三年了,整不明白架构图都画啥?

小傅哥

Java 后端 小傅哥 架构设计 画架构图

树莓派上的温湿度环境监控

冯骐

运维 树莓派 物联网 监控告警

看完你就明白什么是图神经网络

华为云开发者联盟

神经网络 深度学习 节点 图神经网络 图结构

构建一套适合微服务的高可用架构

环信

MongoDB 在评论中台的实践

vivo互联网技术

数据库 mongodb 分布式 集群

国产芯片WiFi物联网智能插座—电耗采集功能设计

不脱发的程序猿

28天写作 国产芯片 电耗检测 电压电流 华大MCU

华为云举办AI经典论文复现活动,打造领先AI开发者学习社区

华为云开发者联盟

AI 华为云 modelarts 论文 AI Gallery

Linux入门篇 —— Linux 磁盘管理之磁盘理论篇

若尘

Linux linux编程 磁盘

Linux 开发过程那么麻烦,是否值得?_开源_Glauber Costa_InfoQ精选文章