升级时无法修补开源软件吗?


13

最近,我在集成到应用程序中的开源软件包中遇到了一个令人讨厌的(已确认)错误。根据公共问题跟踪工具,此错误已在该软件的最新版本中得到解决。

有时您需要该错误修复程序来避免对特定模块进行昂贵的重构,但是由于技术和/或政治原因,您将无法升级到最新版本。

在检查所做的代码更改时,此修复程序似乎很简单,我认为可行的选择是自己修补代码并重新编译我当前批准的软件版本,但是批评者希望证明这种情况几乎总是一个坏主意。这是有风险的,并且会带来麻烦的复杂性。

在他们眼中,因为此代码更改仅由我们完成,仅供我们使用,所以它必须是代码库的一部分,这意味着,与其将开源软件作为第三方依赖项引入,我们还必须将其作为一个新项目引入并纳入将其自动构建到我们的构建过程中。

对我来说,我认为这是错误的做法,因为我们会将他们的代码从其源代码控制存储库中提取到我们的代码中,并且在此之前发生的任何代码更改背后,我们都失去了历史。同样,对于需要进行如此小的代码更改而言,这似乎太复杂了。

在这种情况下执行上述操作会不好吗?如果是这样,那么当开源需要改变但仅出于内部利益而改变时,理想的情况是什么?


1
如果您认为这个问题不是建设性的或可以解决的,请告诉我。
maple_shaft

如果您无法更新集成到软件中的工具,那么您所能做的就是对该工具进行修补,以便修复该错误。重要的是仅在意味着重构您自己的代码时才不更新工具。
Ramhound

Answers:


12

如果您不能使用没有遇到问题的更高版本,则唯一的选择就是

  • 解决问题并找到解决方法
  • 派生库并将其修复为您的私有版本(这实际上是您要做的)
  • 丢下毛巾,告诉您的经理这个问题是无法克服的(这是一个谎言,因为您还有两个选择可以解决)。


我一直在您的位置,选项2(创建自定义分叉)通常是最可口的解决方案。在处理开源库时,这就是生命,特别是那些发展迅速且习惯破坏发行版本之间向后兼容性的开源库(以我的经验,这是必须要做的事情的最常见原因)。
对于不止几个OSS库,它引导我和我的团队参与其中的所有任务的强制包装,并仅通过这些包装访问第三方库的功能。这样,如果我们需要用一个非常不同的版本替换第3方库,这会破坏我们的代码,则更改至少在很大程度上限于该包装器。这不是最好的方法(添加代码,可能会增加复杂性和成本效益),但有时这是保持理智的唯一方法。


有趣!我从未考虑过包装库以帮助去耦的可能性。感谢您的输入!
maple_shaft

如果从第一方开始使用包装器,则是个好主意。如果您已经在直接使用该库,则切换到通用包装器将需要重构并重新测试很多代码。
Blrfl 2013年

1
@Blrfl是的,这就是为什么这不是要轻易采取的步骤。但是在至少一种情况下,我们有一个第三方(OSS)库在2个次要发行版之间更改了其所有软件包和类名,并且没有其他途径只能采用它,因此无论如何都必须进行重构。这样,我们结束了未来的证明,并修复了导致使用新版本的要求的问题。
jwenting

@jwenting:完全同意。我对Boost做同样的事情,因为尽管它们的某些实现很好,但接口却有些钝。那,他们也倾向于经常改变周围的事物。
Blrfl 2013年

2
请注意,某些Linux发行版通过将安全补丁反向移植到较早的发行版而有效地维护了自己的软件“分支”。
liori

6

在更常见的情况下,您捆绑第三方软件并打算跟踪其发布,这是一个坏主意。通常人们这样做是因为他们想要第三方组件中维护者不愿意实现或以您所需的方式实现的功能。

