重构手法之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(提炼 ...
随机推荐
- MongoDB学习教程(1)
1.简介: MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.MongoDB 旨在为WEB应用提供可扩展的高性能数据 ...
- Python自学笔记-Django分页器小实例
from django.core.paginator import Paginator iter = 'abcdefhijklmnopqw' paginator = Paginator(iter,4) ...
- YYModel学习总结YYClassInfo(1)
OC的run-time 机制,简直像是网络上的猫! 我在开发中很少用到,但是作为iOS开发 人家肯定会问这个东西,所以深入的学习了下. 对于 run-time的入手,YYModel的学习,简直让人美滋 ...
- Linq常见操作示例
static void DeferredQuery() { var names = new List<string> { "Nino", "Alberto&q ...
- #tensorflow入门(1)
tensorflow入门(1) 关于 TensorFlow TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操 ...
- [转]pycharm快捷键
开始学习python用的ide是pycharm,之前做java一种用eclipse,刚开始使用pycharm快捷键与eclipse有很大不同,慢慢适应中. 下面列举了下pycharm的快捷键,内容转自 ...
- 【转】浅谈UML的概念和模型之UML九种图
原文地址:浅谈UML的概念和模型之UML九种图 目录: UML的视图 UML的九种图 UML中类间的关系 上文我们介绍了,UML的视图,在每一种视图中都包含一个或多种图.本文我们重点讲解UML每种图的 ...
- Linux CentOS7 安装 Mysql5.7.19
第二次安装会安装失败 1.先停止mysql服务 service mysql stop 2.检查是否卸载干净 find / -name mysql 多用几个命令检查,不要删到其他组件的 ...
- SPARK 创建新任务
1.应用程序创建 SparkContext 的实例 sc 2.利用 SparkContext 的实例来创建生成 RDD 3.经过一连串的 transformation 操作,原始的 RDD 转换成为其 ...
- python-opencv aplpha混合
import cv2 import os import numpy as np print os.listdir(os.getcwd()) img = cv2.imread('building.jpg ...