最近比较烦躁,天气冷了,胃也渐渐感到不舒服,公司的伙食偏辣,感觉不太适应。公司近期有点动荡,新人没到岗,老员工却走了几个。闲下来我总会时不时地去想走过的路,我们把太多的实现花费在确定到底做什么以及所谓的怎么做上,真正做事的时间太少。越想越烦躁,于是就自己向老板请战,决定亲自把数据层的数据访问做了。老板想为我们的软件做个中枢神经系统,也就是他说的数据层,这个想法很不错——其实老板的很多想法都很好,很靠前,只是凭借我们目前的实力很难实现。这个中枢神经目前自然搞不定,我的想法就是先把数据保存下来,然后才是在这堆数据中抽取信息。也就是相当于设计多个传感器,将传感器获取的数据如何传递到中枢系统以及如何保存起来这个问题解决,至于传过来的是什么数据,怎么利用,我一概不管。这个我感觉得找个数据挖掘的专人来解决,我是无能为力了。
我把我们软件的通信分为内部通信和外部通信,内部通信指的是同一机器上的不同模块间的通信,主要指的是同机器上不同进程间的通信,也不排除同进程不同模块间通信。主要做的工作就是支持多种传输媒介,如文件、DB、管道、邮槽等。由于不同的传输媒介差异很大,我把这些媒介分为两类:能自己管理链路状态的,如套接字、命名管道等,和不能自己管理链路状态的。针对后者单独抽取一个数据收发接口,完成基本的数据收发。然后针对这个接口和能自己管理链路状态的几种媒介,又抽取了一个链路管理接口,然后采用一个统一的类完成资源管理。这样,这个类就为不同的媒介提供了一个统一访问的接口。内部通信的结构和ISO的OSI模型很类似。第一个接口类似物理层接口,完成不同媒介的特性统一;第二个接口相当于数据链路层,完成了链路管理;这个统一的类则类似工作在网络层,完成了统一的数据传输,并为数据分发分配必要的资源。IP路由功能在这里也能找到影子。每个数据包包含了一个分级的头部信息,我仿照MFC的消息分发表设计了一个数据分发表,通过头部信息将数据准确的路由到数据处理函数。
外部通信和内部通信的需求截然不同。由于我们的软件内部采用了多种开发平台及语言,某些平台及语言并不支持某些通信协议,因而内部通信的侧重点在多媒介的统一上,由于是在同一台机器上通信,安全性基本上可以不考虑,设计时仅仅用MD5加了一个校验值检测数据包的完整性。外部通信的媒介我只选择了一种:套接字。虽然其他的一些媒介也支持跨机器,如命名管道,邮槽等,但是这些都将或已经淘汰。外部通信的侧重点在安全性上。由于我们的客户端将大量采用P2P技术,安全性将是十分重要的。道高一尺,魔高一丈,每种加密算法都不是绝对的安全,因而我设计了一套动态加密算法。即客户端和服务器之间的通信是动态加密的,加密采用的算法和密钥都会每隔一个随机时间值而更换一次。加密算法及密钥是由服务器统一维护的,客户端只能检索当前的加密算法和密钥。为了保证客户端和服务器能够同步更换密钥,每次更换密钥或算法,客户端和服务器都要进行三次握手。
如何将内部通信类库和外部通信类库(我称它为安全通信类库)整合起来,向上提供一个统一的接口,这个问题让我一时难以抉择。由于我是先做完内部通信框架以及数据分发工作的,现在需要将安全通信类库集成进来,可以用两种方法,一种是添加适配器,将安全通信适配给内部通信框架的数据分发部分,这样就实现内部通信和安全通信的统一;另一种是编写针对外部通信的数据分发代码。第一种最好,但是难度比较大,可能需要修改很多代码,第二种简单,照葫芦画瓢就可以了。最终我选择了第一种,费了九牛二虎之力,最终还是实现了内部通信和安全通信的整合,收发的数据可以统一分发。
数据持久化部分我是模仿ADO.net做的,其中也加了点hibernate的思想。首先,我将DBMS的特性抽取出来一个接口,正对SQLite做了一个实现,然后将数据库表信息做了一封装,这样所有的数据库访问都将在这层封装上进行。这个工作目前没有完全让我满意,封装的还不是很到位。
最后一个问题是如何将这部分独立到一个模块中去。这个问题看似简单,实际不然。由于我封装的类很多都是需要导出给外界使用的,如果用导出类,则必须采用静态链接。还有些类是要分开实现的,比如说数据分发,我想将分发框架保留在这个模块中,而将分发表放到客户模块中采用类似消息分发表的方式实现。第一个问题我是用代理实现的。第二个问题我采用了一些一开始我都不敢相信自己这想法能行。呵呵,千万不要给C++的派生多态迷惑。成员函数就是一个函数,只是多了个this指针,静态成员就是一个实实在在的函数。虚函数也是个函数,只是有虚函数的类多了个vtable,只有数据成员才是一个对象实实在在的东西,这些和vtable构成了一个对象的实质。
这部分工作我自己现在可以说是很满意了,希望能在公司用起来。很多情况下往往事与愿违,做人做事,对得起自己良心就可以了,无需庸人自扰。渐渐地我看的开了,或者说渐渐地我没了菱角。可悲还是可喜,我自己也分辨不出来了