原文地址:css-tricks.com/designing-a…
译者:Gavin,未经授权禁止转载。
前言
许多开源库都有插件系统,例如:Vue、jQuery、Gatsby。插件是库和框架的一个常见特性,用于允许开发人员以一种安全、可伸缩的方式添加功能。那么怎么构建一个插件系统呢?让我们用JS构建一个自己的插件系统来回答这个问题。
简单的计算器示例
从一个名为BetaCalc
的示例项目开始。BetaCalc
的目标是成为一个简单的JS计算器,其他开发者可以为其添加”按钮“。代码如下:
我们将计算器定义为简单的对象字面量
,计算结果将使用console.log
打印。现在功能很简单,有一个setValue
方法,用于模拟计算器上的数字输入,其中的console.log
模拟计算器上的显示屏,还有两个方法,用于对应计算器中的加号按钮与减号按钮。
为计算器程序添加插件系统
建立插件系统第一步就是要建立一个插件注册
方法,其他开发人员可以利用其注册插件。这个方法工作很简单:获取外部插件,抓取其exec
函数,并将它作为一个新的方法(“按钮”)附加到计算器上:
这里有一个插件的例子,它给计算器增加“平方”按钮:
在许多插件系统中,插件通常由两部分组成:
- 需要执行的代码;
- 元数据(如:名称、描述、版本号、依赖关系等)
在我们的插件中,exec
函数包含了需要执行的代码,函数名称为元数据。当插件注册后,exec
函数作为方法直接附加到我们的betaCalc对象上,使它能够访问betaCalc的this。现在BetaCalc有了一个新的“平方”按钮,可以直接调用:
这个系统有很多不错的地方,它是一个简单的对象字面量
,可以传递到函数中。意味着插件可以通过npm下载,并作为ES6模块导入,可以实现简单的分发。
但现在系统还存在一些缺陷:
通过允许插件访问BetaCalc
的this
,插件可以读/写所有BetaCalc中的代码,虽然这对于获取和设置currentValue
很有用,但是也很危险。如果一个插件要重新定义一个内部函数(如:setValue
),它可能会为BetaCalc
和其它插件产生意想不到的结果。这违反了开闭原则,该原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”。
此外,“平方”函数的工作原理会产生“副作用”。这在JS中并不罕见,但感觉并不好--尤其是当其它插件可能处于同样的内部状态时。一个更加实用的方法将大大有助于我们的系统更加安全和可预测。
一个更好的插件系统架构
再来看一个更好的插件架构,下面例子改变了计算器和它的插件API:
这里有一些显著的变化。
首先,我们将插件系统与“核心”计算器方法(如“加号”与“减号”)分离开,将它们放入自己的插件对象中,使系统更加安全。现在插件将不能直接读写BetaCalc
的属性--它们只能看到BetaCalc.plugins
的属性。
其次,我们实现了一个press
方法,它根据名称查找功能(“按钮”)函数,然后调用它。现在,当我们调用一个插件的exec
函数时,我们将当前计算器的值currentValue
传递给它,并期望它返回新的计算器值。
本质上,这种新的press
方法转换成纯功能的计算器“按钮”:获取当前计算器值,执行操作,返回结果。这有很多好处:
- 简化了API
- 使测试更加容易(对于
BetaCalc
和插件本身) - 减少了我们系统的依赖性,使它更松耦合
这个新的架构比第一个示例有更多的局限性,但显然第二种方式更好,能限制插件只做我们想让它做的改变。
现在我们的计算器插件只能对currentValue
进行操作。如果一个插件作者想要添加一些高级的功能,比如"内存"按钮或者一种追踪历史记录的方法,他们可能做不到。这里需要权衡:给插件作者太多权利可能会影响项目的稳定性,但太少的权利可能使他们很难解决他们的问题。
还能做什么
还可以做很多事情来改进我们的系统。例:
- 如果插件作者忘记定义名称或返回值,我们可以添加错误处理来通知他们;
- 扩展插件的范围。目前
BetaCalc
插件仅可以添加一个"按钮",我们可以为某些生命周期事件注册回调; - 扩展插件注册机制,目前
BetaCalc
仅支持一次注册一个"按钮",我们可以使其支持批量注册。
设计你的插件系统
如果你的项目比较大,那么可以参考一些开源的插件架构。例如jQuery、Gatsby、D3、CKEditor或者其它。 当然你也可以熟悉JS的设计模式,或者阅读Addy Osmani的《学习JS设计模式》,这为你提供了许多优秀的插件架构选项。了解这些选项可以帮助你更好地平衡使用你项目所有人的需求。
除了设计模式外,你还可以利用优秀的软件开发原则来做出这类决策。如前面提到的:开闭原则、松耦合,还有一些其它相关的原则,如:得墨忒耳定律、依赖注入等。
看起来很多,但作为一个插件系统设计者,你必须得研究,因为没有什么比让每个人都重写他们的插件更痛苦。当你改变你开源项目的插件架构时,将使你的开源项目失去信任,会大大降低开发者为你的项目作出贡献的热度。
总结
从头开始编写一个好的插件系统架构是很困难的,你必须平衡考虑许多因素,以构建一个满足每个人需求的系统。系统足够简单吗?足够强大吗?能长期发挥作用吗?
不过这是值得的。拥有一个好的插件系统对每个人都有帮助。开发者可以自由地解决他们的问题,终端用户可以从大量的插件中进行选择。你可以围绕你的项目建立一个生态系统和社区。这是一个双赢的局面。
📣智云健康急招聘
欢迎小伙伴来和我们一起来做分享、做开源呀😃~