ctkPlugin插件系统实现项目插件式开发

插件式开发体会:

自开始写【大话QT】系列就开始接触渲染客户端的开发,说是开发不如更多的说是维护以及重构,在接手这块的东西之前自己还有点犹豫,因为之前我一直认为客户端嘛,没什么技术含量,总是想做比较有挑战性的,为了这周总还专门找我谈了谈,算是“安抚”民心吧。正式谈话过后,我才决定接手渲染客户端的开发。

渲染客户端的所有构成均是采用开源框架拼凑起来的整体,细分它的组成大致包含以下开源模块,简单描述:

1> CTKPlugin插件系统框架。负责整个项目的架构,决定了项目采用插件形式开发维护。

2> Google protocol buffer。负责定义项目的通信协议,它是google内部使用的协议架构,最大的优点是:实现高效,向下兼容的通信协议。

3> Zeromq框架:负责项目中的网络通信,用于高性能网络编程。

4> 日志系统。负责项目中所有日志的输出。

其中,最为关键的就是CTKPlugin插件系统,它决定了项目的整体架构——采用插件式开发。经过这么多天的维护开发也深深的感受到这种插件式开发的方式带来的好处。以前,总是从课本上读到所谓的理想的“热插拔”式的插件开发,而我总是不以为然,我的意识里一个项目的开发多多少少都是臃肿的,在使用了这种插件式的开发方式后,突然感觉软件的开发、维护、升级变得很容易,下面说一下我体会到的几点好处:

1. 开发工作由之前的人等人变为并行开发。项目中插件系统分为两大部分:基础插件与应用插件,基础插件即通用插件,在其它插件系统中都要使用到的,比如:日志插件在每个其它插件中都会被使用;而应用插件之间则是相互独立的,比如:登录插件、文件管理插件等。基础插件一般是一些开源库,只需要我们编译出来使用即可,基本不需要我们自行开发;而应用插件功能的独立性决定了它们之间不会相互调用(业务整合插件除外),这样多个人员就可以独立开发,每个人负责一个独立的插件,项目进度会大大加快、周期缩短。

2. 测试案例容易编写,插件功能很方便得到验证。在一个插件的初始版本完成后,可以很方便的编写测试用例,来验证插件提供的功能性。由于插件系统最终提供的是动态链接库dll(windows下),而测试用例则可以建立为应用工程或界面工程,提供程序入口,加载调用插件中提供的方法。而且,测试用例可以保存在项目中(不会最终发布,最终发布的是插件的dll),如果将来插件使用出现问题,或者需要添加其它功能,或者升级均可以利用测试案例重新快速测试验证。

3. 系统业务逻辑变得异常清晰。如果项目不采用插件方式开发,每个功能均会杂糅在一起,无论是开发人员或者将来加入到项目开发的人都无法很快的了解业务流程,在分析这个功能的时候又涉及到那个功能。而采用插件式开发方式则每个业务逻辑很清晰明了,如果将来要调试3dmax的渲染模块,那么只需要阅读3dmax渲染插件就可以了,而且结合测试案例,很容易就可以上手。

上面就是这段时间以来针对项目采用插件系统开发的几点体会。

CTKPlugin插件系统介绍:

在CTKPlugin插件系统中要清晰地理解一个概念:插件是以服务的方式提供功能。每一个插件都有它的生命周期,在插件初始化的时候它会将自己的唯一实例注册到插件系统中作为服务提供,即上图中的register阶段。而当另一个插件需要使用到该插件提供的服务的时候就需要通过getService的方式获取。下面通过代码简单说明一下一个插件是如何想CTKPlugin系统中注册服务以及其它插件是如何使用该服务的:

1.  插件服务注册

每一个插件的实现都必须实现一个插件的声明周期类,它继承自CTKPlugin中的ctkPluginActivator,在ctkPluginActivator中定义了start与stop虚函数,插件的声明周期类必须要实现start与stop,实现服务的注册。

