项目经验-关于提高代码质量的一些体会
如何进行良好的编码,提高编码质量<o:p></o:p>
1 问题的提出<o:p></o:p>
到公司两年也作了一些项目(主要是业务系统)。对公司相关的流程也有了深刻的体会。项目的进行过程主要分为大给以下部分:
需求- 设计- 编码-测试-部署-维护。<o:p></o:p>
项目人员投入和时间分配大概如下<o:p></o:p>
房地产项目:<o:p></o:p>
阶段<o:p></o:p> |
时间(周)<o:p></o:p> |
人员投入(人)<o:p></o:p> |
需求<o:p></o:p> |
2(不是很清楚)<o:p></o:p> |
1<o:p></o:p> |
设计<o:p></o:p> |
1<o:p></o:p> |
2<o:p></o:p> |
编码<o:p></o:p> |
7<o:p></o:p> |
2<o:p></o:p> |
测试<o:p></o:p> |
2<o:p></o:p> |
1<o:p></o:p> |
部署<o:p></o:p> |
-<o:p></o:p> |
1<o:p></o:p> |
维护<o:p></o:p> |
>12*4<o:p></o:p> |
1-4<o:p></o:p> |
还有科技局项目:<o:p></o:p>
阶段<o:p></o:p> |
时间(周)<o:p></o:p> |
人员投入(人)<o:p></o:p> |
说明<o:p></o:p> |
需求<o:p></o:p> |
4(不是很清楚)<o:p></o:p> |
1<o:p></o:p> |
客户对系统功能使用在1/3左右,预计功能使用完成后至少要到2007年3月份,基于这样的情况,程序的维护肯定得陆续的持续到明年。<o:p></o:p> |
设计<o:p></o:p> |
2<o:p></o:p> |
2<o:p></o:p> |
|
编码<o:p></o:p> |
6<o:p></o:p> |
2<o:p></o:p> |
|
测试<o:p></o:p> |
2<o:p></o:p> |
1<o:p></o:p> |
|
部署<o:p></o:p> |
1<o:p></o:p> |
1<o:p></o:p> |
|
维护<o:p></o:p> |
预计>12*4<o:p></o:p> |
1-4<o:p></o:p> |
从上面可以看到:业务系统的周期可能(因为只是这两个项目,所以一切只是可能,只能说很有可能)会非常漫长,系统构造的时间(包括1-5步)小于(或远小于)系统维护的时间,因为这种业务系统用户的特殊性,维护工作将会持续很长时间。比如科技局的,到现在用户才用了1/3的功能,我在科技局的第一个月中,每天都有用户提出至少一个bug,或者对于某个功能的修改意见,加上功能修改基本都是基于jsp页面,修改起来并不轻松。系统后期维护的成本非常大!<o:p></o:p>
2 解决方案<o:p></o:p>
我们哪里做的不好,系统后期不也作了测试吗?为什么会在维护期出现这么多的问题?<o:p></o:p>
原因有很多,一部分在我的《如何合理的进行业务系统的设计》说明,系统设计是个重要的部分,设计阶段的错误如果在后期要进行修改,花费的时间和改一个bug不是一个数量级的,因此要注重进行系统的分析设计,这里就不再多说。另外一些原因个人觉得如下:<o:p></o:p>
l 没有进行单元测试,无法保证代码的可靠性。<o:p></o:p>
l 基于jsp的机制造成代码的可读性十分低下,修改十分困难。<o:p></o:p>
l 代码的重用率低,不同人对业务过程的复写会因为各自对业务逻辑的理解而存在差异。 <o:p></o:p>
解决上面的问题个人觉得有以下几个方法:单元测试、代码重构、代码审查。<o:p></o:p>
2.1 单元测试<o:p></o:p>
测试人员所进行的测试是集成测试,也就是黑盒测试,它不能保证代码的测试覆盖率(就是被测试的代码占所有代码的比率),如果哪个功能使用到没有被测试的代码那么很可能会出现新的程序bug!在科技局项目提交测试之前,任何单元测试的代码都没有,没有人能拍着胸脯说:“我的代码绝对没有问题”。我听到的最多的也是我说的最多的:“应该没有问题吧!”。这样的系统将很多问题的发现向后推了一个甚至更多个阶段,如果测试人员发现了一些问题,这好办,如果部署到用户环境后,仍然有大量的bug出现,这确实要问问自己了。对于程序员来说,不能过分的依赖测试人员,原因上面也说了,测试人员进行的是黑盒测试,他们不知道你的代码有多少条件分支,比如<o:p></o:p>
- public int process( int type ){
- if( type == 1 ){
- //
- // do some thing
- }
- if( type == 2 ){
- //
- // do some thing
- }
- }
当这个方法被测试人员测试时,它的表现形式可能是一个
可能会有人说:“我测试了啊,写了个main函数在类里头”。<o:p></o:p>
- Class Processor{
- Public int process( int type ){
- }
- public static void main( String[] s ){
- new Processor().process( 1 );
- new Processor().process( 2 );
- }
- }
首先说,这样也可以,不过你想过没有,如果你的程序中有少量的几个类,你可以这么做,测试的时候可以直接使用开发工具来运行这个实例。可是如果当这些类达到几十个甚至成百上千个呢?那你岂不是要点无数次开发工具工具条上的运行按钮?我不赞成这样的用法,我宁可花点时间写一些测试类也不愿意这样作,因为这样做把一些对于业务类完成业务操作来说没用的东西也放到业务类中了。我的解决方法是,把所有测试方法放到一个类里面,每次该测试类一次运行将会执行所有的测试:
- class Test{
- public void test(){
- testProcess();
- testProcess2();
- testProcess3();
- …
- }
- public void testProcess(){
- new Processor().process( 1 );
- new Processor().process( 2 );
- }
- public void testProcess2(){}
- public void testProcess3(){}
- public void testProcess4(){}
- public static void main( String[] s ){
- new Test().test();
- }
- }
这样可以解决一些问题,可是时间一长的话,难免在
我这里的单元测试的意思包含两层:1 测试代码;2 完成测试的自动化,就是说,任何时候我只要一次运行就可以完成所有的测试工作。<o:p></o:p>
2.2 Junit的引入<o:p></o:p>
Junit是当前十分流行的一个单元测试框架,实际上,junit只是java领域内的解决方案, 在其他领域junit所表达的这种测试理念,仍然是行得通的,而且有其他版本的实现,有兴趣的话大家可以去研究研究。在junit中包含了TestSuite和TestCase<span style="FONT-FAMILY: 宋体; mso-bidi-font-weight
Test类中充斥了过多的代码,造成Test类没有办法去维护了。<o:p></o:p><o:p></o:p>select列表,传递type值,有可能是1和2 ,也有可能是因为登录的用户身份的限制,该select中只包含了1,这个时候,测试人员对该方法的调用将会是process(1);这样条件分支type==2就不会被测试。如果有一天这个功能被某个用户用到了,而且这个用户的权限使得select中只包含2,那么这个方法将会以process(2)的姿态被执行,但这个时候process(2)是没有被任何测试人员或程序员自己测试,如何能保证它的正确性呢?如果用户得到了一个正确的结果,你就应该很庆幸了;可如果用户得到一个错误的结果呢?你可能会从公司赶到用户现场,先找到你的jsp,然后一条一条查看代码,用无数个System.out.println()来输出debug的信息,有可能是System.out.println( “1111111111 ” + type );也有可能是System.out.println( “----------------“ + type )等等。等一切调试完毕后,你就关掉ue和其他调试用的窗口,跟用户解释:“这个是因为XXX”。<o:p></o:p>呵呵 真是难为你了