【问题标题】:How to design extensible software (plugin architecture)? [closed]如何设计可扩展的软件(插件架构)? [关闭]
【发布时间】:2010-09-24 07:18:58
【问题描述】:

我需要一些资源来讨论如何将您的软件设计为可扩展的,即,以便其他人可以编写为其添加功能的附加组件/插件。

你有什么推荐的?有没有讨论这个主题的书?
我更喜欢简明扼要的东西;一点理论和一堆具体的例子。

我不是针对特定的语言,我希望能够理解核心思想,以便我可以用任何语言实现它。

出于同样的原因,我不喜欢使用其他人构建的框架(除非框架不是非常高级,即不会隐藏太多太多),在那一刻我只想对这个主题进行自我教育并尝试各种方法来实现它。此外,框架通常假设用户了解该主题。

更新

我不是在询问 OOP 或允许我的类被继承。我说的是设计一个将部署在系统上的应用程序,这样它就可以在部署后由第三方插件进行扩展。

例如,Notepad++ 有一个插件架构,您可以在其中将 .dll 文件放置在 plugins 文件夹中,并为应用程序添加不存在的功能,例如颜色选择或 sn-p 插入,或许多其他东西(广泛的功能)。

【问题讨论】:

  • 我想您会发现大多数插件环境都提供了用于编写插件的基类。您的自定义第 3 方插件将从基类派生,并扩展它的“插件标准”功能。
  • 您会发现 Firefox 和 Notepad++ 等软件的可扩展性源于其 OO 设计根源。使您的类可扩展的同一原则将有助于使您的整个软件可扩展。

标签: language-agnostic plugins resources extensibility


【解决方案1】:

OSGI 是技术框架的一个很好的实际示例,可以让你做你想做的事。

theory is here

(free!) book is there

可扩展性和编写插件的能力必须处理服务生命周期

  • 现场添加/删除服务/插件
  • 管理服务之间的依赖关系
  • 管理服务的状态(声明、安装、启动、停止……)

What is OSGI for ?

模块的主要功能之一是作为部署单元……我们可以构建或下载并安装它以扩展应用程序的功能。

您会在 service 的中心概念上找到good introduction here(这与您的问题有关,并解释了围绕服务的一些问题,服务的关键组件可扩展性)。

摘录:

如果没有服务可以构建如此多的应用程序,为什么服务如此重要?好吧,服务是将软件组件彼此分离的最知名方式。

服务最重要的一个方面是它们极大地减少了类加载问题,因为它们使用对象的实例,而不是类名。由提供者而非消费者创建的实例。复杂度的降低是相当惊人的

服务不仅可以最小化配置,还可以显着减少共享包的数量。

【讨论】:

  • 什么是osgi?我查看了该网站,但我不明白它与我的问题有什么关系!
  • “现场添加/删除服务/插件”仅对持续运行的服务器类型应用程序真正有用;其他应用程序可以在启动时加载最新版本的插件。
【解决方案2】:

【讨论】:

  • Spooky,使用 C# 链接的插件架构的代码看起来与我曾经编写的 POC 完全一样。只缺少一件事:在运行时获取新模块的文件系统观察器。非常适合演示:“将 dll 放在此目录中,然后......瞧!一个新的菜单选择。”
  • 因为这个链接codeguru.com/cpp/misc/misc/plug-insadd-ins/article.php/c3879 而接受了,我一开始没有注意到!
  • 谢谢。阿桑特。舒克里亚。舒克兰。天急真。有义务的。谢谢。格拉西亚斯。阿里加托。谢谢。纳瓦兹语。
  • 非常有趣的东西!谢谢!
【解决方案3】:

与其重新发明轮子,不如使用现有的框架。 Eclipse 和 Netbeans 都支持基于插件的扩展。不过你必须使用 Java。