[cpp] view plaincopy

  1. class LHAuthPlugin : public QObject, public ctkPluginActivator
  2. {
  3. Q_OBJECT
  4. Q_INTERFACES(ctkPluginActivator)
  5. public:
  6. void start(ctkPluginContext *Context);
  7. void stop(ctkPluginContext *Context);
  8. private:
  9. LHAuth *m_Auth;
  10. };

实现类:

[cpp] view plaincopy

  1. void LHAuthPlugin::start(ctkPluginContext *Context)
  2. {
  3. m_Auth = new LHAuth();
  4. Context->registerService(QStringList("LHAuthInterface"), m_Auth);
  5. }
  6. void LHAuthPlugin::stop(ctkPluginContext *Context)
  7. {
  8. Q_UNUSED(Context)
  9. if (m_Auth)
  10. {
  11. delete m_Auth;
  12. m_Auth = 0;
  13. }
  14. }

其中:registerService即向CTKPlugin插件系统中注册该插件的唯一实例,而stop则是插件声明周期的终止。

2. 使用其它插件提供的服务

在其它模块中如果想使用登录认证插件,则在其它模块的Init阶段完成登录认证模块的加载,并完成初始化的功能:

[cpp] view plaincopy

  1. //! 初始化登录模块
  2. ctkServiceReference refAuth= d->m_PluginContext->getServiceReference("LHAuthInterface");
  3. d->m_AuthInterface = (qobject_cast<LHAuthInterface *>(d->m_PluginContext->getService(refAuth)));
  4. if (!d->m_AuthInterface ||
  5. (d->m_AuthInterface->Init(d->m_Parameters) != LH_SUCCESS) ||
  6. (d->m_AuthInterface->CreateInstance(varInstance, d->m_Parameters) != LH_SUCCESS))
  7. {
  8. qDebug()<<QObject::tr("Module %1 is invalid").arg("com.lht.auth");
  9. return LH_FAILURE;
  10. }
  11. else
  12. d->m_nAuthInstance = varInstance.toInt();

getServiceReference()即在CTKPlugin插件系统中获取LHAuthInterface服务。在初始化完成之后,就可以利用m_AuthInterface->Login()来使用登录认证插件提供的功能了。

项目如何使用插件式开发:

如上图所示,只是我这个项目本身实现插件系统功能的一个基本架构,相信不同的人使用会探索出更加有效,更加方便的使用方式。

每个项目都会有它的入口,我们不妨称之为portal,在portal中实现的功能很简单,最主要的就是完成CTKPlugin系统的初始化工作,待ctkplugin初始化完成之后首先加载lht_controller插件,lht_controller插件是很重要的一个插件,它主要负责完成其它所有应用插件的加载工作,如上图所示,它加载了lht_login登录插件、lht_mayaMaya渲染插件、lht_log日志插件、lht_goldenfarm渲染客户端插件(业务逻辑插件),然后执行业务逻辑插件,即lht_goldenfarm,而在lht_goldenfarm中根据业务逻辑实现不同的功能,调用不同的插件。

看上面的架构,很清晰明了,对于系统的维护很方便、容易。

本章总结:

好了,以上就是我这段时间开发收获到的东西,很多东西都是我以前开发中不注意的,现在慢慢当成规则严格要求自己,争取让自己的开发更加规范。

只有不断总结才能不断进步,还是验证了周总的那句话:“还是太年轻啊!!”。

时间: 2024-11-05 01:27:31

ctkPlugin插件系统实现项目插件式开发的相关文章

MEF 插件幸运飞艇平台出租式开发 - DotNetCore 中强大的 DI

