如何创建灵活的插件架构?

jus*_*tkt 149 language-agnostic architecture plugins plugin-architecture

我的开发工作中的一个重复主题是使用或创建内部插件架构.我已经看到它涉及多种方式 - 配置文件(XML,.conf等),继承框架,数据库信息,库等.在我的经验中:

  • 数据库不是存储配置信息的好地方,尤其是与数据混合在一起
  • 尝试使用继承层次结构需要了解要编码的插件,这意味着插件架构不是那么动态
  • 配置文件适用于提供简单信息,但无法处理更复杂的行为
  • 库似乎运行良好,但必须仔细创建单向依赖.

当我试图从我曾经使用过的各种架构中学习时,我也在寻求社区的建议.您是如何实现SOLID插件架构的?你最糟糕的失败是什么(或者你看到的最严重的失败)?如果要实现新的插件架构,您会怎么做?您使用过的SDK或开源项目是否具有良好架构的最佳示例?

我自己找到的几个例子:

这些例子似乎发挥了各种语言优势.一个好的插件架构是否必然与语言相关?最好使用工具来创建插件架构,还是在自己的以下模型上进行?

Nou*_*him 83

这不是一堆可能有用的评论/示例的答案.

  • 使应用程序可扩展的一种有效方法是将其内部结构作为脚本语言公开,并用该语言编写所有顶级内容.这使得它具有很强的可修改性和实际的未来证明(如果您的原语被很好地选择和实现).这种事情的成功故事是Emacs.我更喜欢eclipse样式插件系统,因为如果我想扩展功能,我不必学习API并编写/编译单独的插件.我可以在当前缓冲区中编写一个3行代码段,对其进行评估并使用它.非常流畅的学习曲线和非常令人愉快的结果.

  • 我扩展了一点的一个应用是Trac.它具有组件体系结构,在这种情况下意味着将任务委托给广告扩展点的模块.然后,您可以实现适合这些点的其他组件并更改流程.这有点像Kalkie的建议.

  • 另一个好的是py.test.它遵循"最佳API是无API"的理念,完全依赖于在每个级别调用的钩子.您可以在根据约定命名的文件/函数中覆盖这些挂钩并更改行为.您可以在网站上查看插件列表,了解它们的实施速度/速度.

几点概括.

  • 尽量保持您的不可扩展/非用户可修改的核心尽可能小.将所有可能的内容委托给更高层,以便可扩展性增加.在选择错误的情况下,更少的东西要在核心中纠正.
  • 与上述相关的是,您不应该在一开始就做项目的方向做出太多决定.实现所需的最小子集,然后开始编写插件.
  • 如果您正在嵌入脚本语言,请确保它是一个完整的语言,您可以在其中编写通用程序而不是仅为您的应用程序编写的玩具语言.
  • 尽可能减少样板.不要打扰子类,复杂的API,插件注册和类似的东西.尽量保持简单,所以它的方便,而不仅仅是可能延长.这将使您的插件API更多地使用,并将鼓励最终用户编写插件.不只是插件开发人员.py.test做得很好.据我所知,Eclipse 不会.

  • 我会将脚本语言扩展到值得考虑嵌入像 python 或 perl 这样的现有语言 (2认同)

der*_*ion 24

根据我的经验,我发现实际上有两种类型的插件架构.

  1. 其中一个Eclipse model是为了允许自由而且是开放式的.
  2. 另一个通常需要插件来跟随a,narrow API因为插件将填充特定的功能.

要以不同的方式说明这一点,一个允许插件访问您的应用程序,而另一个允许您的应用程序访问插件.

区别是微妙的,有时没有任何干扰...你想要你的应用程序.

我没有大量的Eclipse经验/打开你的应用程序插件模型(Kalkie的文章中的文章很棒).我已经阅读了eclipse做事的方式,但仅此而已.

Yegge的属性博客讨论了如何使用属性模式允许插件和可扩展性.

我所做的大部分工作都使用插件架构来允许我的应用访问插件,例如时间/显示/地图数据等.

