重构——重构组织函数(2)

Introduce Explaining Variable

有一个复杂的表达式,将该复杂表达式的结果放入一个临时变量,以此变量的名称来解释表达式用途。
动机:在某些情况下,表达式可能非常的复杂以至于难以阅读。这样,临时变量可以帮助你将表达式分解为比较容易管理的形式。 在条件逻辑中,引入解释性变量就显得比较有价值。本文的重构手法是比较常见的手法之一,但是对其的使用又不是那么的多。因为一般情况下,我们都可以使用提炼函数来解释一段代码的意义。毕竟临时变量只有在它所处的那个函数中才有意义,局限性较大。

if((platform.toUpperCase().indexOf("MAC") > -1) &&
		(browser.toUpperCase().indexOf("IE") > -1) &&
		wasInitialized() && resize > 0)
	{
		//do something
	}

?

final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResize = resize > 0;

if(isMacOs && isIEBrowser && wasInitialized() && wasResize){
		//do something
}

范例

//重构前
	double price(){
		// 价格 = basePrice - quantity discount + shipping
		return _quantity * _itemPrice -
				Math.max(0, _quantity - 800) * _itemPrice * 0.15 +
				Math.min(_quantity * _itemPrice * 0.25, 100);
}
//重构后
	double price(){
		// 价格 = basePrice - quantity discount + shipping
		final double basePrice = _quantity * _itemPrice;
		final double quantityDiscount = Math.max(0, _quantity - 800) * _itemPrice * 0.15;
		final double shipping = Math.min(basePrice * 0.25, 100);
		return basePrice - quantityDiscount + shipping;
}

运用Extract Method处理:
对于上述代码,通常不以临时变量来解释其动作意图,而是更喜欢使用提炼函数。

//重构后
	double price(){
		// 价格 = basePrice - quantity discount + shipping
		return basePrice() - quantityDiscount() + shipping();
	}
	
	private double basePrice(){
		return _quantity * _itemPrice;
	}
	
	private double shipping(){
		return Math.min(basePrice() * 0.25, 100);
	}
	
	private double quantityDiscount(){
		return Math.max(0, _quantity - 800) * _itemPrice * 0.15;
	}

Split Temporary Variable

你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果。针对每次赋值,创造一个独立、对应的临时变量。
动机: 在某些情况下,临时变量用于保存一段冗长代码的运算结果,以便稍后使用。这种临时变量应该只被赋值一次。如果它被赋值超过一次,就意味着它们在函数中承担了一个以上的责任。如果临时变量承担多个责任,它就应该被替换(分解)为多个临时变量,使得每一个变量只承担一个责任。同一个临时变量承担两件不同的事情,会让代码阅读者糊涂。

//重构前
	double temp = 2 * (_height + _width);
	System.out.println(temp);
	temp = _height + _width;
	System.out.println(temp);

?

//重构后
	final double perimeter = 2 * (_height + _width);
	System.out.println(perimeter);
	final double area = _height + _width;
	System.out.println(area);

Remove Assignments to Parameters

代码对一个参数进行赋值。以一个临时变量取代该参数的位置。

//重构前
	int dicount(int inputVal, int quantity, int yearToDate){
		if(inputVal > 50) inputVal-=10;
	}

?

//重构后
	int dicount(final int inputVal, int quantity, int yearToDate){
		int result = inputVal;
		if(result > 50) result-=10;
	}

动机: 我想你很清楚“对参数赋值”这个说话的意思。如果把一个名称为foo的对象作为参数传递给某个函数,那么“对参数赋值”意味改变foo,使它引用另一个对象。但是,如果在“被传入对象”身上进行什么操作,那没问题,我们经常会这么做。这里只针对“fool被改变而指向另一个对象”这种情况来讨论:

void test(Object foo){
	foo.changedBySomeWay(); //that's ok
	foo=anotherObject; //trouble will appear
}

我们之所不这样做,是因为它降低了代码的清晰度,而且混用了按值传递和按引用传递这两种参数传递方式。JAVA只采用按值进行传递。
在按值传递的情况下,对参数的任何修改,都不会对调用端造成任何影响。如果你只以参数表示“被传递进来的东西”,那么代码会清晰的多,因为这种用法在所有语言中都表现出相同的语义。
在JAVA中,一般不要对参数赋值:如果你看到手上的代码已经这么做了,就应该使用本文的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值