何时应更新依赖项?


30

我们有两个与依赖关系有关的主要危机,它们具有两个不同的代码库(Android和一个Node.js Web应用程序)。Android存储库需要从Flurry迁移到Firebase,这需要将Google Play服务库更新为四个主要版本。我们在Heroku托管的Node应用程序中发生了类似的事情,在该应用程序中,我们的生产堆栈(cedar)已被弃用,需要升级到cedar-14。我们的PostgreSQL数据库也需要从9.2更新到9.6。

这些应用程序的每个依赖项都已经存在了将近两年的时间,而当其中的一些应用程序被弃用并且我们进入“日落”时期时,更新或替换它们一直是头疼的大问题。在过去的一个月中,我花了30多个小时来慢慢解决所有冲突和代码损坏。

显然,让事情搁置两年已经太久了。技术发展日新月异,特别是当您使用Heroku等平台提供商时。假设我们有一个完善的测试套件,以及一个像Travis CI这样的CI流程,它不需要进行很多更新工作。例如,如果某个功能在升级后被删除,而您正在使用它,则测试将失败。

应该多长时间更新一次依赖关系,或者何时应该更新依赖关系?我们进行了更新,因为我们被迫这样做,但似乎某种先发制人的方法会更好。发行次要版本时,我们应该更新吗?主要版本?每个月是否有更新?我想不惜一切代价避免发生我刚刚经历的情况。

PS-对于我的一个个人Rails项目,我使用了一项名为Gemnasium的服务,该服务可以跟踪您的依赖关系,以便可以将安全漏洞通知给您。这是一项很棒的服务,但是我们必须手动检查我提到的项目的依赖关系。

Answers:


32

通常,在以下情况下应升级依赖关系:

  1. 必须的
  2. 这样做有好处
  3. 不这样做是不利的

(这些不是互斥的。)

动机1(“必须时”)是最紧急的驱动程序。您所依赖的某些组件或平台(例如Heroku)需要它,并且您必须顺其自然。所需的升级通常会从其他选择中分离出来。您决定某某升级到PostgreSQL版本。现在,您必须更新驱动程序,ORM版本等。

升级是因为您或您的团队认为这样做具有优势,因此更容易选择。更具判断力的是:“新功能,能力,性能……是否值得努力和引入新功能?” 在过去的时代,人们强烈反对可选升级。它们是手动的并且很辛苦,没有好的方法可以在沙盒中进行尝试或虚拟环境,或者在无法解决问题时将更新回滚,并且没有快速的自动化测试来确认更新没有“破坏苹果购物车”。如今,偏向于更快,更积极的更新周期。敏捷方法喜欢尝试事物。自动安装程序,依赖性管理器和存储库使安装过程快速且通常几乎不可见;虚拟环境和无处不在的版本控制使分支,分支和回滚变得容易。自动化测试使我们可以尝试进行更新,然后轻松地进行实质性的评估:“它起作用了吗?有没有把东西搞砸了?” 这种偏见已经从“如果没有破裂就不要修复”转变为“尽早更新,经常更新”。

动机3是最软的。用户故事与“管道”无关,也从不提及“并保持基础架构不超过当前版本的N个版本”。版本漂移的缺点(大致来说,与落后于技术曲线相关的技术债务)会悄悄入侵,然后经常通过破坏来宣布自己。“很抱歉,不再支持该API!” 即使在敏捷团队内部,当不被视为完成特定的sprint或发布的关键时,也很难激励增量主义和“保持”组件的新鲜度。如果没有人主张更新,他们可能会无所适从。在准备好断裂甚至断裂之前,该轮子可能不会发出吱吱声。

