持续集成要求每天都提交代码,这样才能降低代码集成的风险,不能埋头写一周一起提交,这样往往集成不成功。怎么样才能鼓励每天都提交代码呢?一个就是第二天的站会,你这个功能代码提交了,单元测试通过了,第二天才能说做完了,否则不算,这就逼得你,将大任务拆成小任务,每天都多次提交。
而且Git的提交方式,是后提交者有责任去merge,保证代码的编译通过和测试通过,你会发现,如果你不及时提交,等你改了一大片代码,别人都提交完了,这一大片的冲突都是你来merge,测试用例不通过的你来fix,所以逼的你有一个小的功能的改动,就尽早提交,pull一下发现没有人提交,赶紧提交。
提交不是马上进入主库,而是需要代码审核,这是把控代码质量的重要的环节。
代码质量的控制往往每个公司都有文档,甚至你可以从网上下载一篇很长很长的Java代码规范。但是我们常常看到的例子是,规范是有,但是虱子多了不咬人,规范太多的,谁也记不住,等于没有规范。
所以建议将复杂的规范通过项目组内部的讨论,简化为简单的10几条军规,深入人心,大家都容易记住,并且容器执行。
代码审核往往需要注意下面的几方面:
代码结构:整个项目组应该规定统一的代码组织结构,使得每个开发拿到另一个人的代码,都能看的熟悉的面孔。这也是scrum中提倡的每个开发之间是可替代的,当一个模块有了阻碍,其他人是可以帮上忙的。至于核心的逻辑,估计审核人员也来不及细看,这不要紧,核心逻辑是否通过,不能靠眼睛,要靠测试。
有没有注释,尤其是对外的接口,应该有完善的注释,方便自动生成接口文档。
异常的处理,是否抛出太过宽泛的异常,是否吞掉异常,是否吞掉异常的日志等。
对于pom是否有修改,引入了新的jar。
对于配置文件是否有修改,对外访问是否设置超时
对于数据库是否有修改,是否经过DBA审核
接口实现是否幂等,因为Dubbo和springcloud都会重试接口。接口是否会升级,是否带版本号
是否有单元测试
当然还有一些不容易一眼看出来的,可以通过一段时间通过统一的代码review,来修改这些问题:
某个类代码长度过长
设计是否合理,高内聚低耦合
数据库设计是否合理
数据库事务是否使用合理
代码是否有明显的阻塞
代码审核完毕之后提交上去之后,一个是要通过静态代码审查,可以发现一些可能带来代码风险的问题,例如异常过于宽泛等。
在就是要通过单元测试。我们应该要求每个类都要有单元测试,并且单元测试覆盖率要达到一定的指标。单元测试要有带Mock的模块内的集成测试。
在编译过程中会触发单元测试,单元测试不通过,已经代码覆盖率,都会统计后发邮件,抄送所有的人,这对于研发来讲又是一个压力。
当有一天你的提交break掉了测试,或者代码覆盖率很低,则就像通报批评一样,你需要赶紧去修改。
单元测试完毕之后,就会上传成果物,或者是war或者是jar,一般会用nexus,因为有版本号,有md5,可以保证安装在环境中的就是某个版本的某个包,我们还遇到过有使用FTP的,这样一个是很难保证版本号的维护,升级和回滚比较难弄,另一个是没有md5,很可能包不完整都有可能的,而且一旦发生,很难发现。
如果使用了容器,则还需要编译Dockerfile,使用Docker镜像作为交付,能够实现更好的环境一致性,保证原子的升级和回滚。
每天下班前,当天的代码需要提交到库中去,晚上会做一次统一的环境部署和集成测试。
每天晚上凌晨,会有自动化的脚本将Docker镜像通过编排部署一个完整的环境,然后跑集成测试用例,集成测试用例应该是基于API的,很多的公司是基于UI的,这样由于UI变化太快,还有UI不能覆盖所有的场景,所以还是建议UI和API分离,通过API进行集成测试,有了每天的测试,才能保证每天晚上的版本都是可以交付的版本,也保证我们微服务拆分的时候,尽管改了很多,不会因为新的修改,破坏掉原来能够通过的测试用例,保证不会有了新的,坏了旧的。
这个集成测试或者叫回归测试每天晚上都做,都是在一个全新的环境中,这就是持续部署和持续交付。
如果某一天测试不通过,则会发出邮件来,是因为当天谁的哪个提交,导致测试不通过,抄送所有人,这是另一个压力。