引入解释性变量

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42417535

        在上一篇文章中介绍了“以查询取代临时变量“。本文将介绍“引入解释性变量”这种重构手法。

        下面让我们来学习这种重构手法吧。

开门见山

        发现:你有一个复杂的表达式。

解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途。

	//重构前
	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
	}

动机

在某些情况下,表达式可能非常的复杂以至于难以阅读。这样,临时变量可以帮助你将表达式分解为比较容易管理的形式。

在条件逻辑中,引入解释性变量就显得比较有价值:你可以用这项重构将每个子句提炼出来,以一个良好命名的临时变量来解释对应条件子句的意义。另一种可能的情况是,对于那些比较长的算法,可以运用临时变量来解释每一步运算的意义。

本文的重构手法是比较常见的手法之一,但是对其的使用又不是那么的多。因为一般情况下,我们都可以使用提炼函数来解释一段代码的意义。毕竟临时变量只有在它所处的那个函数中才有意义,局限性较大,函数则可以在对象的整个生命周期中都有用,并且可被其它对象使用。但是,当局部变量使用提炼函数难以进行时,就可以尝试使用引入解释性变量。

做法

(1)声明一个final型的临时变量,将待分解之复杂表达式中的一部分动作的运算结果赋值给它。

(2)将表达式中的“运算结果”这一部分,替换为上述的临时变量。(如果被替换的这一部分在代码中重复出现,可以每次一个,逐一进行替换)

(3)编译,测试。

(4)重复上述过程,处理其它类似部分。

示例

我们从一个简单计算开始:

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

这段代码还是比较简单,不过现在要让其更加容易理解一些。

首先发现底价(basePrice)等于数量(quantity)乘以单价(item price)。于是可以把这一部分的计算结果放进一个临时变量中,同时将Math.min()函数中参数进行同样替换。

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

然后,将批发折扣(quantity discount)的计算提炼出来,并将运算结果赋予临时变量。

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

最后,再把搬运费(shipping)计算提炼出来,并将运算结果赋予临时变量。

	//重构后
	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;
	}

运用提炼函数处理

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

让我们从头开始:

	//重构前
	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
		return basePrice() -
				Math.max(0, _quantity - 800) * _itemPrice * 0.15 +
				Math.min(basePrice() * 0.25, 100);
	}

	private double basePrice(){
		return _quantity * _itemPrice;
	}

继续进行提炼,每次提炼一个新的函数。最后得到代码如下。

	//重构后
	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;
	}

本文主要介绍了重构手法——引入解释性变量。该重构方法主要是在提炼函数需要花费更大工作量时才使用。比如你有一个拥有大量局部变量的算法,那么使用提炼函数绝非易事。这时候就可以使用本文的方法来整理代码,然后再考虑下一步怎么办;一旦搞清楚代码逻辑后,就可以运用以查询取代临时变量把中间引入的那些临时变量去掉。

我想你会比较喜欢提炼函数,因为对于同一对象的任何部分,都可以根据自己的需要取用这些提炼出来的函数。一开始会把这些新函数声明为private;如果其它对象也需要它们,就可以轻易释放这些函数的访问控制。

最后,希望本文对你有所帮助。有问题可以留言,谢谢。(PS:下一篇将介绍重构笔记——分解临时变量)

重构笔记文章如下

重构笔记——入门篇

重构笔记——代码的坏味道(上

重构笔记——代码的坏味道(下)

重构笔记——构筑测试体

重构笔记——提炼函数

重构笔记——内联函数

重构笔记——内联临时变量

重构笔记——以查询取代临时变量

时间: 2024-08-07 19:11:20

引入解释性变量的相关文章

重构改善既有代码设计--重构手法05:Introduce Explaining Variable (引入解释性变量)

  发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0) {

代码重构之引入解释性变量

意图 临时变量可以帮助你将表达式分解为比较容易管理的形式 在较长的算法中,可以运用临时变量来解释每一步运算的意义 示例 /** * 引入解释性变量之前 * Created by luo on 2017/4/23. */ public class IntroduceExplainingVariableBefore { private String platform; private String browser; private int resize = 0; public void test()

第2章 重新组织函数(3):引入解释性变量、分解临时变量和移除对参数的赋值

5. 引入解释性变量(Introduct Explaining Variable) //引入解释性变量 //重构前 if((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0) { //do somethin

1.5 引入解释性变量

[1]源代码 1 bool wasInitialized() 2 { 3 // do something... 4 return true; 5 } 6 7 void Func(QString platform) 8 { 9 if (platform.toUpper().indexOf("MAC") > -1 && 10 platform.toUpper().indexOf("IE") > -1 && 11 wasInit

sed中引入shell变量

sed中引入shell变量的四种方法1.eval sed 's/$a/$b/' filename2.sed "s/$a/$b/" filename3.sed 's/'$a'/'$b'/' filename 4.sed s/$a/$b/ filename

introduce explaining variable 引入解释变量

一段复杂的计算的表达式(一般 逻辑判断  if(a!=1 && b!=Null && a>b  ) && .... 直接在代码中参与到 代码的逻辑中时 将负责的判断表达式 变成有意义的临时变量 boolean validA = a!=null && a!=1; boolean validB = b!=null; if(valiadA && validB){ ... } 如果可以extract method 可以不用引入解

python基础(内存分析,不引入第三方变量的方式交换变量的值)

a,b指向同一块内存地址 下面方法是重新给b赋值;a,b指向不同的内存地址 字符串或int类型内存分析 不引入第三方变量的方式,交换a,b的值 原文地址:https://www.cnblogs.com/jingw/p/9188511.html

javascript 变量的引入、变量的声明、变量的初始化

变量的引入及声明和初始化: 变量: 操作的数据都是在内存中操作 Js中存储数据使用变量的方式(名称,值--->数据) Js中声明变量都用var--->存储数据,数据应该有对应的数据类型 存储一个数字10,变量的声明及赋值: var num=100; 存储一个名字: Var name=’小黑’; 变量---作用:用来操作数据(可以存储,可以读取) 变量声明(有var 有变量名字,没有值): Js中声明变量都用var js中的每一行代码结束都应该有分号:(写代码有分号的习惯) Js中的大小写是区分

js声明引入和变量声明和变量类型、变量

问题: 在网页的发展历程中,发现网页不能对用户的数据进行自动校验,和提供一些特效. 解决: 使用javascript. 作用 可以让网页和用户进行直接简单的交互. 可以让网页制作特效和动画. 声明js代码域 1.<script type="text/javascript"></script> 2.<script src="js/my.js" type="text/javascript" charest="u