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、如何进行测试?
很多朋友不知道如何进行测试,其实测试很简单,别把它想复杂了,按照自己的想法测试每个功能点是否正确即可。
测试的步骤:
- 准备环境
- 调用被测系统
- 验证
- 清理环境
环境:也叫做夹具(fixture)或者固件,表示调用被测系统时需要准备/清理的数据等等;
被测系统:在Java中就是要测试的类,如UserService;
依赖系统:测试被测系统时,其依赖的部分,如UserDao;
测试用例:包含测试方法的类,里边有很多测试方法来测试被测系统。
接下来仔细看看各部分都做了哪些工作。
接下来介绍一下持续集成(CI)吧。
1、为什么需要CI
2、CI如何工作的
3、travis-ci介绍
a、为什么需要持续集成(CI)
正如前边说的,我们单独测试可能会遇到如下问题:
- 如果写了一个测试,就要把所有测试跑一遍看看整个系统是否是正确的,那么每次等待时间是非常漫长的;
- 如果团队中的其他成员改了功能并提交了,如何快速得到该次提交对当前系统代码是正确还是失败的反馈;
那怎么办呢?自动化地持续集成(CI)!CI的核心就是干这件事情的。自动化持续地集成测试。
使用CI后,如果使用Maven,可以新建多个profile:
- 本地测试时忽略一些比较慢的测试;
- CI服务器上执行所有测试;
b、CI如何工作的
一个典型的持续集成流程:
- 定期检测版本服务器上是否有代码更新;
- 如果发现代码更新,从版本服务器下载最新的代码;
- 自动构建并自动化的测试;
- 不管错误/失败,生成报告给开发人员;
- 有些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 | |
如果使用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实现。