1.使用模板技术

     可以参考我们团队的代码规范中的部分内容:开发工具统一和配置具体团队内容定制,适合就可以。

模板,一个我们天天使用的技术, 比如:

  • Java类就是创建Java对象实例的模板;
  • 泛型,参数化类型的模板,如List<User>;常见的如泛型DAO、泛型Service等;
  • Arrays.sort() 一个排序的模板;
  • Spring中的DAO支持设计;可参考《我对SpringDAO层支持的总结》;
  • HttpServlet设计,如service根据http method转发给各个do开头的方法(doGet、doPost等);
  • 还有如Struts2的ActionSupport设计,我们继承后能自动得到如国际化、验证的支持;
  • JSP、Velocity、Freemarker等模板页面技术;
  • 等等

模板带给我们的好处很明显:约束+重用。通过模板我们可以把变与不变分离,重用不变,变可以交给子类/通过回调机制完成,而且还具有约束作用,防止乱写代码。

那我们应该利用好这个技术,加速项目的开发速度。接下来我们看看如何利用模板技术来加速我们的开发速度。

接下来,我将介绍下如何利用模板技术加速开发速度,但不会接受如何利用模板技术开发可复用的代码;本文以IntelliJ IDEA为原型介绍:

a、代码生成

b、Live Template

c、File and code Templates

d、自动代码生成

具体内容请查看博客: http://jinnianshilongnian.iteye.com/blog/1895481

2. 加速项目调试启动

由于篇幅比较长,详情:  查看

3. 第三方框架或依赖模块的加速

我们项目中依赖的第三方框架有:spring ,ibatis等,那么有针对这些,我们做了一些了解,以及对症下药。

如:

      1. 加速spring容器的启动速度

      2. 加速ibatis的实际开发中的问题


针对上面2个问题,其实可以单独写几篇文章来说明,本文的出发点抛砖引玉,所以这里点到止,介绍下。

spring加速:

1.1. 扫描注解Bean

                  写比较精确的扫描路径,如扫描@Service和@Repository:

<context:component-scan base-package="com.sishuok.es.**.repository,com.sishuok.es.**.service,com.sishuok.es.**.extra">

这样写,比直接写com.sishuok.es速度要快很多,因为这样扫描的class会很少。

               还有,如springmvc 扫描

<context:component-scan base-package="com.sishuok.es.**.web.controller" use-default-filters="false">

此处只扫描项目的web.controller包,这样扫描的class也很少。

                等等。

1.2 延迟加载bean

                常见的方式是在配置文件中在<beans>上加:default-lazy-init="true", 但是 注解扫描的bean无效,如@Service,需要使用@Lazy指定,但这样太麻烦,需要一个一个的配置, 还有就是如果你使用springmvc,lazy-init几乎没啥用,因为springmvc容器在启动时会通过DefaultAnnotationHandlerMapping查找相关的带有@RequestMapping的bean并注册请求映射;所以相关的如Service/Repository也级联非lazy-init;张开涛写了一个工具 SpeedUpSpringProcessor,其作用是:lazy-init所有bean,包括注解的bean;具体内容可以看他的博客:http://jinnianshilongnian.iteye.com/blog/1883013

1.3 等等。。。


4.单元测试+持续集成

大家可能对如下情景比较熟悉:

  • 如果开发过SSH的web项目,启动服务器可能会比较慢,有的项目甚至需要1分多钟,甚至更多,这个启动时间的等待一般就浪费了;
  • 在开发项目时,有些功能比较复杂,当时觉得思路特清晰,但是过了一段时间后,自己也忘了,完善功能时频繁出现bug,降低开发速度;
  • 在维护项目时,不知道自己修改的对还是不对,是否存在隐患;维护速度降下来了;
  • 如果开发一个很多人都使用的接口,典型的如用户系统,要保证比如升级时向下兼容;
  • 在团队间协作时,有时候只定义好接口,对方还没有给实现,如何进行同步开发?

如上问题,估计只要是个开发人员,都可能遇到过;如果此时有了单元/集成测试,那我们能很好的解决这些问题。(注:加下来如果没有特殊情况,不刻意强调 单元测试/集成测试,即提到测试是指的是单元/集成测试)

a、为什么需要测试?

