如何devise可扩展的软件(插件架构)?
我需要一些资源来讨论如何devise你的软件是可扩展的,也就是说,让其他人可以编写增加function的插件/插件。
你有什么build议? 那里讨论这个问题的任何书籍?
我更喜欢那些简短而重要的东西; 一些理论和一些具体的例子。
我并不是针对特定的语言,而是希望能够理解核心思想,以便我能够用任何语言来实现它。
出于同样的原因,我宁愿不使用其他人构build的框架(除非框架不是非常高级的,即不会隐藏太多的框架),目前我只想教育自己主题和实验方法来实现它。 此外,框架通常假设用户对该主题的了解。
UPDATE
我不是在问OOP还是让我的类inheritance。 我正在讨论如何devise一个将部署在系统上的应用程序,以便在部署后可以通过第三方附件进行扩展。
例如,Notepad ++有一个插件体系结构,您可以将一个.dll文件放在plugins文件夹中,并为不在其中的应用程序添加function,例如颜色select,插入代码或其他许多function(广泛的function)。
如果我们正在谈论.NET,请尝试在CodeProject上使用VBScript脚本编写.NET应用程序 。 那里有很多具体的例子。
以下是实施各种应用扩展技术的网站
- ClearScript – 为.NET应用程序提供V8,VBScript和JScript
- CS脚本 – C#脚本引擎
- 使用C#的插件架构
- 意见插件体系结构
- 关于Eclipse插件体系结构的注意事项
- 初学者插件架构框架
- 壁虎插件架构
- Fungimol插件的体系结构
OSGI是一个技术框架的一个很好的实际例子,可以做你以后的事情。
理论在这里 。
(免费!)书在那里 。
扩展性和编写插件的能力必须处理服务生命周期
- 当场添加/删除服务/插件
- pipe理服务之间的依赖关系
- pipe理服务状态(声明,安装,启动,停止…)
什么是OSGI?
模块的主要function之一是作为部署的单元…我们可以构build或下载和安装的某些东西来扩展应用程序的function。
你会在这里find一个很好的介绍 ,关于服务的中心概念(与你的问题有关,解释服务的一些问题,可扩展性的关键组件)。
提取:
为什么服务如此重要,如果有这么多的应用程序可以没有他们呢? 那么,服务是将软件组件彼此分离的最有名的方法。
服务最重要的一个方面是,它们显着减less了类加载问题,因为它们处理对象的实例,而不是类名。 由提供者创build的实例,而不是消费者创build的实例。 复杂性的降低是相当令人惊讶的
服务不仅使configuration最小化,而且还显着减less了共享包的数量。
你试图达到两个相互竞争的目标:
- 你的软件的组件必须暴露很多自己,所以它们可以被重用
- 你的软件的组件必须暴露自己很less ,所以他们可以被重复使用
说明:为了鼓励代码重用,您应该能够扩展现有的类并调用其方法。 当这些方法被声明为“private”并且这些类是“final”(并且不能被扩展)时,这是不可能的。 所以要实现这个目标,一切都应该是公开的。 没有私人数据或方法。
当你释放第二个版本的软件时,你会发现版本1的很多想法是错误的。 您需要更改许多接口或您的代码,方法名称,删除方法,破坏API。 如果你这样做,很多人会转身离去。 所以为了能够发展你的软件,组件不能暴露任何非必要的东西 – 代码重用的代价。
例如:我想在SWT StyledText中观察光标(插入符号)的位置。 脱字符不意味着延长。 如果你这样做,你会发现代码包含的检查是“包是org.eclipse.swt中的这个类”,还有很多方法是私有的,最终的,以及什么。 为了实现这个function,我不得不将大约28个课程的SWT复制到我的项目中,因为一切都被locking了。
SWT是一个很好的框架来使用和地狱扩展。
在您的应用程序中实施固体原则。
1.单一责任原则:一个class级应该只有一个责任(即只有一个软件规范的潜在变化应该能够影响class级的规范
2. 打开/closures的 原则:软件实体…应该是开放的扩展,但closures修改
3. Liskovreplace原则:程序中的对象应该可以replace其子types的实例,而不会改变该程序的正确性
4.接口隔离原理:许多客户端接口比一个通用接口更好
5.依赖倒置原则: 依靠抽象 。 不要依赖于结核
Stackoverflow问题:
单一责任原则举例
开放/封闭原则是一个好主意吗?
什么是Liskov替代原则?
接口隔离原理 – 编程接口
什么是依赖倒置原则?为什么它很重要?
当然有着名的开放封闭原则 – http://en.wikipedia.org/wiki/Open/closed_principle
那这取决于语言。
- 在C / C ++中,我非常确定有一个loadlibrary函数允许您在运行时打开一个库并调用它的导出函数。 这通常是如何在C / C ++中完成的。
- 在.NET中,有reflection,这是提供类似(但更广泛)的加载库。 还有整个图书馆都build立在reflection上,比如托pipe扩展框架,或者Mono.Addins,它们已经为你完成了大部分繁重的工作。
- 在Java中,也有reflection。 JPF(Java插件框架)就是用于像Eclipse IIRC这样的东西。
根据你使用的语言,我可以推荐一些教程/书籍。 我希望这可以帮到你。
文章编写基于插件的应用程序使用一个非常简单的例子清楚地解释了架构各个部分的责任; 源代码提供(VB.Net)。 我发现它对理解基本概念非常有帮助。
结帐“CAB” – 微软的组合应用构build模块框架 。 我认为他们也有一个“networking版”…
我刚开始开发一个智能客户端应用程序。 这是我正在考虑的两个选项。
使用Microsoft的System.AddIn命名空间。 看起来非常有希望,但是对于我们的最终解决scheme来说可能有点复杂。
或者来自Microsoft的智能客户端 – 复合UI应用程序块
最近,我已经考虑将组件用户界面应用程序块和System.AddIn命名空间构build成我自己的组件。 由于源代码可用于CAB,所以很容易扩展。 我认为我们的最终解决scheme将是CAB的轻量级版本,明确使用Unity应用程序块
插件架构由于其可扩展性和灵活性而变得非常stream行。
对于c ++,Apache httpd服务器实际上是基于插件的,但是使用了模块的概念。 大部分的apachefunction都是作为模块来实现的,比如caching,重写,负载均衡,甚至是线程模型。 这是我见过的非常模块化的软件。
而对于Java,Eclipse绝对是基于插件的。 Eclipse的核心是一个pipe理bundle的OSGI模块系统,另一个是插件的概念。 Bundle可以提供扩展点,我们可以用较less的努力来构build模块。 OSGI中最复杂的是它的dynamic特性,这意味着bundle可以在运行时被安装或卸载。 没有停止世界综合症了!
如果你使用.Net,我们的研究产生了两种方法:脚本和组合。
脚本
您可以通过使用脚本编排它们来扩展类的function。 这意味着以dynamic语言展示您最喜欢的.Net语言编译的内容。
我们发现一些值得探索的选项:
- IronPython的
- IronRuby的
- JavaScript: Jint , Jurassic和JavaScript .Net是很好的起点。
- Script.Net – >这是第一个引起我们注意的地方。
组成
如果您使用.Net 4或更高版本启动项目,则必须仔细阅读托pipe扩展性框架(MEF)。 它允许你以插件的方式扩展你的应用程序的function。
托pipe扩展性框架(MEF)是.NET的组合层,可提高大型应用程序的灵活性,可维护性和可testing性。 MEF可以用于第三方插件的可扩展性,或者它可以将松散耦合的插件式架构的优点带给常规应用程序。
托pipe加载项框架也是一个很好的阅读。
- MSDN: http : //msdn.microsoft.com/en-us/library/dd460648.aspx
- Codeplex: http : //mef.codeplex.com/
由于我没有足够的代表点发表评论,我张贴这个答案。 SharpDevelop是一个用于在C#/ VB.NET / Boo中开发应用程序的IDE。 它有一个非常令人印象深刻的架构,允许以多种方式扩展 – 从新的菜单项到开发支持全新的语言。
它使用一些XMLconfiguration作为IDE核心和插件实现之间的胶合层。 它可以处理插件的定位,加载和版本控制。 部署新插件只需简单地复制新的xmlconfiguration文件和所需的程序集(DLL)并重新启动应用程序即可。 您可以在这里阅读原作者Christian Holm,MikeKrüger,Bernhard Spuida所着的“分解csharp应用程序”一书中的更多内容。 这本书似乎没有在该网站上,但我find了一个副本,可能仍然在这里
在这里也find了相关的问题
而不是重新发明轮子,使用手中的框架。 Eclipse和Netbeans都支持基于插件的扩展。 你必须在Java中工作。