【IT168 技术文章】 重复代码是怎么产生的?
请观察下面的代码。我们已经有一个根据出租记录的id取出租用客户姓名的方法:
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方法一样,deleteRental方法也要一个一个遍历出租记录,所以将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很可能是短时间内发现不了的。
