插件式构架设计经验

来源:互联网 发布:怎么测网络速度 编辑:程序博客网 时间:2024/05/17 03:07

1  只建议导出接口或者函数,使用标准类型变量,不建议导出复杂的类。

解释:

插件式编程就是最大化的解耦,模块全部放置于DLL中,并且每个DLL只导出标准的加载函数,由加载函数再次导出模块类接口。标准的加载函数都是C风格的。导出的类在修改的时候,不应该需要编译其他的模块。由于头文件的修改会引发其他模块的重新编译,因此建议不导出复杂的类,而采用比较简单的类,或者接口。在实现时,采用继承的方式,不破坏接口。

2  DLL无法导出模板类,在导出类中使用了模板类,也会引起大量的Warning,因此不建议在导出接口中使用模板类。

解释:

模板类属于不确定版本的代码,并且是源代码编译。不同版本的模板类实现可能不一样,这样就限制了插件开发工具与版本,插件尽量减少这方面的限制,COM做到了只限制操作系统,不限制开发语言,我们一般要做到限制开发语言和开发工具,但不要限制开发工具的版本,插件开发人员可以选择自己喜欢的类库。如果限制开发工具版本和库版本,此条可不算。

3  开发插件式系统,需要有一套好的公共库

解释:

由于插件式系统由各种模块组成,标准的参数类型已经不够用,比如字符串类,由于尽量不使用模板类,因此各个接口中只能使用原始的字符数组模式,这在Windows API中非常明显。如果要做一套好的插件式系统,像字符串这种类型,最好自己实现一个字符串类,供各个模块使用。在MFC库中,就实现了大量的基础类,如果我们允许非MFC库开发的话,那么是有必要提供一套这样的基础类的。各个插件可以使用自己熟悉的类,但导出接口中,只能使用公共的类。

4  尽量只提供UI线程给插件

解释:

各个模块都可以有属于自己的线程,但只应该自己使用,尽量不要和其他模块做交互,交互的接口或者函数尽量放在主线程,也就是UI线程中,防止线程互锁问题发生。如果不是必须,主模块尽量不提供多线程给插件。

5  避免时间长的函数,如需要使用异步机制

解释:

由于插件接口的调用,基本上都是在主线程中,因此一旦发生某个插件的某个函数超长的问题,会造成界面假死现象,不能因为一个插件造成如此问题。将同步的函数转成异步函数,这个事情放在插件中做比较好,如果主模块来做,造成了多个线程被插件使用,有可能发生死锁。

6  非核心插件不能抛异常

解释:

保证程序稳定运行是每个插件的责任,因为某个插件的问题而抛异常,插件抛出异常将整个程序崩溃的做法是不可取的。插件应该尽量控制可能出现的问题,并做好自己的处理,不要将问题抛给主模块来处理。我个人也不喜欢代码中抛异常的方式,C工作了这么多年,没有异常反而能把问题处理得非常好。C++语言效率赶不上C的地方,异常是最拖分的一块。

7  内存谁申请谁释放

解释:

内存的使用和释放,在Effective等文档中说过,在插件式编程中,全部是插件DLL,都不在一个模块内,因此内存的使用和释放问题更严重,这一点要在命名接口的时候,就做到。这一点我们可以模仿COM,各种接口的Delete都使用Release函数,由各个接口自己去释放自己,保证不出现申请和释放不是同一个模块的问题。

8  资源与多语言支持

现在的软件系统一般支持多语言模式,插件式系统,一般都采用自定义字符串的方式,也就是说字符串一般不放置于资源中,而是外部文件。对于各个模块自己的资源,在使用的时候,也需要小心,不能搞错了资源,而导致加载其他人定义的资源,从而引起资源混乱。