重构手法之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(提炼 ...
随机推荐
- vuejs2+axios设置
http://www.cnblogs.com/wisewrong/p/6402183.html 1 当前项目安装axios $ cnpm i axios --save-dev 2 import axi ...
- 消息队列、OSS常用操作封装
public class MessageQueue { #region Private Properties private const string _accessKeyId = "&qu ...
- Jquery购物车jsorder改进版,支持后台处理程序直接转换成DataTable处理
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Windows系统下八大具有高逼格的DOS命令之一【ping】
ping命令: ping是用来检测网络是否通畅或者查询网络连接速度的一个基础命令.作为一名对计算机痴迷的爱好者来说,ping命令是需要第一个掌握的DOS命令.它所利用的原理是这样的:网络上的机器都有唯 ...
- 四种Sandcastle方法生成c#.net帮助类帮助文档
方法一 前端时间在网上收集和自己平时工作总结整理了<干货,比较全面的c#.net公共帮助类>,整理完成上传github之后我又想,既然是帮助类,总得有个帮助文档于是乎想到了Sandcast ...
- ajax请求service报405错误 - 【服务器不允许的方法】
产生原因:web服务器找不到service方法处理请求. 检查方向: ① service方法名称写错 ② service方法参数类型与标准不一致 ③ service方法异常,返回值类型和标准不一致 ④ ...
- Angular4 后台管理系统搭建(10) - 做一个通用的可跨域上传文件的组件
写的很慢,不知不觉这是第十篇了.但是我其他事情太多,只能抽空写下.现在angular4或angular2流行的上传方式是ng2-file-upload.它的功能很强大.但是我没有配置成可以跨域上传的. ...
- <Mastering KVM Virtualization>:第四章 使用libvirt创建你的第一台虚拟机
在第3章<搭建独立的KVM虚拟化>中,你安装并启动了libvirtd服务.你还引入了帮助你管理虚拟机的libvirt管理工具virt-manager和virsh. 相较于命令行,新用户总是 ...
- [Java第一个游戏]JFrame文本框下贪吃蛇
刚刚接触java的文本框绘图的知识点,然后就可以按照老师的提醒做一些简单的游戏,对JFrame加深一下,下面就贪吃蛇给出一些源代码,其实正真的实现的代码并不多,只是稍微处理一下就可以明白,下面代码均有 ...
- Struts2+Spring+Hibernate实现员工管理增删改查功能(一)之ssh框架整合
前言 转载请标明出处:http://www.cnblogs.com/smfx1314/p/7795837.html 本项目是我写的一个练习,目的是回顾ssh框架的整合以及使用.项目介绍: ...