如何将紧密耦合的代码提取到外部库中?

时间:2016-02-14 19:28:09

标签: javascript html paradigms

这是一个关于范式的一般性问题,如果这是一个不合适的地方,我道歉。有关正确地点询问此事的礼貌建议将不胜感激:)

我正在为一家公司工作,该公司的每个网站都有单独的代码库。我被要求从一个代码库中获取相当大的功能并将其放入外部库中,以便多个代码库可以使用它。

问题是代码与它内置的代码库紧密耦合,而且我很难将其提取出来。我从多个角度解决了这个问题,每次都从头开始重新启动。每一次,我都开始陷入复杂的困境,感觉我正在以错误的方式接近问题。我想知道是否有其他人有这方面的经验,或者是否有推荐的方法继续进行?

这是我尝试过的:

  • 我将相关文件复制到一个新项目中,用vanilla javascript小心地替换旧代码库的每个引用。这是一个艰苦的过程,我一直遇到无法解决的问题

  • 我在旧代码库中放置了一个非常基本的HTML文件,以及一个空白的javascript文件。我已经将一个函数分别剪切并粘贴到该javascript文件中,并在旧的代码库和基本的HTML文件中调用它们。

  • 我创建了另一个新项目,并一次一个地复制和粘贴函数到新项目中。

每种方法都给我带来了自己的挑战,但是我无法解决这样一个事实:原始代码与原始代码库紧密耦合,进展非常缓慢,我开始质疑是否存在任何问题代码是可以挽救的。

1 个答案:

答案 0 :(得分:1)

旧代码可能无法挽救,并且达到您回去说这一点的理由是合理的。

我在这些情况下的典型目标,几乎所有旧代码都是无法实现的,但新的需要不仅要接管它,而且很快就会被新旧代码库使用,这就是重构将代码转换为模型,服务和组件(减少MVC和更多数据,如何获取和更改数据,以及如何查看数据和与数据交互)。

如果您正在构建复制旧版本的东西,但是从头开始编写它,我将其视为全新的,并首先从界面开始。通过了解外边缘应该的外观,并保持内部代码清洁,并依靠DI(原则,特别是没有任何包装),我构建系统我认为我应该是能够拥有,使新项目/产品能够愉快地与正确的东西融为一体。

...对于需要对产品进行改造的项目,在破旧的旧系统中,我采取几乎相同的方法;我设计了我想要的界面,我确保所有东西都是DI友好的(这在这里变得更加重要),然后我构建了一个外观,看起来就像是如何调用和使用旧的破坏,以及在那个外观内部,我实例化了理智的系统,我将任何旧的,可怕的数据点转换成我们的新模型,我做我系统需要做的任何事情,并且在离开系统的路上,我将我们真棒的新模型转换为可怕的结果是旧系统负责制作。

最新的东西是一个托管新API的新平台。 然而,API与可怕的,旧的,有状态的,基于会话的Web服务交谈,这使得水平扩展绝对不可能(当您的目标是在AWS上在Node上分发新平台时,不是您想要听到的)

解决方案是按照我们的预期完全构建API;在满足API客户端的实际需求的同时,让界面看起来更好,尽可能有用。

然后,我们确保提供API的模块使用DI作为服务的DI,作为旧后端的连接器。 这样,当需要连接到更好的系统实现时,我们可以简单地换掉该服务。 但是,这项服务需要变形金刚。

它需要一个变压器将我们令人敬畏的新请求对象转换为可怕的旧泥球,这个泥球不断增长。 然后它需要另一个变换器将丑陋的旧数据的输出转换成我们整个系统使用的新模型。 那些变压器不一定需要注入服务,因为它们的实现细节与他们调用的地方紧密相关,对服务的任何更新或任何新的服务都需要变换器为特定服务的实施细节工作。

然后在前端方面存在问题,在与服务器通信时,通信过去常常被视为理所当然。

我们现在在客户端有变换器,它们在最后一秒使用(实际上,我们编写了客户端服务)来转换旧的做事方式与新表格进行对话。

如果服务,转换和API通常用于特定/可重用的目的,那么在流程中间随机调用的任何神奇全局数据都会被考虑在内。 现在显式地传递了这些神奇地抓取的信息中的任何信息。一些是仅客户端的,因此是用于实例化的配置数据,或者是服务上的特定方法的参数。 会话数据现在显式地从客户端传回,以请求它们的每个请求(目前)的标记/ ids的形式。 因此,新平台保持100%无状态(从而在这方面进行了奇妙的扩展)。

只要所有这些神奇的数据都从内部传递出来并通过,系统就可以继续进行重构,而不必过于担心。 一旦状态和状态管理存在于系统内部,它开始变得越来越难以重构(并且你已经知道了)。

对永不离开页面的产品进行重构(即:不涉及API /服务,或者至少没有任何与您的前端紧密耦合的服务),并不是真的有很大不同。

通过明确强制将其传递到您的系统中来删除全局状态(构建时,调用时,只要符合数据的目的)。 如果存在触发太多事物的移动部件的异步竞争条件,请查看是否可以使用promises解决它们,以使您脱离嵌套的回调地狱。 我的团队现在主要使用基于集合的编程(.map.filter.reduce,而不是数组)和函数式编程,以简化我们查看和编写的大部分代码,因为每个新功能可能只有3-5行(有些是单行)。

所以我们的服务倾向于以OOP的方式构建,但是尽可能保持纯粹(没有外部状态由/为函数调用修改),并且这些调用的内部通常看起来更多像链式或组合函数式编程。

这与整个重构没什么关系,更多的是与微型重构有关,因为我们构建了我们的系统。 对于宏观层面来说,它确实是你的界面,你把旧东西包裹起来的外观,以及所有全局状态(功能有帮助)的消除,这些都会产生不同。

另一种选择当然是复制并粘贴整个文件/页面,并开始删除你知道不会破坏的东西,直到你找到可能破坏的东西,并继续那里。它不漂亮,不可重复使用,但我一生中被迫做了几次,每次都后悔。