实现邮储柜台模拟程序杂感(一)

来源:互联网 发布:恢复windows删除数据 编辑:程序博客网 时间:2024/05/04 06:11

前言:

公司测试部门要求部分实现一个邮储柜台充值系统,用来和公司的业务系统进行测试。给了我7天的时间和两个设计与实现的规则来完成这个系统,至于实现的技术和编程方法就自由发挥了,最终我延期了又7天的时间完成了。在这个2个规则下,我是戴着镣铐跳舞,用14天完成了这个系统,测试部门却因这个规则放弃了这个新的测试系统,真是杯具……。以下权当我写完系统后根据网络上的信息写的自我总结吧与系统代码优化的设想吧:

 

以前写的应该是技术人员在进行系统实现时,往往很多时候过于陷入技术而最后导致忽略了原始需求的误区的描述,最近忘了在谁的blog上也看到一篇讲这个的东西,写的挺不错的,很喜欢里面的一句话:软件的建设目的是为了让客户和老板爽,实现他们的功能需求才能达到这个目标,而非功能性需求很多时候都是为了让开发人员爽,在建设系统的时候不要犯反客为主这样的错误,^_^
写这篇和以前的意思不一样,这篇主要是对现在的动辄采用aop思想、采用插件架构、采用SOA、大集成技术这些东西的一个个人的看法,象这种思想级别或者架构级别的东西来说,是很多人采用,但真的发挥了它的作用吗?不敢认同,呵呵,其实象一旦采用aop、插件体系架构这样的思想或架构级的东西,带来的是设计时,甚至是分析时的思想转变,^_^,否则采用了甚至比不采用还惨,不仅带不来效果反而会受很大的"伤害",呵呵,所以在要采用思想级别和架构体系级别的技术转变的时候真的要慎重思考,需要的是对采用的思想以及架构体系的深入了解,毕竟做软件不是为了技术而技术的,当然,自己小玩玩当然是可以了。

 

1、编程技术

“软件的建设目的是为了让客户和老板爽,实现他们的功能需求才能达到这个目标,而非功能性需求很多时候都是为了让开发人员爽”

做汇兑模拟器的时候-系统内部测试使用、技术没有要求、工期有要求,预先的技术架构:数据库采用Berkeley DB Java,事务管理是通过AOP技术实现,自己实现一套事务管理模块。但是在实际的编码过程中,通过AOP管理bdb的事务,在开发技术上的、分析思想上需要转变,新技术的使用、新框架的搭建会导致项目延期-一直想模拟实现spring aop,但是预计的工时不允许。在每次采用新的编程方法时,在业务基础上分析之后,更需要在思想级别、架构体系级别做深入的了解。最后在事务管理上采用折中的办法:使用硬编码模式来管理bdb的事务。

Service部分通过对抛出的异常进行统一的封装,由AOP进行统一处理,就可以避免了大量的try-catch-finally语句。

 

2TDD

代码编写之前要去实践TDD,在代码编写完成后,回顾下来,发现TDD并没有完全坚持下来,这些测试不是真正的TDD,而是Test for Class

TDD意义:

1、  保证类是为了其所赋予的功能、职责而存在,增强对自己所写代码的信心。

2、  保证避免过度设计

3、  为了重构方便,为了持续集成-这是很重要的原因,每个项目都需要维护,这些测试测试案例能够保证新的修改对原功能无害,新的修改能够正确执行。

一般的TDD做法:

1、为一个类首先编写测试类

2、确认类的每个方法提供的是什么功能、输入输出、异常抛出,为不同情况编写测试方法

3、实现类。运行测试类,修改类错误,循环至成功。

本人做法:

1、根据设计编写类的实现方法

2、根据设计编写测试类不同条件的方法

3、运行测试类、修改错误,循环至成功

我比较讨厌失败提示,一般先实现类方法,然后运行测试类,这样红色提示就会少些。

 

注意:测试类中如需要使用来源于数据库的数据,应该使用Mock模拟数据库,可以保证测试数据和运行数据的分离,不要去依赖系统中真实的运行数据。如果没有使用Mock,就会需要一个测试环境数据库,在测试类执行完毕后清除,要做好扫尾工作,不要影响到其他功能测试(方法:先将数据输入数据库或者表,然后导出一个数据库或者表的备份,回头在测试前将数据库恢复到这个导出时状态。并且可以根据测试不同要求建立不同的备份-很麻烦。)-这样就涉及到测试类的方法依赖问题,JUnit3.x是通过Vector保存测试方法,在JUnit4.x可以指定依赖方法,保证方法的执行顺序,这样做在实际的编码过程中就会减少Mock代码的编写量。

       通过数据库来提供数据的缺点:TDD一个目的就是“测试特定情况下单元执行的结果是否和预期一致”,用这种方法进行测试,就会把该单元依赖的其他的对象、东西进行模拟,模拟的方法很笨拙。例如:一个Service类依赖于一个Dao类,通过由Dao从数据库读取的数据进行相关的业务处理。在进行对Service类的单元测试时,需要处理Dao-数据库连接、数据读取等,使用这种方法不仅要关注Service类的运行,还要处理Dao的执行情况。但是单元测试只是关注当前对象执行的正确性,这个对象所依赖的东西已经被假设为成功状态。真正的单元测试应该为这样的:对Service类进行测试时,它所依赖的Dao类返回的各种结果已经被Mock是实现了--这也解释了为什么会出现面向接口的编程了。

 

依赖具体数据库的单元测试实际上是集成测试:创建出当前系统所依赖的运行环境,从系统的入口进行测试。例如b/s系统中,系统的入口就是页面。在编码过程中的集成测试就是首先创建出入口对象所依赖的对象和环境,通过Bottom-Up的方式进行测试-开发循环过程。在模拟器开发过程中就是采用这种伪TDD开发。

 

3、缓存

       在模拟器技术调研过程中,曾考虑使用缓存技术。我认为缓存应该分为2种:页面缓存、业务数据缓存。缓存的储存方式是通过key-value格式的。

       页面缓存:指的是对页面的片段内容进行缓存,在JEEMVC架构中,页面的缓存是一般使用oscache实现的,oscache提供jsp tag来标示需要缓存的内容,一般这个内容涉及到后台业务请求或者逻辑处理。缓存规则的设计:被缓存对象对应的key,例如用户id+页面+交易id;后台业务增加、删除、修改操作对缓存的影响-事件模型通知缓存数据被修改,或者缓存系统主动检测数据是否被修改;缓存的作用域-requestapplicationsession

       业务数据缓存:比较常见的是hibernate的一级、二级缓存,memcached缓存框架。hibernate中如果更新数据,就会把缓存中的数据全部删除;如果查询数据,首先是从缓存中查取,如果没有才会到数据库读取-在后台发生改变的时候其实是不知道需要移除哪些key的,所以hibernate为了避免这个麻烦,采用的就是当数据一旦发生改变的时候就清除全部的查询缓存,而不是只去清除相关的缓存。这些框架的原理都是共通的,系统缓存机制的好坏是在硬件固定的时候,命中率的高低决定的。

目前比较流行的缓存方式是通过spring aop+ehcache实现的。我还没有实现过具体的编程。

      

       使用页面缓存的时候,是将jsp渲染后的结果保存,在大型项目中cache tag过多会导致维护上的困难,也不利于数据复用;业务数据缓存是将业务数据:数据访问数据、业务处理的结果保存起来,跟利于多个模块的数据复用。

关键字:cache provider, cache policy

http://www.blogjava.net/BlueDavy/archive/2006/06/02/50076.html