当前位置: 首页 > 科技观察

遗留代码升级的良好实践

时间:2023-03-19 21:14:55 科技观察

传统企业乃至互联网公司往往存在大量的遗留代码。这些遗留代码中的大部分都可以正常工作,有些可能仍然运行着关键业务或持有核心数据。然而,大多数遗留代码通常具有技术陈旧、代码复杂、修改困难的特点。随着时间的推移,遗留代码的维护和管理成本越来越高。在微服务全面转型的今天,这些遗留代码应该如何处理?TomaszKania-Orze?为我们解释了升级遗留代码的最佳实践。我相信这篇文章对于有大量遗留代码的企业/组织非常有用。“我有一个关于RubyonRails的应用程序可以追溯到2011年,它在过去五年里没有添加任何新功能。它现在很缓慢,随着我们的用户群不断增长,它几乎没有提供服务。你能帮忙吗我们用这个?”这是我在Monterail客户身上看到的最常见的场景之一。这种难以维护且存在安全漏洞的遗留代码对于必须使用它的企业以及必须处理它的开发人员(如我们)来说是一场噩梦。在我作为软件工程师的十年左右的时间里,我有很多机会观察一些开发人员为更新Web应用程序中的遗留代码而进行的技术转变的成功和失败。例如,这可能意味着从框架的版本2升级到版本6,或者从Ruby升级到Python,或者从单体应用程序升级到微服务架构,或者从手动构建升级到持续交付。为了进行无痛(或至少不那么痛)的更新,您必须决定是否有必要进行更改,确定最适合您的方法,并承诺从长远来看这样做。1、什么时候改?性能不佳是进行技术更改的原因。另一个原因是你使用的技术的流行度逐渐或突然下降。毕竟,如果市场上能够支持你工作的开发者越来越少,你的技术被关闭的风险就会增加。有些人早在2010年就使用Backbone构建了他们的应用程序,如今却在与模型-视图-控制器问题作斗争,而其他人则在使用基于组件的框架,如React或Vue等。如果您选择的框架失去活性,风险会更大支持。还记得AngularJS吗?2018年7月,它进入了长期支持阶段,这意味着谷歌将不再纳入新功能或修复,即使是一个小的突破性变化。译注:“模型-视图-控制器”(Model-view-controller,MVC)是软件工程中的一种软件架构模式,它将软件系统分为三个基本部分:模型(Model)、视图(View))和控制器(控制器)。MVC最早由TrygveReenskaug于1978年提出,是XeroxPARC在1980年代为编程语言Smalltalk发明的一种软件架构。MVC的目的是实现一个动态的程序设计,简化程序后续的修改和扩展,使程序的某一部分的复用成为可能。此外,MVC通过简化复杂性使程序结构更加直观。当你的技术在人力或机器成本方面过于低效和昂贵时,这不仅是发起技术变革的好机会,而且可能是你在技术变得无法修复之前修复该技术的最后机会。您永远不想达到创建新功能根本不可行的地步。欧洲电子商务公司Zalando一直在努力快速扩展其单一的PHP应用程序,但无法快速或高效地提供新功能。这导致他们在2016年从单体应用程序转向微服务,使不同的团队能够以更快的速度交付功能。2.应该如何进行更改一旦确定您正在开发的产品需要升级,那么就该对更改方向做出明智的决定了。一旦编写代码,它就会成为遗留代码,并且无法保证您编写代码的技术在未来不会失去支持或变得过时。(安息吧,AngularJS。)因此,更改应该支持未来的灵活性。这里有一些选项:选项一:BigBangRewrite第一个也是最明显的选项是BigBang重写:从头开始更改代码库并在一次转换中切换所有用户。然而,完全重写是非常耗时的,而且必然需要相当大的成本。您还可能最终得到一个需要数月甚至数年才能发布的应用程序,并且在该过程结束之前您将无法看到最终结果。此外,应用程序越大,开发人员在重写过程中提供维护和添加新功能的难度就越大。考虑到文档和技术知识,向大型代码库添加新功能就像在公园里散步一样简单。没有这些,真的很难做到这一点。选项二:重生凤凰第二个选项是在现有代码库中添加使用新技术构建的新功能。理想情况下,您不应该接触旧技术,而是将所有新功能隔离开来。但不幸的是,这样的原始结果很少见:新功能几乎总是需要与旧功能集成。这也需要一个详细的计划,因为事情很复杂,不仔细计划是很难做好的。在复杂的体系结构中创建新组件需要大量有关遗留应用程序中组件行为方式的信息。你需要一个广阔的视角,从新旧两方面来看待技术。使用单体应用程序,您可以在单独部署的新代码库中创建新功能,同时使用与新旧代码交互的单个数据库存储数据。这个解决方案看似简单,但其长期成功取决于您坚如磐石的承诺。(特别是如果您的整个系统受到机器性能或并发问题的影响。)例如,如果您的单体应用程序开始获得更多用户,那么单个数据库可能成为瓶颈。(另一方面,云中的数据库可以扩展。)由于原始代码库的长期脆弱性,特别是考虑到潜在的安全漏洞或错误,这种架构是不可持续的。实际上,保留过时的代码意味着您正在等待它最终永远失败。选项三:混合方法重写整个代码库是一种极端的想法,而且往往是错误的想法。在旧代码库之上添加新功能更可行,但会产生严重的副作用,例如,如果您的遗留代码基于旧框架版本,则会出现安全问题。那么,您还能做些什么更便宜或危险性更低的事情呢?你有其他选择吗?我推荐一种混合方法。此选项与大爆炸式重写一样,也需要更改整个遗留代码。但与第一个选项不同的是,重写应该在一段时间内(比如几年)完成,以最大限度地减少技术债务和财务成本。至关重要的是,这种渐进式方法将基于您的愿景。您需要首先知道要改变什么:一些功能对业务来说是核心和关键的,而其他功能则更多地发挥辅助作用。有了明确的目标,多层次的工作就会变得更容易。例如,您是否仍计划在此过渡期间发布新功能?如果是这样,您需要在计划中考虑到这一点。如果没有清晰的路线图,您的代码最终将变得一团糟,开发人员将更难理解。对我来说,这种方法是关于未来和可扩展性的:而且它最容易与微服务一起使用。假设您的遗留代码库是新微服务生态系统中的一个元素。当然,它太大太复杂,无法成为真正的微服务,但它可以像微服务一样与新功能进行通信。要处理这种安排,您需要创建允许遗留代码与新技术通信的API或“桥梁”。当您以单独的微服务形式添加新功能时,它们将一点一点地吞噬遗留代码的业务逻辑。虽然您可以通过向遗留的单一应用程序添加新功能来实现类似的功能,但这样做会产生技术债务和灵活性损失。几乎所有的解决方案都有副作用,包括这种方法。但我们需要知道如何最大限度地减少副作用。对于Web应用程序的前端,反向代理可以减轻此更改的副作用。使用这种方法,您甚至可以在不接触旧软件的情况下替换为单个URL提供服务的Web应用程序中的逻辑。但是这种技术有其自身的要求,例如,如果您有用户登录,您应该在页面之间维护状态。我们总是需要存储状态,但在这个解决方案中,我们需要在两个应用程序之间移动或共享状态。它更难维护,但您仍然可以获得更具弹性的基础设施。更复杂的变化需要改进基础设施,例如创建一个前端服务器层,您可以从中呈现来自不同来源的应用程序片段,如上面的微服务示例。基于XML的标记语言ESI(EdgeSidesIncludes)可能适合这项任务,而Varish或Nginx然后,为了确保您的应用程序能够随着用户群的增长保持性能,创建负载平衡器和独立的基于上下文的数据库,这些数据库在微服务或宏服务中单独使用。创造一个可以支持这种安排的灵活环境也是一项挑战。当转向微服务时,你只需要在基础设施上投资一次,但你将需要进一步支持这个架构的维护。不过,它可能仍然比重写所有代码便宜很多。如果您的主要目标是创建一个易于维护的生态系统(而不是首先关注性能然后关注维护),您还需要在开发过程中确定系统的关键元素并创建路线图以对其进行更改。在流程中引入一些持续集成和部署魔法,CI和CD流程可以在没有QA或开发人员帮助的情况下实现自动化,最终您会得到一个结构清晰且易于修改和调整的成熟软件。当然,这种混合方法并不是世界上唯一可用或正在使用的选择。然而,对代码库的增量更改最终会导致完全重写,让您可以使用工作代码,保证业务安全,而微服务使不同的团队能够独立交付新的和不同的功能,提供专为长期使用而设计的流程和架构.3.做出持久改变需要什么?您可能会查看我的首选解决方案并想,“好吧,这有点过于工程化了”,或者“我没有一个团队可以胜任这种工作”,或者“这对我的平台来说太过分了”。复杂”,甚至“这不是纯粹的微服务架构!”我没有反对你的意思,但我确实认为升级你的技术会迫使你从长远考虑。我提供的不是快速解决方案。相反,混合方法为您提供了构建在您工作之上的新技术。通过逐渐转向微服务,增量更改使您可以轻松地更新您的应用程序并利用最新的框架,所有这些都不会迫使您在可靠性方面做出妥协。那么,您准备好了吗重构你的软件?作者介绍了TomaszKania-Orzel,一位经验丰富的软件和DevOps工程师,最喜欢从事前端技术工作。目前在Monterail担任技术负责人,带领着一个75人的开发团队。