翻译-插件架构

原文 Plug-in Architecture

在这里插入图片描述

这是一个我们可能每日使用并交互的东西之一,但是很少意识到它的存在。

它不仅仅存在于产品软件,像是可以通过插件定制并扩展的 Eclipse(IDE) 或者浏览器,而且存在于业务规则和数据处理逻辑都非常多变的业务软件中,例如保险理赔和税务软件。

底层思想很简单。能够插入特性到一个已经存在的组件中,并且组件不知道这个插入特性的实现细节。这听起来向我曾经听到过的。

Polymorphism (OOP)?. Protected Variations (Design Principle)?. Strategy Pattern (Design Patterns)?.

是的,就是这样!它们都涉及了相同的概念。

描述

插件架构包含了两部分:核心系统和插件模块。

设计的关键是以插件的方式给核心系统增加特性,提供扩展性,弹性,并且软件的特性和扩展处理逻辑是隔离开的。

特定的规则和处理流程和核心系统是分离的。在任何给定的点,我们可以添加,删除,和更改已经存在的插件,而对剩余的核心模块和插件影响很小或者没有影响。

核心系统

在高层级上,它定义了核心系统如何操作和基本的业务逻辑。这里没有特殊实现,没有定制化,它是抽象的。

一个简单的例子。通用工作流,像是数据如何在应用内部流动是定义好的。但是,工作流中包含的步骤取决于插件。因此,所有的插件会遵循这个提供它们自定义实现的通用流程。

再深入一点儿,它仍然处理特殊案例,应用特殊规则和复杂条件处理。不管扩展插件是什么,这些都是需要强制执行的。

此外,它仍然包含公共的代码来被多个插件去使用,来避免代码重复或者模板代码。

举个例子,如果两个插件都记录事务和失败日志,核心系统应该提供一个日志功能作为它的一部分。更不用说像安全、版本、UI 组件、数据库访问、缓存等等。

插件

插件是独立的,包含了特殊处理流程、额外的特性、自定义代码的独立组件,它可以增强或扩展核心系统产生新的能力。

通常,插件模块应该和其它插件模块独立。尽管一些插件需要和其他插件沟通或假设其它组件组件已经存在。不管怎样,要尽可能保持插件间的通信和依赖尽可能的小。

核心←→插件

核心系统需要知道(1)扩展插件模块(2)如何去获得它们。

核心系统声明了插件可以挂载的点。这些扩展点,这些挂载,通常代表了核心系统的生命周期。

因此,每个插件通过一些像是名字,通信协议,输入输出数据处理器,数据格式注册到核心系统上,并且挂载到这些扩展点上。

需要在核心系统和插件间有定义明确的接口。

核心系统和这些插件如何连接完全取决于软件构建(小型还是大型商业软件)和你的特殊需求(例如:单节点部署还是分布式部署)。

快速瞟一眼连接两种组件的不同方式。

配置

到现在你应该已经知道了这些插件需要向核心系统宣布它们的存在,插入扩展点,并且传递一些信息。
这就带来了配置的想法。胶水,协议点,我们通过它将插件连接到核心系统上,上面提到的每一样东西(扩展点,通信协议等)在这里被定义。

// 这个插件被插入核心系统的生命周期中
// 并且保存核心系统发出的活动事件到数据库中
core.registerPlugin({
   name: 'track-my-activities', 
   port: 8081,
   hooks: {
     wakeup: function (time) {
        saveTime("Woke up at: " + time);
     }, 
     work: function (time) {
       saveTime("Started work at: " + time);
     },
     exercise: function (time) {
       saveTime("Exercising at: " + time);
     }
    }
});

这个配置不仅给了我们敏捷性,而且允许我们可视化每个插件是如何工作的,或许还有数据的流动。

如果因为接口不兼容要插入一个插件到核心操作系统是痛苦的,那么通常的做法是在核心系统和插件间创建一个适配器,这样核心系统就不用为每一个不兼容的插件写特殊的代码了。

配置文件应该被保存到哪里?

配置可以通过命令行工具直接存在代码里,或者数据库里。它可以使用多种语言来写,像是 YAML,TOML,JS,JSON,XML 等等。

无论你考虑使用什么语言,都要确保你能做像是注释、条件、变量、循环或者其它需要的。记住,这在 JSON 中是不可能的。

此外,可以构建一个小工具去验证这些配置。

一个vs多个实例

我们提到过两个 case:基于产品的软件和基于业务的软件。

在这里插入图片描述

添加插件到浏览器上使我们都做过几次的事情。浏览器就是一个我们可以将插件插入的核心系统。

另一方面,特别在大型业务软件中,我们可以有多个应用实例,它们的每一个都可以扩展核心系统并且添加一个或多个插件。拿浏览器举例来说,这意味着有多个浏览器,每一个都有它自己的特性集合。

所以,我们本质上是在扩展多个核心系统,它们的每个都独自工作,完全独立。

其它模式

不令人吃惊的,这种模式可以解决特定的问题。而且它也可以重塑整个架构,成为另一个架构模式的一部分,或和另一个架构模式一起使用。

例如,您有一个据说不错的分层架构,其中插件架构嵌入其中。

另一方面,你可以有一个基于组件的架构,这个应用由客户、订单、支付等组件组成,这些组件是核心系统的组成部分。

分析

这种架构的特性带来了很多优点。

因为这些插件是独立的,这给予了敏捷性去快速改变、删除和添加插件。

减少拥有一些服务、插件之间的沟通和处理失败的麻烦。应用程序的行为是可以预测的。

取决于模式是如何被实现的,每一个插件可以被分别部署、测试和伸缩。

无论怎样,这里有一个巨大的隐患。就是核心系统自己,修改它可能打破或者改变插件的行为,因此,需要在一开始就周密的设计它。

所有我们提到的定义可能的扩展点,连接核心和插件,版本,强制由核心执行业务规则,这些都增加了实现这个模式所涉及的复杂性。

你最终会得到一个复杂的核心系统,充满了 if-else 条件,并且修改一行代码我们需要大量的分析人员,开发人员,测试人员。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值