IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    结对编程实践

    longhao (longtask@gmail.com)发表于 2011-11-12 02:10:29
    love 0

    不少程序员会说“代码写的太烂了”,说很容易,然后您能告诉别人什么地方需要改进么?其实我也有这样的毛病,单个人代码写的好时偶然的,写的烂是必然的,所以需要借助团队的力量来告诉成员需要改进的地方。由于业务编码工作接近尾声,业务开发人员和我主要从测试代码开始入手来改善代码质量,优化业务流程。

    流程:由我通过mock的方式写service层的测试代码(仅仅测试复杂的业务流程,仅仅简单调用DAO层流程不用走mock测试),发现代码问题,由业务开发人员来修改代码满足我的需求,在走测试流程中,遇到重复的代码,很容易被发现,由业务开发人员来负责修改(我也会修改一点点)。然后由我继续测试,递归至整个service测试通过。这个流程理论上应该称谓“乒乓结对编程”。我的编码经验相对丰富,可以适当指导结对开发的同学。

    原则:以人为本,不随意修改别人代码,尊重别人的中间地带的习惯。

    实践过程中的一些感想:

    1:单个类中重复代码的提取。Ctrl+C and Ctrl + V对不少人而言都习惯了,复制一下,修改一点东西,一个功能就出来了。也不用考虑未来的维护成本,所以重复代码在系统中就越来越多。在方法中发现类似重复代码,选择这段代码,使用eclipse的refactor快捷键 Alt + Shift + m 可以自动提取方法,eclipse会自动发现其他地方重复的,并用提取的方法代替。

    2:Service层方法参数尽量为对象或者接口。在方法中,如果new出一个对象,就无法mock相关对象,导致测试无法进行先去。在方法参数中传入对象或者接口是很有必要的。

    eg:2.1

    public Long addUser(String name , String passwd){

    User user = new User();

    // set method ! 这个地方导致mock不能用

    //do something!

    }

    修改为

    public Long addUser(User user){

    //do somethings!

    }

    3:代码中不少地方可以重构。如果发现一个方法中有很多的if-else,那么这个代码明显的抽象的不够。有些if过长,可以通过提取boolean变量来方便代码阅读。某些变量可以使用enum的尽量不要在接口中定义。

    eg3.1:

    if(pvs.getRefererUrl().equals(UrlUtils.getItemUrl(tmpItem.toString() ,

    UrlUtils.ItemUrlType.Original))

    || pvs.getRefererUrl().equals(UrlUtils.getItemUrl(tmpItem.toString() ,

    UrlUtils.ItemUrlType.Simplify)))

    && tmpItem > 0){

    //do someting!

    }

    可以修改为:

    boolean needUpdateFlag = pvs.getRefererUrl().equals(UrlUtils.getItemUrl(tmpItem.toString() ,

    UrlUtils.ItemUrlType.Original))

    || pvs.getRefererUrl().equals(UrlUtils.getItemUrl(tmpItem.toString() ,

    UrlUtils.ItemUrlType.Simplify)))

    && tmpItem > 0;

    if(needUpdateFlag){

    //do something!

    }


    eg3.2:

    public interface User{

    public int BUYER = "0";

    public int SELLER = "1";

    //else

    }

    可以修改为:

    public enum UserRole{

    BUYER(0) , SELLER(1);

    private UserRole(int num){

    this.num = num;

    }

    private int num;

    public int getNum(){

    return this.num;

    }

    }

    eg3.3:代码块中if的抽象

    if(a > 0){

    throw new RuntimeException("a > 0");

    }

    if(b > a){

    throw new RuntimeException("b > a");

    }

    可以抽象一个方法

    public void check(boolean flag , String prompt){

    if(flag)

    throw new RuntimeException(prompt);

    }

    4:测试驱动开发。有些代码会导致Mock测试非常的麻烦,这类代码需要放在小模块中,然后分而治之的去测试。

    eg:4.1

    public boolean checkPassword(Long memberId, String password, String ip){

    ////以下代码写在一起的

    //验证用户的代码

    //验证用户登录次数的代码

    //验证用户密码的代码

    }

    可以尝试修改为:

    public boolean checkPassword(Long memberId, String password, String ip){

    checkMember(memberId);

    checkLoginTimes(memberId);

    checkPasswd(memberId , password , ip);

    }

    5:工具设置和IDE快捷键。还是想说下,宽屏时代的“margin column”应该设置为120而不是eclipse默认的80。具体方法:Window > Perferences > General > Editors > show print margin修改80到120。编码中超过120个字符就尽量换行处理。IDE的快捷键尽量多用,不要问我为什么!

    6:争执。独立思考的能力一个具体体现就是与人争执,我鼓励大家与我争论某个代码,同时希望有人能够说“老子觉得就应该这样写”。如果能够拿出证据或者就是想装逼,我觉得应该尊重别人的想法。

    和同事们结对编程过程中,很容易看到别人不好的编码习惯,也很容易学到别人的优良的编码习惯。既然编程界存在5%的神话(http://is.gd/bWjI5m , http://is.gd/Ic8RU0),如何成为那5%呢?结对编程为我们提供了相互学习编码习惯的条件。思考习惯只能靠自己独立努力去学习!




沪ICP备19023445号-2号
友情链接