这段时间在对我们项目的代码进行重构,发现我们以往开发软件的时候耦合度非常高, 最严重的是很难对软件进行扩展和删减,现在对软件进行扩展的功能成本非常大
比如我们有一个模块a,当到打一定的时间,或者说条件后,需要调用它:
function()
{
function_a1()
function_a2()
function_a3()
}
这个时候软件还好,但是随着时间的增加,你需要加入b,c,d,e的功能,代码将会非常长,而且如果有时候我们需要阉割一些功能,或者说,我们需要增加一些功能,但是这个功能只是在某个客户所需求的,于是我们开始利用宏定义或者if语句配合配置文件来,达到所谓的扩展和删减功能,这样久了后,软件的主干部分是这样的:
function()
{
read_config()
if(need_a)
{
function_a1()
function_a2()
function_a3()
}
if(need_b)
{
function_b1()
function_b2()
.....
}
......
}
这样扩展下去后,你将会有两个问题:
配置文件膨胀
代码文件膨胀
在一个项目里面,不可能只有function这么简单的函数会用到其他的模块,可能你app init的时候,app destroy的时候,都需要因引用到其他模块,于是,这个问题会非常严重,而且在对一些客户进行定制开发的时候,他们也都需要在适当的时候调用对应的代码,于是不管在app init,app destroy或者其他地方,你总能看到一大堆的if语句,有时候我们要修改一个客户的功能,我们要先从几百个文件里面查找代码,然后在一个一个文件去修改
现在我们的一个配置文件有40+个配置项目,经常有时候出问题都不知道是哪个模块出问题,也不知道配置文件要怎么搞,一个cpp里面有6000+行代码,几乎include了整个系统的头文件,而且这个cpp里面实际上有3000+行都是针对单一客户的,也就是说,我们发一个版本给一个客户,实际上他也要了其他针对几十个客户的定制的模块
代码膨胀和配置文件膨胀是我们在维护上遇见的最大的问题
这样在团队开发的过程中,我们经常会遇见一个问题就是两个人都需要同时修改到function,如果一不小心,容易引起冲突,然后代码被覆盖掉,小乌龟在合并上做的不是很好,经常会提示冲突,需要手动解决,smartsvn在自动合并上就做得很好
耦合度太高也是我们团代配合时候经常会出现的问题
总之,这种开发模式下,我们的软件已经越来越复杂,维护越来越困难,从去年开始我开始思考如何做到更好的模块化,今年开始着手
就是引入了一个事件机制,当系统达到一定的条件后,将会去通知你,当然是前提你要告诉他,这个就是观察者模式,也可以说是sub/pub模式
比如像上面的function函数,我们模块a和模块b需要他调用,那么我们可以定义个虚基类,然后像function的管理类注册,到时间自动调用
如下:
class IModuleEvent
{
public:
virtual void OnEvent() = 0;
};
class EvtMgr
{
void RegisterEvt(IModuleEvent *evt)
{
m_EvtList.push_back(evt);
}
}
function()
{
for_each(EvtMgr.m_EvtList)
}
上面的是程序的核心部分,下面则是模块a
ModuleA:public IModuleEvent
{
ModuleA()
{
EvtMgr.RegisterEvt(this);
}
};
这样
- function不知道module a的存在,module a随时可以向EvtMgr注册事件,也可以随之滚蛋走人,就一句代码的事情,很容易扩展和删减
- module a的代码就肯定在模块,不会像之前那样散落在几十个地方,也不会造成代码冲突
基本就这样了,在对一个新的客户进行软件定制的时候,我开始对使用这套系统,虽然还没全部完成,但是到目前为止,我们已经可以很好的对新项目进行扩展和卸载,新的客户软件就是一个lib库,如果需要,那么我们让程序link我们的lib库就可以了
顺便说下,因为是使用lib库的原因,再者程序的核心部分并不知道有什么模块加入到这个软件里面,编译器不会主动去链接模块的lib,所以需要修改vs的强制符号引用,强制链接,后续可以通过改成dll来达到动态加载的目的
后续:
上面的程序使用了继承的方式,是不是觉得很麻烦,特别是在一个系统中,有几十个事件很正常,那岂不是要连续定义十多个class或者接口
其实现在已经有function和bind来取代虚函数了,推荐
http://blog.csdn.net/solstice/article/details/3066268
vs2010也自带了这个
再后续:
后续引入boost的signals2的库