“机房收费系统”(个人版)总结截稿了。
初期,构造原型(主要是绘制系统的界面)历时10天。
绘制UML图的问题
其次,因为对于三层的理解只是表面上的,实际绘制的时候根本不知道如何下手,所以UML画图总共花了三次,第一次是纯三层版的用了15天,第二次是设计模式版的用了7天。最后经师傅的指导,还是选择了在第一版的基础上进行修改。几乎是画一个时序图就立即敲一个代码主线下来的。最终,敲代码的时间也就是10多天左右,从刚开始敲一个功能5天,到一个功能用1天,到半天,最后缩减到1-2h,最末调试用3天结束的。
对于“机房收费系统”中的业务,有些矛盾的地方:
一、业务问题:
1、结账:
(1)首先,结账的对象是谁?猜测该系统的本意是针对“操作员”的售卡、充值、退卡、临时收费进行结账的。但是实际过程中,一般用户也是可以行使上机下机操作的,管理员可以执行注册、充值、退卡、上机下机的操作。因此,会觉得“结账”时,应该针对所有的一般用户+操作员+管理员。所以,我采取的做法是在窗体加载时,把所有的系统用户名全部加载上了。
(2)“结账”功能不仅仅是在售卡表+充值表+退卡表,将“未结账”属性改成“已结账”属性。重点是:同时,加载“日结账单表”中一条记录。
(3)“结账”?的执行者是谁呢?管理员对不对?理想中管理员应该每天在工作的末尾,对所有的用户进行结账。但是,假设管理员生病了呢?一病就是五天,那么,等五天休息过后,再单击“结账”按钮时,应该出现在数据库表中的是一条五天的总记录?还是五条每天的分记录?按理说,我更喜欢后者,因为记录很详细很明确。但是,貌似第一种做法更简单。
2、日/周结账单:
(1)只是负责查询表中的制定记录,并不负责将“结账记录”加载到“日结账单中”。此项功能应由“结账”功能实现。
(2)在实现过程中,我把日结账单和周结账单进行合并,账单的主要功能即:选定日期段内的明细账单,及其汇总工作(这点很重要)。
3、临时/固定用户:
(1)临时用户和固定用户有什么区别呢?这个问题纠结了我相当长的一段时间。有人说:
临时用户和固定用户,只是收费模式的区别,即花的钱不一样。对于临时用户也要像固定用户那么注册:卡号、学号、学生姓名、……。那,临时用户多冤呀,注册信息一点不比固定用户少,还要花更多的钱?其实,不然,“临时用户”相当于网吧的管理员,早就准备好的一批卡,有人来上网,只要负责开卡就可以了。意思就是:临时用户的信息早就已经存在于数据库的卡表中了。“固定用户”呢?举个例子:我去网吧上网,告诉网管“我想办理一张会员卡”,于是管理员才对我的个人信息进行全新的注册。
另一中解析方法:数据库的“卡表”中是空的。无论是会员还是非会员都需要注册卡信息,只不过,会员(这里指:固定用户)需要注册的信息比较多而已,非会员(这里指:临时用户)只需要注册:卡号、充值余额就可以,其余的信息可以在数据库中设计默认值。
二、代码实现问题:
1、在Entity层中,增加了两个实体类:SettleAccountsEntity(结账实体类)+ GroupEntity(组合实体类)。好处,仅在于实现数据传递的方便。结账类用于存放单击“结账”按钮,时的结账信息,如:售卡张数、退卡张数、充值金额、退还金额……组合实体类用于存放组合查询方法中传递的所有信息,如:3个字段+3个操作符+3个要查询的内容+2个关系,这样在D层只要写一个参数化查询语句就可以了。
2、在U层中抽象出一个ConfigurationUI类用于存放一些共用的函数,如:判断text是否为空,判断非法输入(这里用这则表达式对输入的数据进行限制)……同样,在B层中抽象出一个ConfigurationBLL类用于存放一些公用的函数,如:函数转换:目的在于把组合查询中选择输入的内容,转化为数据库能识别的信息。如:将“大于”转化为“>”,将“空值”转化为“1”。
3、功能的实现,无非就是U层调用B层的一个方法,B层调用D层的N个(大于等于1)方法。
总结:俗话说“三思而后行”指的是做事之前一定要考虑周到,但是当你面对一个并不熟悉的事物的时候,并没有办法考虑的面面是到,因此呢?“行”即可。当然,这并不是告诉你可以鲁莽行事。只是,“思”的时间过程,得不偿失不说,也会打消自己的积极性的。以“行”修订“思”,以“思”指引“行”。