几年前,我会创建工厂,插件管理器和配置文件来管理所有这些,让我确定在运行时使用哪个插件.

  • 现在我通常只做DI framework大部分的工作.

我仍然需要编写适配器来使用第三方库,但它们通常并没有那么糟糕.

  • 很棒的文章链接. (3认同)

Pat*_*ick 14

我见过的最好的插件架构之一是在Eclipse中实现的.一切都是插件,而不是拥有插件模型的应用程序.基础应用程序本身就是插件框架.

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

  • 在新版本的Symfony框架中使用了相同的方法(一切都是插件).它们被称为捆绑,但原理是相同的.它的架构很简单,也许你应该看看它:http://symfony-reloaded.org/quick-tour-part-4 (6认同)

Ash*_*vis 9

我将描述一种我过去使用的相当简单的技术.此方法使用C#反射来帮助插件加载过程.可以修改此技术,使其适用于C++,但是您无法使用反射.

一个IPlugin接口用于识别实现的插件类.方法被添加到接口以允许应用程序与插件通信.例如Init,应用程序将用于指示插件初始化的方法.

要查找插件,应用程序会扫描.Net程序集的插件文件夹.每个组件都已加载.反射用于扫描实现的类IPlugin.创建每个插件类的实例.

(或者,Xml文件可能会列出要加载的程序集和类.这可能有助于提高性能,但我从未发现性能问题).

Init为每个插件对象调用该方法.它传递了一个对实现应用程序接口的对象的引用:( IApplication或其他名称特定于您的应用程序的对象,例如ITextEditorApplication).

IApplication包含允许插件与应用程序通信的方法.例如,如果您正在编写文本编辑器,则此接口将具有OpenDocuments允许插件枚举当前打开的文档集合的属性.

通过创建派生插件类,例如LuaPluginIPlugin函数和应用程序接口转发到Lua脚本,可以将此插件系统扩展到脚本语言,例如Lua .

这种技术可以让你反复地实现你的IPlugin,IApplication在开发过程中和其他应用程序特定的接口.当应用程序完成并且很好地重构时,您可以记录暴露的接口,并且您应该有一个很好的系统,用户可以编写自己的插件.


Ian*_*ose 8

我曾经在一个项目上工作,每个客户都可以设置系统的方式非常灵活,我们发现的唯一好的设计就是为客户提供一个C#编译器!

如果规范中填充了以下单词:

  • 灵活
  • 插入
  • 定制

询问很多关于如何支持系统的问题(以及如何支付费用,因为每个客户都认为他们的案例是正常的,不需要任何插件.),就像我的经验一样

客户(或支持人员)编写插件的支持比架构要困难得多


BAL*_*aph 7

Usualy我使用MEF.Managed Extensibility Framework(简称MEF)简化了可扩展应用程序的创建.MEF提供了可用于加载应用程序扩展的发现和组合功能.

如果您有兴趣了解更多...


Jon*_*rdy 5

根据我的经验,创建灵活插件架构的两种最佳方式是脚本语言和库。这两个概念在我看来是正交的;两者可以以任何比例混合,就像函数式编程和面向对象编程一样,但在平衡时会发现它们的最大优势。库通常负责实现具有动态功能的特定接口,而脚本则倾向于强调具有动态接口的功能

我发现基于脚本管理库的架构似乎效果最好。脚本语言允许对较低级别的库进行高级操作,因此库不受任何特定接口的影响,将所有应用程序级交互留在脚本系统更灵活的手中。

为此,脚本系统必须有一个相当健壮的 API,具有与应用程序数据、逻辑和 GUI 的挂钩,以及从库中导入和执行代码的基本功能。此外,通常要求脚本是安全的,因为应用程序可以从写得不好的脚本中优雅地恢复。使用脚本系统作为间接层意味着应用程序可以更轻松地在发生Something Bad™ 的情况下自行分离。

打包插件的方式在很大程度上取决于个人喜好,但是使用简单界面的压缩存档永远不会出错,比如PluginName.ext在根目录中。