总想写一些东西,但总是发现想写的内容还没积累到可以写出来的程度。没有压力是不行的,至少每月得来那么一次才对,不然就闹出人命了。^3^
很羡慕那些做题的同学,每道题的算法都可以发一篇博文,可惜我多数情况下都看不懂也就不细看。不过有空的时候细看一篇,google其中理论,还是很长见识的。很久前我就看过一篇最大流最小割的,大学学过忘了,这次算记住了。
1.虚函数vs回调函数
可能通过继承进行复用真不是什么好东西。
最初为bo2服务器组设计通信层的时候,使用的socket c++wrap lib的设计理念是通过继承来对模式化的网络编程代码进行复用,以及通过实现指定的虚函数来开展应用上的业务。
1 class TcpSocket
2 {
3 virtual void OnRead();
4 virtual void OnConnect();
5 virtual void OnDisconnect();
6 };
这样的接口,一看便知。最接近基本认识的做法,就是继承TcpSocket,然后按业务需求实现那些虚函数。
第一版的bo2服务器组就是在这种想法下实现通信层的。这造成了一些问题,服务器组里面有很多服务器,每个服务器需要的TcpSocket子类并不是完全一致的,毕竟不同的连接处理的消息都不太一样,于是TcpSocket的子类的数量就写的有些多了,而且每个服务器都写。
不久后,以将通信层划入一个独立的线程为契机,重构开始了。因为对第一版的设计不甚满意加上多线程的情况下无法直接给应用层拿着TcpSocket的指针(这个库默认情况自动析构已断开的Socket对象),最终的手段是,实现唯一的TcpSocket子类,在虚函数中统一的调用3个与之对应但全局唯一的回调函数。于是,第二版展现的是,每个服务器都有一个类似network的模块,实现这3个回调函数,不同的连接如果有不同的代码的话,则根据连接的id进行跳转。
总算砍断继承的锁链了。
不过事情并没有在这里就完全结束了。bo2服务器组并不会仅仅只有当前这些数量的服务器,以后随着新的需求而将不断增加,如何能让新来的同学更快的开发新的业务服务器而不必在通信层上花费任何精力呢,答案就是把每个服务器的network模块统一并入appbase中。
只是连接上某个服务器并不能成为bo2服务器组的一分子。连接谁,连接上之后要交代什么信息,这都是有规定的。而这些工作都是在每个服务器的network模块单独做的,势必不能让新同学为这些差不多重复的代码而烦恼。
多数类似的服务器的network模块并入appbase并不算太难,不过困难的是一些核心服务器,他们不太一样,很多连接需要好几个不同的onconnect和ondisconnect回调,可是第二版使用的是全局唯一的回调,而且现在也带着默认代码隐藏到appbase里了。
修改了一下,最终我让每个连接都可以指定自己独有的onconnect和ondisconnect回调,但是新同学不必担心这个,因为他们什么也不需要指定和实现,他们只要在service模块中专心处理消息就可以了。
绕了三版,得出的是每个连接都可以指定不同回调函数的方案(onRead是统一的),就跟TcpSocket的三个虚函数一样,想想都好笑。不过有了继承不是复用的好方式这种想法,算是一种收获吧。
2.统一的定义stl库包含头
几天前出了个bug,就是debug运行正常,release运行崩溃那种,崩溃的位置在一处list<t>::begin()调用上。最终查证的结果是因为bo2项目通过一些stl宏对stl容器进行了裁减,统一用std_inc.h导入stl库,而崩溃的地方是很早的代码,直接包含的是stl库文件,引起不同编译单元中对这个容器大小认识不一致,运行时崩溃。
结论是,如果在项目中使用stl库,那么将所有常用的stl头文件都写在一个std_inc.h中,在使用stl的模块中包含该文件,而不是其他,并建立预编译头导入该文件,就能避免出现类似的问题。
出bug的时候,完全不知如何下手,只好完全依赖更NB的同学,看着人家把崩溃的代码拷到刚创建对象的地方,调试未崩,然后再在创建对象的地方调用崩溃代码所属的函数,调试崩溃。翻到我写的类的头文件中include的几行说,stl容器大小不一致。
看得我是一脸惭愧。
3.
我蛮喜欢看包子山同学的GWeekly系列,不过他最近都不更新了。每周都写博我是抗不住的,每月勒令自己的话,还是能唠叨些文字的。仿照GWeekly的命名,我也来一个month-flow系列吧,实在没有成体形的内容可写的情况下,每月必定唠叨一篇。
posted on 2009-06-07 21:46
LOGOS 阅读(1711)
评论(1) 编辑 收藏 引用 所属分类:
month-flow