但是,您明确表示不会升级捆绑的代码。这使您有效地成为了第三方组件的维护者。因此,修补它是否是一个好主意,仅取决于您是否足够了解该代码以确信所需的效果。您的集成测试应该足以验证它确实在按照您的假设进行。因此,正如您所说的那样,在我看来,您的审稿人是错误的。


3

只要每个人都能承受成本,收益和风险,这样做确实没有错。

...修复程序似乎很简单...自己修补代码

当您有工作要做时,完善(拥有您真正想要的第三方库)就是足够好的敌人(自己进行修补),有时您必须做这样的事情。我已经完成了许多项目,在这些项目中,我们购买了商业图书馆的源许可证,因此我们可以在供应商解决之前解决问题。

……批评者想争辩说,这几乎总是一个坏主意,因为它有风险并带来麻烦的复杂性。

如果您没有杂物处理别人的代码,识别问题并编写修复程序,那将是一个坏主意。无论代码是内部的还是第三方的,都是如此。唯一的区别是,它是落在小腿上还是扔在小隔间或建筑物墙壁上。

如果您的批评者只是在不考虑执行此补丁程序的成本的情况下将想法搁置一旁,那么他们就没有在做作业。如果您有很多内部代码受补丁程序所修复的错误的影响,则必须仔细检查并更改它以解决该问题,然后重新测试所有内容以确保其正常运行。然后,如果您将软件包升级到错误修复的版本,则可能必须找到并删除解决方法,然后再次进行测试。也有这样做的风险,例如丢失更改的案例或测试不足。就个人而言,如果我有机会从源头上修复一个错误,我宁愿在那里做,而不是用苍蝇拍追逐其余的代码,希望我能得到一切。

...代码更改是由我们完成的...它必须是我们代码库的一部分...我们必须将其作为一个新项目进行介绍,并将其自动生成合并到我们的生成过程中。

如果您正在制作补丁程序,则该补丁程序是您自己的代码的一部分,这意味着您必须使其成为流程的一部分。这与向系统中添加100%的代码没有什么不同。将第三方分发视为神圣不可侵犯,并将其放入模块中,就像源代码一样。您编写的所有修补程序都与它一起存储在单独的文件中,并在构建过程中应用。这样,您始终可以从干净的源代码到修补的源代码,再到内置产品,并且可以准确显示正在发生的事情。(有些人将其解压缩,手动打补丁,重新打包并将其存储在版本控制中。这很糟糕。)

...我们会将他们的代码从其源代码控制存储库中提取到我们的代码中,而我们丢失任何代码更改背后的历史记录...

如果您将第三方库视为第三方依赖项,那么就没有该历史记录,也不会丢失任何内容。如果您可以继续访问第三方存储库,则可以根据需要进行咨询。第三方发行版应像无变化的斑点一样对待,您无需更改即可将其签入自己的系统。如果您需要查看正在使用的版本与更高版本之间的更改,则可以这样做,并且,如果需要,可以为旧版本提供包含所需更改的补丁程序。

同样,对于需要进行如此小的代码更改而言,这似乎太复杂了。

如果您的构建过程足够复杂,那么添加此过程就不会比添加您自己的代码困难得多。要使它自动解包/修补/构建过程要花费很少的精力,但是一旦完成,它就永远存在。现在可能有一个错误,但将来可能有二十个。如果有的话,您会更高兴为现在支持所有工作奠定基础,因为这将使处理下19个工作减少很多。


2

您想做的事情似乎很合理,但是听起来有(反对?)过程上的原因。我不会比较建议的解决方案,但也许有一种方法您也可以吃蛋糕:

如果有问题的开源项目允许,请将您的反向移植错误修正贡献到其存储库中。也就是说,如果您使用的是1.5.2版,而当前的稳定版本是1.6.1,请向1.5.2贡献一个补丁。如果采用了固定源,则可以直接从存储库(可能是1.5.3版)中获取固定源,并使所有人满意。

换句话说:也为您遇到的其他人修补它。当然,只有在项目支持(或至少允许)对已发布版本的更新时,才有可能。但这几天确实是相当标准的做法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.