如何设计可扩展软件(插件体系结构)?[关闭]


75

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

你有什么建议吗?有没有讨论该主题的书?
我希望简短而切合实际的东西;一些理论和一些具体的例子。

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

并且出于同样的原因,我不希望使用其他人构建的框架(除非该框架不是非常高级,即不会隐藏太多),此刻我只想对自己进行主题并尝试各种实现方式。另外,框架通常假设用户对主题的了解。

更新

我不是在问OOP或允许我的类被继承。我说的是设计一个将部署在系统上的应用程序,以便在部署后可以由第三方加载项扩展。

例如,Notepad ++具有一个插件体系结构,您可以在其中将.dll文件放置在plugins文件夹中,并且它为应用程序添加了不存在的功能,例如颜色选择,代码段插入或许多其他功能。 (广泛的功能)。


我认为您会发现大多数插件环境都提供了用于编写插件的基类。您的自定义第三方插件将从基类派生,并扩展其“插件标准”功能。
Kieveli

3
您会发现Firefox和Notepad ++之类的软件的可扩展性源于其OO设计根源。使您的类具有可扩展性的同一主体将有助于使您的整个软件具有可扩展性。
orokusaki 2010年

Answers:


25

1
怪异的是,使用C#链接的插件体系结构所编写的代码与我曾经编写的POC完全相同。只缺少一件事:一个文件系统监视程序,用于在运行时拾取新模块。非常适合演示:“将dll放入此目录,然后……瞧!一个新的菜单选择。”
古格

1
由于这个链接codeguru.com/cpp/misc/misc/plug-insadd-ins/article.php/c3879而被接受,而我最初并未注意到它!
哈森

谢谢。阿桑特 舒克里亚。舒兰 天九河 义务。谢谢 格拉西亚斯。阿里加托。谢谢。纳瓦什语。
bugmagnet

真的很有趣的东西!谢谢!
Sander Versluys 2010年

16

OSGI是技术框架的一个很好的实际例子,可以帮助您完成所需要的工作。

理论是在这里

(免费!)书是有

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

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

OSGI的作用是什么?

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

您将在这里找到有关服务的中心概念的很好的介绍(与您的问题有关,并解释了围绕服务的一些问题,可扩展性的关键组成部分)。

提取:

如果没有它们就可以构建这么多的应用程序,那么为什么服务如此重要呢?好吧,服务是使软件组件彼此分离的最著名的方法。

服务最重要的方面之一是,由于它们使用对象的实例而不是类名,因此可以极大地减少类加载问题。由提供者而非使用者创建的实例。降低复杂性非常令人惊讶

服务不仅使配置最小化,而且还大大减少了共享软件包的数量。


什么是osgi?我查看了该网站,但不知道它与我的问题有什么关系!
哈森


“当场添加/删除服务/插件”仅对连续运行的服务器类型应用程序真正有用;其他应用程序在启动时可以加载插件的最新版本。
拉德瓦尔德

5

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

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

2.开放/封闭原则:软件实体…应该开放以进行扩展,但封闭以进行修改

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

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

5.依赖倒置原则: 应依赖抽象。不依赖具体

Stackoverflow问题:

单一责任原则示例

开放/封闭原则是个好主意吗?

Liskov替代原理是什么?

接口隔离原理-编程接口

什么是依赖倒置原则,为什么重要呢?


4

您尝试达到两个相互竞争的目标:

  1. 您的软件组件必须具有很多自身功能,因此可以重复使用
  2. 您的软件组件必须很少公开,因此可以重复使用

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

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

示例:我想观察SWT StyledText中光标(插入符号)的位置。插入符不打算扩展。如果这样做,您会发现代码中包含诸如“是否是org.eclipse.swt包中的此类”之类的检查,并且许多方法是私有的,final的以及诸如此类的方法。为了实现此功能,我必须将SWT中的约28个类复制到我的项目中,因为所有内容均已锁定。

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



2

好吧,这取决于语言。

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

根据您使用的语言,我可能会推荐一些教程/书。我希望这可以帮到你。


“ loadlibrary”:在标准C / C ++中不存在。
拉德瓦尔德


0

结帐“ CAB”-Microsoft的Composition Application构建模块框架。我认为他们也有一个“网络版本” ...


0

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

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

或Microsoft的Smart Client- Composite UI Application Block

最近,我研究了使用Composite UI Application Block和System.AddIn命名空间这两个组件来构建自己的组件。由于源代码可用于CAB,因此很容易扩展。我认为我们的最终解决方案将是使用CAB的轻量级版本,最终使用Unity Application Block


0

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

对于c ++,Apache httpd服务器实际上是基于插件的,但是使用模块的概念代替。大部分的Apache功能都是作为模块实现的,例如缓存,重写,负载平衡,甚至线程模型。这是我见过的非常模块化的软件。

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


0

如果使用.Net,我们的研究将得出两种方法:脚本编制和组合。

脚本编写

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

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

组成

如果您使用.Net 4或更高版本启动项目,则必须对托管扩展框架(MEF)有所了解。它允许您以插件方式扩展应用程序的功能。

托管扩展框架(MEF)是.NET的组合层,可提高大型应用程序的灵活性,可维护性和可测试性。MEF可以用于第三方插件的可扩展性,也可以将松散耦合的类似插件的体系结构的优点带给常规应用程序。

托管加载项框架也很不错。


0

由于我的代表点不足以发表评论,因此我将其发布为答案。SharpDevelop是用于在C#/ VB.NET / Boo中开发应用程序的IDE。它具有令人印象深刻的体系结构,可以通过多种方式进行扩展-从新菜单项到对全新语言的开发支持。

它使用一点XML配置作为IDE核心和插件实现之间的粘合层。它可以立即处理插件的定位,加载和版本控制。部署新插件仅需复制新的xml配置文件和所需的程序集(DLL),然后重新启动应用程序即可。您可以在此处阅读该应用程序的原始作者克里斯蒂安·霍尔姆(Christian Holm),迈克·克鲁格(MikeKrüger),伯恩哈德·斯普达(Bernhard Spuida)所著的《剖析csharp应用程序》一书中的更多内容。该书似乎在该网站上不存在,但我发现这里可能仍存在该书的副本。

在这里也找到了相关问题


-8

与其重新发明轮子,不如直接使用框架。Eclipse和Netbeans都支持基于插件的扩展。但是,您必须使用Java。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.