从实际的角度来看,您的团队需要更加注意版本漂移问题。2年太长了。没有魔术。这只是“现在付款或以后付款”的问题。要么逐步解决版本漂移问题,要么每隔几年遭受苦难,然后克服更大的麻烦。我更喜欢渐进主义,因为某些平台震动很大。您不再依赖的关键API或平台可能真的毁了您的一天,一周或一个月。我喜欢每年至少评估1-2次组件新鲜度。您可以明确地安排评论,也可以通过相对节制的(通常是每年一次)主要组件(如Python,PostgreSQL和node.js)的有机更新来有机地触发评论。如果组件更新不能非常强烈地触发您的团队,则可以对主要版本进行新鲜度检查,在自然项目高原,或者每k个释放也可以工作。不管是什么,都以更规则的节奏来关注纠正版本漂移。


5

需要更新库时,应更新它们。这意味着,如果更新没有任何价值,那么您不应该这样做。

在您的特定情况下,您正在从旧的技术堆栈迁移到新的技术堆栈,并且为此,您不得不更新依赖项。那一刻是更新依赖项的正确时间。

如果您要跨时间更新依赖关系,为了“现在不麻烦”,您将不得不花费大量工作时间(编码)以获取无返回值。而且,当您要进行最后一次更新时(您现在正在执行的,但是要更新1个主要版本而不是4个),您可能仍会感到头痛(毕竟,主要版本意味着无法更改)。因此,我认为您的做法正确。

但是,如果您发现迁移太难,并且必须进行大量重构,则问题可能出在您的代码库中。对于Android项目,在代码结构方面没有整体架构是很常见的。像Dagger 2这样的好的依赖项注入框架,以及像SOLID这样的软件工程原理,可以更轻松地更改代码实现,同时保持相同的行为/要求。

另外,由于我们正在进行重构,因此请阅读一些有关单元测试的内容,因为这在进行此类工作时会很有帮助。


4

如果您使用软件包管理工具(例如npm,NuGet)并具有全面的自动化测试套件,则升级依赖项应该是一件轻而易举的工作,只需升级软件包,运行测试套件并查看是否存在任何问题。如果存在,则回滚并提出工作项以调查并解决问题。

只要升级依赖项的成本较低,就值得不断更新:

  • 如果升级存在问题,那么您需要早日知道,以防需要上游更改。
  • 将依赖项升级留到最后一刻通常意味着您在紧要关头进行这些升级(例如,响应于安全性严重的错误)。保持依赖关系的最高级意味着您可以控制何时进行这些工作,并可以在不那么忙的时候执行这些升级。
  • 较新的版本可能会提高生产率,例如,更好的文档,更易于使用的API,错误修正(尽管也可以相反)。

如果升级依赖关系不是一件容易的事(例如,因为您需要手动测试升级,或者因为存在已知问题/重大更改),则必须权衡其他任务的利弊。旧的依赖关系是一种低息技术债务,因此应相应地加以处理。


2

除非有已知的替代版本,否则不应该在已知的情况下使用依赖关系的旧版本进行发行。

即,如果您使用的是V1,并且仍受支持,则仍可以使用v1的最新版本。

您唯一过时的时间是:

答:您已经有一段时间没有发布了。

B:您使用v1很久了,不再受支持

更新的发布是有原因的,其中包含您应该使用的安全修复程序。

如果出现新版本的依赖关系,则还应该发布


1

我认为它一定程度上取决于所讨论的库,但是我本人也曾遇到过类似的依赖问题。

常识对我说,主要版本可能是升级的正确时机,而次要版本解决了严重的缺陷或包含了重要的优势,将取代该版本。

有时,我们没有处理需要维护的每个应用程序的奢侈资源,甚至没有部署关键任务的应用程序,但最终它们会咬住您,一丝预防往往能胜任治疗!


0

当图书馆提供您的软件将使用的优势来补偿更改中花费的工作时,应更新库。

即使是较小的库版本升级也可以破坏或在应用程序中插入不一致之处。从这个角度看,没有什么小变化。

使用旧库没有什么可耻的。当需要更改时,可能会很痛苦,但这是工作的一部分。


我同意每次升级都应该了解。如果您可以偿还技术债务,也可以。我们并非聘请您使用最新版本(并且一直在追逐最新版本,而无需考虑或分析),但是最新版本可能会有助于我们聘请您做些事情。
geoaxis
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.