背景叙述在前面几篇幸运飞艇平台出租(www.1159880099.com)QQ1159880099 MEF 插件式开发 系列博客中,我分别在 DotNet Framework 和 DotNet Core 两种框架下实验了 MEF 的简单实验,由于 DotNet Framework 由来已久,因此基于该框架下衍生出的很多优秀的 MEF 框架较多.但是对于 DotNet Core 来说,情况有所不同,由于它本身对 DI 内置并提供支持,因此我尝试使用它的全新 依赖注入(DI) 来做一些实验. 动手实

【大话QT之十五】ctkPluginFrameWork插件系统Windows下编译

使用ctkPluginFramework作为插件系统框架的确有着众多开发上的优势.最近收到一些站内信,大家都想使用ctkPluginFramework但是不知道如何编译,这篇教程就来讲一讲ctkPluginFramework插件系统在Windows下的编译过程. 准备条件: 1. 安装Git,我们通过它来下载CTK的源码. 2. 安装CMake,我们用它来生成vs下的sln解决方案文件. 相关站点: 1. CTK的官网:http://www.commontk.org/index.php/Main

android基于插件式开发

之前没有听过app插件式开发今天就做一下学习的笔记.这里的插件式开发通俗的讲就是把一个很大的app分成n多个比较小的app,其中有一个app是主app.网上查了一下采用了这种开发模式的有支付宝客户端.QQ换肤其他的就不得而知了有人说微信也是基于插件的但是微信在更新的时候会下载全部的应用程序把旧的完全覆盖所以猜想应该目前不是吧. 基于插件的开发列举两个比较突出的优点: 1.应用程序非常容易扩招,比如有一个新的领域要加到旧的应用程序中来只需把这个新的领域做为一个插件,只开发这个小的app就可以了旧的

Android应用插件式开发解决方法[转]

一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来越多,APK安装包也越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块.此时可能就需要考虑如何分拆整个应用了. 二.解决方案提出 一般有两种方式,一种是将应用按照功能分拆成多个应用,用户需要哪个就下载哪个,都需要就都下载.应用之间,可以在代码层面做一定的关联,以共享部分信息.另一种方式,类似于其他平台插件的方式,用户可以在主应用中可以选择性的下载需要的插件,不需要该功能,则不需要下载. 第一种

从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装

标题:从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11343141.html 源代码:https://github.com/lamondlu/DynamicPlugins 前情回顾 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.NET Core MVC的插件式开发(二

从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11717254.html 源代码:https://github.com/lamondlu/DynamicPlugins 前景回顾 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.NET Core MVC的插件

从零开始实现ASP.NET Core MVC的插件式开发(五) - 插件的删除和升级

标题:从零开始实现ASP.NET Core MVC的插件式开发(五) - 使用AssemblyLoadContext实现插件的升级和删除作者:Lamond Lu地址:https://www.cnblogs.com/lwqlun/p/11395828.html源代码:https://github.com/lamondlu/Mystique 前景回顾: 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.N

.NET简谈插件系统开发模式

摘选自[王清培]博客 http://www.cnblogs.com/wangiqngpei557/archive/2011/06/10/2077413.html 今天跟大家分享一下我们在日常开发中并不常用的开发模式“插件系统模式”,什么叫插件,从大一点的概念讲就是我们开发的软件是由很小的模块组成,每一块都能成功的装卸,使我们的软件成为一个有机体,在发生重大事故.改良优化等等的时候,我们不需要重新编译我们的系统就能很方便的进行升级替换进行使用:这样的开发模式就是插件系统开发模式:这个概念很大,每个

也来学学插件式开发

上一家公司有用到插件式开发来做一个工具箱,类似于QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了.可惜在那家公司待的时候有点短,没有好好研究一下.现在有空,自己在网上找了些资料,也来试试. 主要思路:公开一个插件接口,如果.DLL或.EXE的代码中有继承这个接口就将其示为插件,并将这些插件放在同一目录.运行程序的时候扫描目录并通过反射判断.DLL或.EXE中是否存在该接口,若存在,则当作插件加载进来. 我们来做一个示例看看.例子也是在园子里找的,自己改了一下,详见:http://w