测试的目的是什么?我的理解是:

  • 缩短发现问题到解决问题的速度;
  • 给程序一个修改后能验证是否正确的保证;(回归测试)
  • 如果是开源软件,我们可以通过单元测试了解其是怎么使用的;比如我之前通过cglib的单元测试学习过cglib的使用;

所以如果你遇到如上问题,就需要写测试。写测试可能是为了自己(1、2);也可能是为了帮助别人(3)。



b、如何进行测试?

很多朋友不知道如何进行测试,其实测试很简单,别把它想复杂了,按照自己的想法测试每个功能点是否正确即可。


测试的步骤:

  1. 准备环境
  2. 调用被测系统
  3. 验证
  4. 清理环境

环境:也叫做夹具(fixture)或者固件,表示调用被测系统时需要准备/清理的数据等等;

被测系统:在Java中就是要测试的类,如UserService;

依赖系统:测试被测系统时,其依赖的部分,如UserDao;

测试用例:包含测试方法的类,里边有很多测试方法来测试被测系统。

 

接下来仔细看看各部分都做了哪些工作。



接下来介绍一下持续集成(CI)吧。

1、为什么需要CI

2、CI如何工作的

3、travis-ci介绍

 

a、为什么需要持续集成(CI)

正如前边说的,我们单独测试可能会遇到如下问题:

  • 如果写了一个测试,就要把所有测试跑一遍看看整个系统是否是正确的,那么每次等待时间是非常漫长的;
  • 如果团队中的其他成员改了功能并提交了,如何快速得到该次提交对当前系统代码是正确还是失败的反馈;

那怎么办呢?自动化地持续集成(CI)!CI的核心就是干这件事情的。自动化持续地集成测试。

 

使用CI后,如果使用Maven,可以新建多个profile:

  • 本地测试时忽略一些比较慢的测试;
  • CI服务器上执行所有测试;

 

b、CI如何工作的

一个典型的持续集成流程:

 

  1. 定期检测版本服务器上是否有代码更新;
  2. 如果发现代码更新,从版本服务器下载最新的代码;
  3. 自动构建并自动化的测试;
  4. 不管错误/失败,生成报告给开发人员;
  5. 有些CI服务器还能产生可执行的软件,自动化地部署到测试机器,交给测试人员测试。


持续集成服务器其实就是一个定时器,自动帮你下载最新代码、编译、测试、集成及产生报告发给开发人员。

 

常见的CI服务器有:

  • Apache Continuum
  • Hudson
  • CruiseControl
  • Jenkins CI
  • TeamCity
  • Travis CI

 

我09年时使用过TeamCity社区版,足够满足常见需求;目前我使用github托管项目,使用Travis CI进行分布式的持续集成,免费,目前看来还是不错的。

 

c、travis-ci介绍

我现在开发的ES-JavaEE项目开发脚手架就是使用travis ci进行持续集成;具体参考《Getting started》进行与Github集成,其支持的语言:

支持的数据库:

  • MySQL
  • PostgreSQL
  • MongoDB
  • CouchDB
  • Redis
  • Riak
  • RabbitMQ
  • Memcached
  • Cassandra
  • Neo4J
  • ElasticSearch
  • Kestrel
  • SQLite3

更多请参考其官网的介绍。

 

如果是Java开发人员,支持的JDK包括:OpenJDK 和 OracleJDK。 如果使用的是OpenJDK,Maven中使用ascii2native插件时,需要如下配置:


1



2



3



4



5



6



7



8



9



10



11



12



13



14



15



16



17



18



19



20



21



22



23



24



25



26



27



28



29


< plugin >



< groupId >org.codehaus.mojo</ groupId >



< artifactId >native2ascii-maven-plugin</ artifactId >



< version >1.0-alpha-1</ version >



< executions >



< execution >



< phase >generate-resources</ phase >



< goals >



< goal >native2ascii</ goal >



</ goals >



< configuration >



< encoding >UTF-8</ encoding >



< src >src/main/messages</ src >



< dest >target/${project.artifactId}/WEB-INF/classes</ dest >



< includes >messages.properties</ includes >



</ configuration >



</ execution >



</ executions >



<!-- native2ascii 使用的tools.jar -->



< dependencies >



< dependency >



< groupId >com.sun</ groupId >



< artifactId >tools</ artifactId >



< version >1.7.0</ version >



< scope >system</ scope >



