这一篇先从整体上讲述一下系统的各个模块,理一理系统的面目的形成过程。
首先明确的一点是这将是一个CS的系统,系统有离线的要求,而且更重要的是客户端要访问硬件设备,而且客户端的显示刷新是要达到准实时要求的,这些东西用BS的架构是难以实现的。
开发环境先确定下来就是VS.NET 2003、SQLServer 2000。当时VS2005及SQLServer 2005虽然已经越来越多的被使用,的确也是有比较多吸引人的特性,但对于非BS的开发来讲,于我看来优势不明显。而且相对来讲.Net Framework 1.1比起.Net Framework 2.0普及一点,以后部署也方便。
关于系统的分层理论现在都讲滥了,我这里就不详提了。这次开发系统其实是分为二个大程序的(其实小程序当然还有,不过都是依附于二个大的),前台显示与后台管理控制,为了避免混淆(有时后台一般又指DB Server之类的),以后统一把前台显示端统称为签到终端,把后台管理控制统称为管控端。
管控端,从物理上来讲就是一个二层的系统,一个DB,一个Application。现在着重点在签到终端,因为签到终端跟管控端是有关联的,签到终端要接受近控端的签到指令,管控端要汇集签到终端的签到数据。所以从签到终端那一边看来系统是分三个部分的,即Client-Application Server-DB Server。
现在考虑的是要不要把Client与DB Server隔离起来,这从理论上来讲比较的顺理成章,但经过一阵思虑后我最终放弃了这种比较诱人的想法。因为如果真那么做的话,势必要在Application Server上花费相当大的精力,虽然最初整个系统本身是没什么大的时间压力的,但也不能由此在一个看起来很美的东西上花费大量时间与精力。这样签到系统从前台看来就成了“三块二层”的一个三角形。
Client
Application Server DB Server
(以下如无特指Client专指签到终端,Application Server专指管控端)
整体的架构确定了下来,下面考虑二个比较重要的问题。一是签到终端与管控端之间用什么手段通讯;二是如何保证签到终端的离线运行。
通讯问题基本不用费什么脑筋就选定了用Socket,这也是旧系统的技术选择,简单有效。
离线运行问题,综合各方面考虑,还是用一个本地数据库(Local DB)来解决。其实这也是旧有系统的做法,但在如何利用本地数据库的问题上我跟旧有系统有很大区别。成功的离线应用的关键是把离线对系统的影响降到最低,对于客户端应用来说,离不离线差别是不大的,或察觉不出来的。
本想参照Offline Application Block的做法来实现离线功能,但我嫌它太过于繁琐(其实Microsoft的所有Application Block对于我的系统来说都过于繁琐)而弃之。鉴于签到过程中数据流量最大的是集中在存放签到记录的那个表,最终关心的也是那个表。我最终决定用远程的DB Server与Local DB的数据同步来隔离消除离线对于签到终端顺利工作的影响。本地既然有一个数据库那就充分利用之,签到终端的所有数据访问都从这里走。与此同时,开一个线程来同步DB Server与Local DB的签到记录,当在某个签到终端有新的签到记录时,在第一时间同步上传到DB Server,然后再同步到其他的签到终端的Local DB。网络正不正常只有这个线程清楚,也只有这个线程关心。
现在系统由之前的三角形变成了矩形:
Client Local DB
Application Server DB Server
从签到终端角度看,系统分为了以下几个模块:
1、 数据访问:Client与Application Server共用(1),为简单起见,DB Server与Local DB的数据表结构是一致的。
2、 通讯:Client与Application Server共用(2)。
3、 硬件访问:Client专有。
4、 数据同步:Client专有。Application Server只是一心一意的从DB Server取数据,它是不会知道Local DB的存在的。
5、 UI:Client与Application Server都有。
6、 公用模块:Client与Application Server共用。
注:(1)、后来其实二者并没有用严格上的同一个程序集。由于Client的数据同步也是要用到数据访问的,而由于数据同步是要访问二个数据库的,这就要Client的数据访问是可以随时切换Connection的,所以后来在Client上使用的数据访问模块,就增加了一个开关,而Application Server版本则加了个编译指令使这个开关不起作用。
(2)、Socket通讯在服务端与客户端的写法有区别,而且实际应用中签到终端与管控端发出与接收的指令是互反的,二者往外触发的事件也不同。最后实现时并没有把二者的通讯模块封装成一个。
模块上篇到此为止,而管控端模块划分在模块下篇里讲述,但接下来的总结(四)我不准备马上开讲模块下篇,而是按照去年进度的先后顺序先把签到终端解决个八九不离十再着手管控端。