Chinaunix首页 | 论坛 | 博客
  • 博客访问: 443693
  • 博文数量: 1496
  • 博客积分: 79800
  • 博客等级: 大将
  • 技术积分: 9940
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-09 13:22
文章分类

全部博文(1496)

文章存档

2011年(1)

2008年(1495)

我的朋友

分类:

2008-09-09 13:26:07

重复代码是怎么产生的?

请观察下面的代码,我们已经有一个根据出租记录的id取出租用客户姓名的方法:getCustomerName。

   public class BookRental { //该类描述出租记录
        String id;
        String customerName;

        ...

    }
    public class BookRentals {
       private Vector rentals;
       public String getCustomerName(String rentalId) { 根据出租id取出客户姓名
           for (int i = 0; i < rentals.size(); i++) {
              BookRental rental = (BookRental) rentals.elementAt(i);
              if (rental.getId().equals(rentalId)) {
                  return rental.getCustomerName();
               }
           }
           throw new RentalNotFoundException();
        }
    }
    public class RentalNotFoundException extends Exception {

        ...

    }


    假定现在你要增加一个新的方法,该方法是根据出租记录的id删除该记录,你把这方法命名为deleteRental(String rentalId)。现在你已经考虑到,就像getCustomerName这个方法一样,也要一个一个遍历出租记录。所以你就将getCustomerName这个方法里面的一些代码拷出来,然后稍微修改一下:

    public class BookRentals { 
        private Vector rentals;
       public String getCustomerName(String rentalId) {
           for (int i = 0; i < rentals.size(); i++) {
              BookRental rental = (BookRental) rentals.elementAt(i);
              if (rental.getId().equals(rentalId)) {
                  return rental.getCustomerName();
               }
           }
           throw new RentalNotFoundException();
        }
        public void deleteRental(String rentalId) {
             for (int i = 0; i < rentals.size(); i++) {
                 BookRental rental = (BookRental) rentals.elementAt(i);
                 if (rental.getId().equals(rentalId)) {
                     rentals.remove(i);
                     return;
                  }
              }
             throw new RentalNotFoundException();
         }
     }


现在这样的代码看起来怎么样?不怎么样,两个方法有大多的同样的代码了。


移除重复代码吧!

要移除所有的重复代码,你可以将BookRentals这个类修成如下的样子(也就是“重构”了):

    public class BookRentals { 
        private Vector rentals;
        public String getCustomerName(String rentalId) {
           int rentalIdx = getRentalIdxById(rentalId);
           return ((BookRental) rentals.elementAt(rentalIdx)).getCustomerName();
        }
        public void deleteRental(String rentalId) {
           rentals.remove(getRentalIdxById(rentalId));
        }
        private int getRentalIdxById(String rentalId) { //新增加的一个方法
            for (int i = 0; i < rentals.size(); i++) {
               BookRental rental = (BookRental) rentals.elementAt(i);
               if (rental.getId().equals(rentalId)) {
                   return i;
               }
            }
           throw new RentalNotFoundException();
        }
     }


为什么我们要移除重复代码?

    我来向各位程序员同学稍微说一下,在BookRentals这个类中,rentals这个属性的类型是Ventor,如果我们需要将它改为数组,那我们就必须将所有的"rentals.size()"改为"rentals.length". 在重构以后的版本中,我们只需要在getRentalIdxById这个方法中修改一次,而在原来的版本,我们就得在getCustomerName跟deleteRental两个方法中都改一次。类似的,我们还要将所有的"rentals.elementAt(i)" 改为 "rentals[i]". 又是改一次跟改两次的比较!

    大多数情况中,如果类似这样的代码在10个地方重复,当我们修改代码的时候,就要修改10个地方,我们并不能保证能把这10个地方都记住了,而一旦漏掉了几个地方,等待我们的,是一处一处的错误去修复。而最致命的是,当我们修改的是业务逻辑时,这时候,不管我们漏掉了几个地方,IDE都不会报错,那么,等待我们的,将是一堆Bug去检查,而造成的一些bug中,很可能是短时间内还发现不了的. 惨-_-!!
【责编:Peng】

--------------------next---------------------

阅读(93) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~