< systemPath >${java.home}/../lib/tools.jar</ systemPath >



</ dependency >



</ dependencies >



</ plugin >



如果使用mysql,端口只能是3306。

如果想开端口测试,这是不允许的。

 

如下是我项目中的一个配置.travis.yml,放到项目的根下即可:

———————————–

language: java           语言

 

env:                           环境

- DB=mysql              使用mysql

 

jdk:

- openjdk                jdk使用openjdk

 

mysql:

database: es         数据库名为es

username: root     用户名为root

password :            密码为空

encoding: utf8      编码为utf8

 

install:                     安装时执行的脚本

- mvn install -Dmaven.test.skip=true     mvn安装并跳过测试

 

before_script:        script之前执行的测试

- cd web

- mvn db:create  创建数据库的mvn命令(此处使用了 maven-db-plugin 插件)

- mvn db:schema  创建脚本的mvn命令

- mvn db:data        安装数据的mvn命令

- cd ..

 

script:                      测试时执行的脚步

- cd common

- mvn test              测试common子模块

- cd ..

- cd web

- mvn test -Pit       测试web子模块,并指定使用it profile测试(即集成测试的配置,具体参考pom.xml中的profile/it)

 

notifications:          触发

email:                  测试完成后测试报告发到哪

- zhangkaitao0503@gmail.com

———————————–

 

持续集成不能修复代码的错误,而是和单元测试一样,缩短发现问题带解决问题的时间,这样可以提高开发效率,降低项目风险,提高项目的稳定性。而且尤其是团队协作时,可以发现其他人的代码是否对自己的代码产生影响。

 

到此我们利用单元测试+CI可以加速开发人员的开发速度。利用好单元测试和CI,不要纯粹为了单元测试和CI而去做这些事情。

 

本文没有介绍TDD,TDD并不会那么美好,我认为我们可以借鉴TDD的一些思想,但决不能迷信TDD,有时候,尤其如开发企业应用,先写功能再写测试可能效率更高,而且大部分时候是不需要TDD的。而且我也没能在实际项目中获取太多TDD的好处,但是我获得了测试的好处。

 

本文也没有介绍测试覆盖率,我认为不要一味的追求覆盖率,有时候有的覆盖率没有任何意义。所以不要让为了覆盖率而覆盖率拖慢了项目开发进度。



5. 脚本日常管理

在日常开发中会经常遇到如下问题:

1. 应用发布

2. 在测试的时候,重建数据库和数据

3. 备份数据库

4. 监控服务器运行状态并报警

5.清理系统的垃圾文件和过时文件

6.压缩日志及删除过期的日志

等等。。。。


对于如上的一些操作因为经常使用的一些功能,我们应该使用模板+命令/脚本自动化来解决,而不是每次重新写一个, 建一个命令文件,存储一些经常使用的命令(因为有些命令可能个把月才用一次,记不住啊) 对于一些需要按步骤执行的操作,可以使用一个批处理文件来存储,然后下次只需要执行批处理即可,可变部分使用命令行参数传入即可。

  其实如上也是使用了模板的思想,把一些不变的但常用的命令集中存储或脚本化,下次遇到相同问题时,只需要把命令或脚本复制下执行一下即可,可变的部分通过参数传入。如果是一些需要固定周期执行的命令/脚本,可以使用定时调度,如linux的crontab定时调度,如典型的数据库备份、清理垃圾文件、压缩及删除过期的日志等等。

针对不同团队有不同的需求,就我们团队来说,我整理了一些内容,与大家共勉。


解决思路:

1. 应用发布流程: 详见应用发布流程,待续。。。

2.  在测试的时候,重建数据库和数据, 我在应用中有一个init-sql.txt文件,如果每次有数据库的结构变化,就需要同步该文件,这样保持数据库的一致。

3. 备份数据库:服务器上这个一定要做的,不过我写的非常简单,适合小数据库的备份,

/home/mysql/mysqldump -u用户名 -p密码 db_name  > /home/data/backupfile/db_name-backup-`date +%m%d-%Y`.sql



4.监控服务器运行状态并报警: 待续


5.清理系统的垃圾文件和过时文件:通过linux crontab实现, crontab -e 编辑内容,59 23 * * * /home/data/cleanup.sh 保存,等等,做一切你想做的事情。

6.压缩日志及删除过期的日志:   通过linux crontab实现。