重构手法之Introduce Explaining Variable(引用解释性变量)
5 Introduce Explaining Variable(引用解释性变量)
概要
你有一个复杂的表达式。
将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途。
动机
有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数。这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰化。这个重构手法在条件逻辑中用的比较多。
我们来看这样一个条件判断:
if(platform.ToUpper().IndexOf("MAC")>-&&browser.ToUpper().IndexOf("IE")>-&& wasInitialized()&&resize>)
{
//do something
}
是不是看上去晕晕的,不知道这个条件判断是判断什么的?
我们用这个手法重构一下:
bool isMacOs = platform.ToUpper().IndexOf("MAC") > -;
bool isIEBrowser = browser.ToUpper().IndexOf("IE") > -;
bool wasResized = resize > ;
if (isMacOs && isIEBrowser && wasInitialized()&& wasResized)
{
//do something
}
这样代码是不是很清晰。
范例
我们从一个简单的计算开始:
double GetPrice()
{
return _quantity * _itemPrice - Math.Max(, _quantity - ) * _itemPrice *
0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
这段代码很简单,但是不好理解。可以进行Introduce Explaning Variable,将_quantity * _itemPrice的计算结果放进临时变量中。
double GetPrice()
{
double basePrice = _quantity * _itemPrice;
return basePrice - Math.Max(, _quantity - ) * _itemPrice * 0.05 +
Math.Min(basePrice * 0.1, 100.0);
}
再将折扣提炼出来。
double GetPrice()
{
double basePrice = _quantity * _itemPrice;
double quantityDiscount = Math.Max(, _quantity - ) * _itemPrice * 0.05;
return basePrice - quantityDiscount + Math.Min(basePrice * 0.1, 100.0);
}
最后把运费计算提炼出来。最终代码如下。
double GetPrice()
{
double basePrice = _quantity * _itemPrice;
double quantityDiscount = Math.Max(, _quantity - ) * _itemPrice * 0.05;
double shipping = Math.Min(basePrice * 0.1, 100.0);
return basePrice - quantityDiscount + shipping;
}
这里虽然完成了,但是我们前面讲过,临时变量只在它所处的那个函数中才有意义,局限性较大,函数则可以在对象的整个生命中都有用,并且可以被其他对象使用。所以下面我们使用Extract Method方法对刚刚的示例进行重构。同时我们也推荐使用这种方法。
运用Extract Method处理上述范例
同样这样一个函数:
double GetPrice()
{
return _quantity * _itemPrice - Math.Max(, _quantity - ) * _itemPrice *
0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
这一次我们把底价计算、批发折扣以及运费都提炼到一个新函数中。最终代码如下:
double GetPrice()
{
return GetBasePrice() - GetQuantityDiscount() + GetShipping();
} private double GetQuantityDiscount()
{
return Math.Max(, _quantity - ) * _itemPrice * 0.05;
} private double GetBasePrice()
{
return _quantity * _itemPrice;
} private double GetShipping()
{
return Math.Min(GetBasePrice() * 0.1, 100.0);
}
比较两种手法
对比Extract Method和Introduce Explaining Variable这两种手法生成的函数:
1、前者生成的函数更短,更清晰易懂,而后者则产生了大量的临时变量,使函数变得更长;
2、前者生成了很多的独立函数,如果想在外部访问某个函数,直接调用就好,而后者得重新写方法供其调用。
小结
我个人比较推荐Extract Method这种手法,因为同一对象中的任何部分,都可以根据自己的需要取用这些提炼出来的函数。一开始我们可以把函数声明为private;如果其他对象需要它们,再释放这些函数的访问限制。
既然如此,那么我们什么时候使用Introduce Explaining Variable呢?在Extract Method这种手法需要花费更大工作量时。比如说,有一个拥用大量局部变量的算法,这时候用Extract Method这个手法就不好处理。
To Be Continued...
重构手法之Introduce Explaining Variable(引用解释性变量)的更多相关文章
- introduce explaining variable 引入解释变量
一段复杂的计算的表达式(一般 逻辑判断 if(a!=1 && b!=Null && a>b ) && .... 直接在代码中参与到 代码的逻辑 ...
- 重构改善既有代码设计--重构手法05:Introduce Explaining Variable (引入解释性变量)
发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().in ...
- 重构手法之Split Temporary Variable(分解临时变量)
返回总目录 本小节目录 Split Temporary Variable(分解临时变量) Remove Assignments to Parameters(移除对参数的赋值) 6.6Split Tem ...
- 『重构--改善既有代码的设计』读书笔记----Introduce Explaning Variable
有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数.这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰 ...
- 重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)
重构手法16:Introduce Foreign Method (引入外加函数)你需要为提供服务的类增加一个函数,但你无法修改这个类.在客户类中建立一个函数,并以第一参数形式传入一个服务类实例. 动机 ...
- 重构改善既有代码设计--重构手法06:Split Temporary Variable (分解临时变量)
你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果.针对每次赋值,创造一个独立.对应的临时变量 double temp = 2 * (_height + _width); ...
- 重构改善既有代码设计--重构手法04:Replace Temp with Query (以查询取代临时变量)
所谓的以查询取代临时变量:就是当你的程序以一个临时变量保存某一个表达式的运算效果.将这个表达式提炼到一个独立函数中.将这个临时变量的所有引用点替换为对新函数的调用.此后,新函数就可以被其他函数调用. ...
- 重构改善既有代码设计--重构手法01:Extract Method (提炼函数)
背景: 你有一段代码可以被组织在一起并独立出来.将这段代码放进一个独立函数,并让函数名称解释该函数的用途. void PrintOwing(double amount) { PrintBanner() ...
- 重构手法之Extrct Method(提炼函数)
返回总目录 本节包含3个手法: 1.Extract Method(提炼函数) 2.Inline Method(内联函数) 3.Inline Temp(内联临时变量) Extract Method(提炼 ...
随机推荐
- C语言 流缓冲
**From : https://www.gnu.org/software/libc/manual/html_node/Stream-Buffering.html** 12.20 流缓冲 通常情况下, ...
- 【特效】select美化
select的默认样式往往很丑,为保证页面样式风格统一,需要对select进行美化.虽然其美化的插件很多,一搜一大把,但是需要引入长长的css文件和js文件实在是件头痛的事.其实select的实现原理 ...
- 为选择屏幕的字段设置F4帮助
在没有参考 数据元素,域和搜索帮助的情况下,自定义F4 帮助 1,PARAMETERS: p_bukrs(4) TYPE C MATCHCODE OBJECT H_T001. 2,AT SELECTI ...
- Mvc 流程调用分析
链接地址 https://www.processon.com/view/link/59e71fbbe4b09000f03ce78e 总结: 1. 在Global.ascx 中我们使用RouteColl ...
- win10 UWP RSS阅读器
RSS简易信息聚合(也叫聚合内容)是一种RSS基于XML标准,在互联网上被广泛采用的内容包装和投递协议.RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使 ...
- LINUX 笔记-free命令
free命令可以显示Linux系统中空闲的.已用的物理内存及swap内存,及被内核使用的buffer. focus@ubuntu:~$ free -h total used free shared b ...
- Jenkins项目部署使用教程-----02视图及项目添加
注意:此以我公司为例,以svn上传代码 一.添加视图 1.点击右上角”+”号,新建新视图 勾选在该视图下显示的项目或者在该视图新建项目,点保存即可. 二.新建项目 1.点击左上角的新建,创建新项目. ...
- Asp.net MVC4高级编程学习笔记-模型学习第四课基架与模型绑定20171027
MVC模型 一.构建基架. MVC中的基架可以为应用程序提供CURD各种功能生成所需要的样板代码.在添加控制器的时候可以选择相应的模板以及实体对象来生成相应的模板代码. 首先定义一个模型类如下所示: ...
- 【Salvation】——登录注册存储数据&验证用户
写在前面:登录注册功能是在纯Unity3D环境内实现的,用到UGUI绘制界面技术,数据库的部分是后面拓展加进来的,这里数据存储是指存在XML用户文件中. 注册用户名和密码 zc() 用户名和密码登录 ...
- 用户 'IIS APPPOOL\Private' 登录失败。
用户 'IIS APPPOOL\Private' 登录失败. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细 ...