第一次用EXE+BPL+DLL项目总结
前段时间研究了一下BPL方式的开发,刚好最近有个小项目,于是尝试了一下,项目已完成。
有一些心得和体会,写下来与大家分享,请大家提出不足,另外有在研究BPL方面的朋友,有问题可以大家
共同探讨,以便进得更快一些。
关于一个项目的总结 ( EXE+BPL+DLL 模式)
以前一直采用一个独立的EXE文件的方式做项目,当时的感觉就是方便,不用考虑得太多,把所有的业务逻辑功能
做完后,编译成一个EXE执行文件就OK了,因为一直没有研究过BPL这种框架的编程,最近研究了一下,感触很深,
这种模式才是更方便的。而且对于团队模式更是方便,只要把各Team的BPL拿来就完成了。基于这种思想,最近应
用到一个新的项目上,已初见成效,现对这个项目总结如下:
一、规划
BPL框架编程规划很重要,一个项目要分成N个BPL,每个BPL的作用、分工在分析时必须确定下来,这一点很重要。
本项目分为以下几种包:
(1)、DBCommon.bpl --> 数据模块包,包括数据模块、数据库读写类模块 (数据访问层)
(2)、pubComon.bpl --> 公共函数、过程单元,公共变量单元、自定义结构类型单元、自定义类单元
(3)、BaseForm.bpl --> 所有窗体的基类单元、业务逻辑基类窗体单元
在(3)的基础上,按照不同的业务逻辑,建立不同业务的业务包,例:A.bpl,B.bpl,C.bpl......
(4)、A.bpl --> 业务包1
(5)、b.bpl --> 业务包2 ......根据业务逻辑的分类,建立不同的业务包。
二、设计
包的应用是有先后的,一些基础包必须首先建立好,以便供其他包在建立时被应用,基础包在修改后,所有应用该
基础包的必须重新编译,而且顺序不能搞错。例: DBCommon.bpl-->BaseForm.bpl-->A.bpl 当DBCommon.bpl修改并
重新编译后,后面两个包必须重新编译,且先编译BaseForm.bpl,后编译A>bpl
BaseForm.bpl包中有整个项目的基类窗体单元,以及从该基类窗体继承的业务逻辑基类窗体单元,在基类窗体单元
中将整个项目的风格统一、包括字体,各控件包括第三方控件的样式、颜色等做到了规范统一,窗体关闭时应该释放的
内容等。而基类窗体的相关风格、样式是由主程序EXE在初始化时进行布局,这样如果想换风格,只要在公共变量单元中
修改相关的内容即可。
( 注:本项目没有使用皮肤,只是通过颜色等风格进行控制 )
例1:为了使DevExpress组件的风格与整个项目的风格一致,特别是TcxGrid在选用dxOffice11样式时的颜色,
因为dxOffice11默认的颜色是采用深蓝色的那种,为了使TcxGrid的颜色与整个项目的颜色配套,就必须
调整,包括线的颜色,这个设置在EXE初始化时得到了安排,这样设计后,整体效果比较理想。
例2:项目中也采用了第三方控件RZ组件,这也是一个很好的三方控件,这个控件也有一个很好的样式统一控件,
只要控制好就可以与项目的风格融合到一起了。例TrzFrameController、TrzMenuController等,就是为了
统一风格而使用的。设置好这两个非可视控件的样式,就可以达到控件所有使用这个风格的控件了。而主
程序只要在初始化时,设置它们的风格就可得到一劳永逸的效果。
三、调用
框架确定了,包功能完成了,余下来就是主EXE载入Bpl运行了。载入包分为动态和静态两种方式。根据业务的规
划,三种基础包DBCommon.bpl,pubComon.bpl,BaseForm.bpl是静态载入,由主EXE编译时加入作为必须使用的
运行包。其他包由根据业务功能动态加载读取运行。
动态加载显示Bpl中窗体的方式分两种:一种是融合在主EXE窗体的PageControl上,另一种是ShowModal模式。
这两种方式是可以调整的,只要修改一个数据库中表中的字段,就可以达到效果而不要修改主EXE,这样的安排
确实很方便。
以前做独立EXE程序时,都是通过TActionList手动将所有的功能建好后,再与菜单、按钮进行绑定(设置Action),
工作量确实很大,本项目中没有采用TActionList,而是通过一个TtreeView实现了所有的功能,在主EXE运行读取
权限功能时,一次读取功能权限表,加载允许使用的权限到TtreeView上,通过定义一个记录类型,来记录bpl名、
表单类名及其他内容,并与TtreeView的Data进行处理,当点击TtreeView的节点时,读取节点的Data数据,作为
参数来加载指定的Bpl并显示表单窗体。这种方式减少了数据库的访问次数,而且都是动态处理。从这种思想引深,
以后如果扩展了项目的功能,只要把新的包复制到系统的相关路径下,
主程序就可以自动加载并显示功能窗体了。唯一要做的只是在数据库的表中定义好就行了。这样的框架安排为顺利
扩展打下基础。
在本项目是同时也做了调用DLL中表单的尝试,并得到成功。显示DLL中的表单也分两种方式,一种是融合在
主EXE的pageControl上,另一种是ShowModal模式。这两种模式都处理好了回车下移的效果。但是这两种模式的
窗体,在被弹出的窗体所“认识”的方式上差别较大,因为不同于bpl中的表单,可以很方便的操作。对于融合
在主EXE上pageControl上的DLL表单,在关闭表单时,通过向主EXE发送消息的方式,来通知主EXE释放动态建立
的TabSheet。
四、体会
通过本项目的开发,深入应用了TtreeView节点的data属性与记录类型的变量的配合。以前在实际项目中也曾将
其他对象存储在该Data上,因为Data本身是一个指针类型,因此发掘它的潜力可以得到不错的收效。
窗体的融合技术的应用在不同的情况下,操作起来还是不一样的,例普通表单的融合、BPL中表单的融合、DLL表
单的融合,这三种融合在实际业务上差别还是存在的。特别是被弹出窗体“认识”并对其操作,这方面还是需要
技巧的,还好这三种操作方式目前都得到地成功使用。TFrame框架的使用确实给项目带来不方便,减少了不少
工作量。 TFrame放在Bpl中的应用一般都是动态加载方式的使用,当然其在窗体上的位置是要事先安排好的,
动态建立的TFrame被窗体内的其他控件所识别也是需要花些时间的才能做好。
数据库访问通过一个数据库访问类来减少冗余的没有技术含量的代码,提高了不少效率。
通过本项目的开发,为以后的工作积累了不少的知识点,同时积累了一些自己的库。对以后的开发效率会带来
很多帮助。
因为是第一次正式做Bpl结构的项目,还没有这方面的积累经验,感觉就是发布的时候还是麻烦,要确定随项目
一起发布所带的bpl包,还是准备了20分钟,才最终搞定。在网上查了下,有网友建议将包合并,这个要到以后
有时间再尝试一下了。
(无声的雨)
这种模式我们早在多年前就应用的很成熟了,
并且深度也比你这边说的要广的多,
具体有空时可再仔细说说。
总之这是个很好的方式。
从你的描述上看,在一些细节上还是存在点问题的,
提点建议,仅供参考。
第1,bpl的划分和依赖顺序上,提到封装成3个包:
(1)、DBCommon.bpl --> 数据模块包,包括数据模块、数据库读写类模块 (数据访问层)
(2)、pubComon.bpl --> 公共函数、过程单元,公共变量单元、自定义结构类型单元、自定义类单元
(3)、BaseForm.bpl --> 所有窗体的基类单元、业务逻辑基类窗体单元
这个划分不是太理想,更好的划分是,
1)在最底层增加一个系统bpl,例如SysCommon.bpl,做为最基础的包,
这个包可放一些公用函数,通用基类等,但不要包含界面的处理,
这样数据模块包也可使用它。
2)界面处理相关单元单独一个bpl,例如叫UICommon.bpl
3)公共变量单元,要单独出来,尽可能放在上层,并尽量少用。
这样依赖关系大致如下:
SysCommon.bpl->DBCommon.bpl->
->UICommon.bpl->pubComon.bpl->BaseForm.bpl
根据项目应用情况,还可以再细分。
第2,
第3方控件使用问题,
既然使用了DevExpress组件,就没必要再用RZ组件,不要觉得哪个组件好就拿来用。
这个用的越少越好。
第3,比较奇怪的一点,
文中很详细谈到了“TtreeView的Data”的应用,似乎把这个做为一个很好的模式。
事实上这个充其量只是一个应用上的小技巧而已。
包的加载,表单窗体的调用,
应通过单独的管理类来统一调度。