【讨论】:

    【解决方案4】:

    Checkout "CAB" - Microsoft 的Composition Application Building blocks Framework。我认为他们也有“网络版本”...

    【讨论】:

      【解决方案5】:

      我刚刚开始开发智能客户端应用程序。这是我正在考虑的两个选项。

      使用 Microsoft 的 System.AddIn 命名空间。看起来很有希望,但是对于我们的最终解决方案来说可能有点复杂。

      或智能客户端 - 来自 Microsoft 的 Composite UI Application Block

      最近,我研究了如何使用复合 UI 应用程序块和 System.AddIn 命名空间来构建自己的组件。由于 CAB 的源代码可用,因此很容易扩展。我认为我们的最终解决方案将是 CAB 的轻量级版本,肯定会使用 Unity Application Block

      【讨论】:

        【解决方案6】:

        当然还有著名的开闭原则——http://en.wikipedia.org/wiki/Open/closed_principle

        【讨论】:

          【解决方案7】:

          您尝试实现两个相互竞争的目标:

          1. 软件的组件必须大量暴露自己,以便它们可以重复使用
          2. 软件的组件必须很少暴露自己,以便可以重复使用

          说明:为了鼓励代码重用,您应该能够扩展现有的类并调用它们的方法。当方法被声明为“私有”并且类是“最终的”(并且不能扩展)时,这是不可能的。所以为了实现这个目标,一切都应该是公开的和可访问的。没有私有数据或方法。

          当您发布软件的第二个版本时,您会发现版本 1 的许多想法是完全错误的。您需要更改许多接口或代码、方法名称、删除方法、破坏 API。如果你这样做,很多人会转身离开。因此,为了能够发展您的软件,组件不得公开任何非绝对必要的内容 - 以代码重用为代价。

          示例:我想观察 SWT StyledText 中光标(插入符号)的位置。插入符号并不意味着扩展。如果你这样做,你会发现代码包含诸如“这个类在包 org.eclipse.swt 中”之类的检查,并且很多方法是私有的和最终的等等。为了实现这个功能,我不得不从 SWT 中复制大约 28 个类到我的项目中,因为一切都被锁定了。

          SWT 是一个很好用的框架,而且还可以扩展。

          【讨论】:

            【解决方案8】:

            插件架构因其可扩展性和灵活性而变得非常流行。

            对于 c++,Apache httpd 服务器实际上是基于插件的,但是使用了模块的概念。大多数 apache 特性都是作为模块实现的,比如缓存、重写、负载平衡,甚至线程模型。这是我见过的非常模块化的软件。

            对于 java,Eclipse 绝对是基于插件的。 Eclipse的核心是一个管理bundle的OSGI模块系统,插件的另一个概念。 Bundle 可以提供扩展点,我们可以在这些扩展点上轻松构建模块。 OSGI 中最复杂的是它的动态特性,这意味着可以在运行时安装或卸载包。不再有停止世界综合症!

            【讨论】:

              【解决方案9】:

              文章Writing Plugin-Based Applications 用一个非常简单的例子清楚地解释了架构各个部分的职责;提供源代码(VB.Net)。我发现它对理解基本概念很有帮助。

              【讨论】:

                【解决方案10】:

                这取决于语言。

                • 在 C/C++ 中,我很确定有一个 loadlibrary 函数允许您在运行时打开一个库并调用它的导出函数。这通常是在 C/C++ 中完成的方式。
                • 在 .NET 中,有反射,它提供与负载库类似(但更广泛)的功能。还有基于反射构建的完整库,例如托管扩展框架或 Mono.Addins,它们已经为您完成了大部分繁重的工作。
                • 在 Java 中,还有反射。还有用于 Eclipse IIRC 之类的 JPF(Java 插件框架)。

                根据您使用的语言,我可以推荐一些教程/书籍。我希望这会有所帮助。

                【讨论】:

                • “loadlibrary”:不在标准 C/C++ 中。
                【解决方案11】:

                如果您使用 .Net,我们的研究产生了两种方法:脚本和组合。

                脚本

                您可以通过使用脚本编排类来扩展类的功能。这意味着以动态语言公开以您最喜欢的 .Net 语言编译的内容。

                我们发现一些值得探索的选项:

                作曲

                如果您使用 .Net 4 或更高版本启动项目,则必须仔细查看 Managed Extensibility Framework (MEF)。它允许您以插件方式扩展应用程序的功能。

                托管可扩展性框架 (MEF) 是一个组合层,用于 .NET 提高了灵活性、可维护性和可测试性 大型应用程序。 MEF 可用于第三方插件 可扩展性,或者它可以带来松耦合的好处 普通应用程序的插件式架构。

                Managed Add-in Framework 也是一本好书。

                【讨论】:

                  【解决方案12】:

                  在您的应用程序中实施SOLID 原则。

                  1.单一职责原则: 一个类应该只有一个职责(即软件规范中只有一个潜在的变化应该能够影响类的规范

                  2.开闭原则:软件实体……应该对扩展开放,对修改关闭

                  3. Liskov 替换原则: 程序中的对象应该可以被其子类型的实例替换,而不会改变该程序的正确性

                  4.接口隔离原则: 许多客户端专用接口优于一个通用接口

                  5.依赖倒置原则: 应该依赖于抽象。不要依赖结石

                  Stackoverflow 问题:

                  Example of Single Responsibility Principle

                  Is the Open/Closed Principle a good idea?

                  What is the Liskov Substitution Principle?

                  Interface Segregation Principle- Program to an interface

                  What is the Dependency Inversion Principle and why is it important?

                  【讨论】:

                    【解决方案13】:

                    由于我没有足够的代表点来发表评论,因此我将其发布为答案。 SharpDevelop 是用于在 C#/VB.NET/Boo 中开发应用程序的 IDE。它有一个令人印象深刻的架构,允许以多种方式对其自身进行扩展——从新菜单项到对全新语言的开发支持。

                    它使用一些 XML 配置来充当 IDE 核心和插件实现之间的粘合层。它开箱即用地处理插件的定位、加载和版本控制。部署新插件只需复制新的 xml 配置文件和所需的程序集 (DLL) 并重新启动应用程序。您可以在原作者的“剖析 csharp 应用程序”一书中阅读更多相关信息 - 来自 here 的应用程序的 Christian Holm、Mike Krüger、Bernhard Spuida。这本书似乎在那个网站上没有,但我找到了一份可能还在here附近的副本@

                    还找到了一个相关的问题here

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2011-08-02
                      • 2014-08-07
                      • 1970-01-01
                      • 2011-05-23
                      • 1970-01-01
                      • 2014-09-25
                      • 2011-04-13
                      • 1970-01-01
                      相关资源
                      最近更新 更多