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


无论对于哪个组织 , 这都是值得的:它能使别人(包括将来的你)更容易理解为什么要做这个变更 , 为什么代码以这种方式运转 , 这可以使新人更快速地成长 , 可以防止重复出现相同的 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 很满意 , 它让我实现了保持房间清洁的所有好处 , 但又不必我亲自动手 。 这引出了我下面的观点……


推荐阅读