java重构学习3:以查询代替临时变量(Replace Temp with Query)

本篇博客源自《Java重构:改善既有代码的设计》一书,介绍如何通过将临时变量转换为查询方法来提升代码质量。首先,找出只赋值一次的临时变量并声明为final,然后将其赋值表达式提炼为独立的查询方法,确保方法无副作用。最后,进行编译测试并内联临时变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列来自《java 重构改善既有代码的设计》一书

如:将一个临时变量temp保存到某一个表达式的运行结果。

做法将这个表达式提炼到一个独立函数(所谓查询式:Query),将这个临时变量的所有替换为新函数的调用。新函数可以被其它地方引用。

public double getPrice(){
	double basePrice = itemPrice * quantity;
	if(basePrice > 1000) {
		return basePrice * 0.95;
	} else {
		return basePrice * 0.98;
	}
}
可以写成:

public double getPrice() {
	if (basePrice() > 1000) {
		return basePrice() * 0.95;
	} else {
		return basePrice() * 0.98;
	}
}

public double basePrice() {
	return itemPrice * quantity;
}
考虑到临时变量只是暂时的,而且只能在所属函数内部使用,由于临时变量只有在所属函数内部使用,所以会驱使你写出更长的函数,因为只有这样你才能访问到要访问的临时变量。而如果把临时变量替换成为一个查询式(query method),那么同一个类的所有函数都能获取这份信息。

以查询替换临时变量往往是提炼方法(Extract Method)前必不可少的步骤,因为局部变量会让代码难以提炼,所以应该尽可能把他们替换成查询式。

做法:

1、找出只被赋值一次的临时变量(如果某个变量被赋值超过一次,考虑使用Split Temppopary Variable(解剖临时变量)将它分解成多个变量)。

2、将该变量申明为final(final只能被赋值一次)

3、编译(可以确保该临时变量确实只被赋值一次)。

4、将对该临时变量赋值的语句等号右侧部分提炼到一个独立的函数中(首先将它申明为private,如果后续有其他class需要调用,可以取消保护。同时要确保提炼出来的函数无任何连接影响,即该函数并不修改任何对象的内容)。

5、编译测试,并在临时变量上实施Inline Temp。

例:

public double getPrice() {
	int basePrice = quantity * itemPrice;
	double discountFactor;
	if (basePrice() > 1000) {
		discountFactor = 0.95;
	} else {
		discountFactor = 0.98;
	}
	return basePrice * discountFactor;
}
尽管代码十分清楚,依然将临时变量加上final,检查他们是否的确只被赋值一次。然后编译运行,这样处理的话如果没有问题,编译器就不会警告。之所以这样,是因为如果这个变量不只被赋值一次,那么我们就不能进行这次重构。

接下来就是提炼Query Method:

public double getPrice() {
	final int basePrice =  basePrice();
	final double discountFactor;
	if (basePrice() > 1000) {
		discountFactor = 0.95;
	} else {
		discountFactor = 0.98;
	}
	return basePrice() * discountFactor;
}

private int basePrice() {
	return itemPrice * quantity;
}
接下来将临时变量内联化,删除临时变量:

public double getPrice() {
	final double discountFactor;
	if (basePrice() > 1000) {
		discountFactor = 0.95;
	} else {
		discountFactor = 0.98;
	}
	return basePrice() * discountFactor;
}
同样的道理,提取discountFactor的Query Method

public double getPrice() {
	return basePrice() * discountFactor();
}

private int basePrice() {
	return itemPrice * quantity;
}

private double discountFactor() {
	if (basePrice() > 1000) {
		return 0.95;
	}
	return 0.98;
}
这是我们发现:如果没有将basePrice替换成一个查询表达式,将多么难提炼discountFactor().




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值