烟熏鲱鱼(臭臭)
指那些已经被添加了太多属性或者方法的,难以维护的的函数或类。通常这种情况不是突然出现的,而是随着代码进化而不断积累,特别是在没有人专门维护代码的时候。
超长的方法
特征和症状
一个方法中包含了太多行代码。在一个方法中如果代码超过10行,那就应该考虑拆分。一个方法中的代码越多,你越难看清楚这个方法到底干了什么。
原因
就像加州旅馆,代码被不断的加入到一个方法中但是却从来不删除代码。因为写代码要比读代码容易的多,这种气味通常不易察觉,直到有一天你的代码变成怪异的,超重的怪兽。
人们往往不愿意创建新的方法,而更愿意将代码塞在已有的方法里:“就两行代码,没必要写个新函数”,于是不断就“两行代码“加入进来。正这是这种想法导致方法面变得越来越长,最后变成一团乱麻。
解决办法
只有一条规则:如果你觉得需要为方法里的代码写注释,那么你就应该为那些代码新建一个方法。即使需要被注释的的代码只有一行也应该这么做。如果代码有了一个可以描述的名字(方法名),其他人就可以安心的跳过这部分代码,去看他们想看的部分。
你有一些可以被分组的代码
void printOwing() {
printBanner();
//print details
System.out.println("name: " + name);
System.out.println("amount: " + getOutstanding());
}
将这些代码拆分到新的方法中
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails(double outstanding) {
System.out.println("name: " + name);
System.out.println("amount: " + outstanding);
}
你会将一个表达式的结果赋值给本地变量,以便稍后使用
double calculateTotal() {
double basePrice = quantity * itemPrice;
if (basePrice > 1000) {
return basePrice * 0.95;
}
else {
return basePrice * 0.98;
}
}
你可以将整个表达式拆分到新的方法中,然后以函数执行代理本地变量
double calculateTotal() {
if (basePrice() > 1000) {
return basePrice() * 0.95;
}
else {
return basePrice() * 0.98;
}
}
double basePrice() {
return quantity * itemPrice;
}
如果你有一组接受相同参数的方法,那么你应该讲这些参数封装在一个新的对象里。
如果你从一个对象中获得多个值,然后将这些值传递给一个方法
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
boolean withinPlan = plan.withinRange(low, high);
可以将整个对象当做参数传递
boolean withinPlan = plan.withinRange(daysTempRange());
使用了太多的局部变量导致没办法进行方法拆分
class Order {
//...
public double price() {
double primaryBasePrice;
double secondaryBasePrice;
double tertiaryBasePrice;
// long computation.
//...
}
}
可以将这个方法改写成类,这样,局部变量就编程了函数的属性,然后就可以对之前的方法进行拆分了。
class Order {
//...
public double price() {
return new PriceCalculator(this).compute();
}
}
class PriceCalculator {
private double primaryBasePrice;
private double secondaryBasePrice;
private double tertiaryBasePrice;
public PriceCalculator(Order order) {
// copy relevant information from order object.
//...
}
public double compute() {
// long computation.
//...
}
}
你有一系列复杂的条件判断(if-then / else or switch)
if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
charge = quantity * winterRate + winterServiceCharge;
}
else {
charge = quantity * summerRate;
}
将条件判断中复杂的部分拆分到单独的方法中
if (notSummer(date)) {
charge = winterCharge(quantity);
}
else {
charge = summerCharge(quantity);
}
负债
- 函数或者方法越长,人们就越难理解它,维护它。通常程序中那些存在最久的类,都是拥有短方法的类。
- 另外,长的方法通常会变成重复代码的避难所。
性能
有人会担心方法数量的增加会导致程序性能的下降,的确是这样。但是大部分情况下这种影响可以忽略不计。但好的方面是:如果你把代码弄得简单明了,那么必要的时候你很容易对代码进行优化。
网友评论