重构 - 提炼函数,消除重复代码

一、参考资料

  1. 《重构 2》6.1 提炼函数
  2. 《重构 2》10.3 以卫语句取代嵌套条件表达式

二、重构步骤 - 以提炼重复计算函数为例子

演示代码

如下代码,存在坏味道

  1. 充斥着if else
  2. 重复的new Length()创建
  3. 重复的参数this.value 和 target_unit
    唯一的不同点 仅仅是计算的方式 如 value / 3,value * 12
public Length as(Unit target_unit) {
	Length result = this;
	if (this.unit == Unit.FOOT) {
	  if (target_unit == Unit.YARD) {
			result = new Length(this.value / 3, target_unit);
	  } else if (target_unit == Unit.INCH) {
			result = new Length(this.value * 12, target_unit);
	  }
	}

	if (this.unit == Unit.YARD) {
	  if (target_unit == Unit.INCH) {
			result = new Length(this.value * 36, target_unit);
	  } else if (target_unit == Unit.FOOT){
			result = new Length(this.value * 3, target_unit);
	  }
	}
  return result;
}	

具体步骤

注:以下只展示最关键的代码降低认知负载,做了变化的地方,在代码上都会注释

1.提取重复new创建

例如:下面代码中new Length()为重复创建

public Length as(Unit target) {
  // 提取了重复的new创建
  Length result = new Length(this.value, target);
    if (this.unit == Unit.FOOT) {
      if (target == Unit.YARD) {
        // 提取了重复的new创建
        result = new Length(this.value /3, target);
      } else if (target == Unit.INCH) {
        // 提取了重复的new创建
        result = new Length(this.value * 12, target);
      }
    }
    //省略...,其他代码同理
}

  return result;
}

2.提取会变化的信息

例如:下面代码中this.value是会变化的

public Length as(Unit  target) {
  // 提取会变化的信息
  double value = this.value;
  Length result = new Length(value, target);

  if (this.unit == Unit.FOOT) {
    if (target == Unit.YARD) {
      // 提取会变化的信息
      value = value / 3;
      result = new Length(value, target);
    } else if (target == Unit.INCH) {
      // 提取会变化的信息
      value = value * 12;
      result = new Length(value, target);
    }
  }
    //省略...,其他代码同理
  return result;
}

3.使用抽取的共有信息,并删除原有信息

例如:下面代码中,共有信息new Length() 和 value,因为使用了共有信息,此时原有信息result就没用了
注:当没用引用时,result变量名会变灰,此时可以用 alt + enter,会有个安全删除,选择安全删除,则会吧所有的result都同步删掉

public Length as(Unit target) {
  double value = this.value;

  if (this.unit == Unit.FOOT) {
    if (target == Unit.YARD) {
      value = value / 3;
    } else if (target == Unit.INCH) {
      value = value * 12;
    }
  }
   // 使用抽取出来的信息
  return new Length(value, target);
}

4.提取计算函数

  1. 例如:下面代码,吧获取value的信息,抽取为方法,封装具体实现,这样当阅读这段代码时,不需要了解具体实现,通过方法名就可以知道这是做什么,相比之前,需要去看这段代码是干什么的,可读性更高。
  2. 建议:在代码中,可以采取抽取方法的方式,对代码的结构进行一个划分,使其可读性更好
  3. 抽取方法快捷键参考
    后继会出文章,讲解,抽取为方法的好处,以及实战
public Length as(Unit target) {
  // 提炼函数
  double value = getValue(target);
  return new Length(value, target);
}
// 提炼函数
private double getValue(Unit target) {
	...
}

5.使用卫语句,简化代码逻辑

public Length getValue(Unit target) {
	if (this.unit == Unit.FOOT) {
	  if (target == Unit.YARD) {
	  	//  提前返回,消除else
		return this.value / 3;
	  }
	  if (target == Unit.INCH) {
		//  提前返回,消除else
		return this.value * 12;
	  }
	}

	//省略...
	return this.value;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值