返回总目录


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(引用解释性变量)的更多相关文章

  1. introduce explaining variable 引入解释变量

    一段复杂的计算的表达式(一般 逻辑判断  if(a!=1 && b!=Null && a>b  ) && .... 直接在代码中参与到 代码的逻辑 ...

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

      发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().in ...

  3. 重构手法之Split Temporary Variable(分解临时变量)

    返回总目录 本小节目录 Split Temporary Variable(分解临时变量) Remove Assignments to Parameters(移除对参数的赋值) 6.6Split Tem ...

  4. 『重构--改善既有代码的设计』读书笔记----Introduce Explaning Variable

    有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数.这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰 ...

  5. 重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)

    重构手法16:Introduce Foreign Method (引入外加函数)你需要为提供服务的类增加一个函数,但你无法修改这个类.在客户类中建立一个函数,并以第一参数形式传入一个服务类实例. 动机 ...

  6. 重构改善既有代码设计--重构手法06:Split Temporary Variable (分解临时变量)

    你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果.针对每次赋值,创造一个独立.对应的临时变量 double temp = 2 * (_height + _width); ...

  7. 重构改善既有代码设计--重构手法04:Replace Temp with Query (以查询取代临时变量)

    所谓的以查询取代临时变量:就是当你的程序以一个临时变量保存某一个表达式的运算效果.将这个表达式提炼到一个独立函数中.将这个临时变量的所有引用点替换为对新函数的调用.此后,新函数就可以被其他函数调用. ...

  8. 重构改善既有代码设计--重构手法01:Extract Method (提炼函数)

    背景: 你有一段代码可以被组织在一起并独立出来.将这段代码放进一个独立函数,并让函数名称解释该函数的用途. void PrintOwing(double amount) { PrintBanner() ...

  9. 重构手法之Extrct Method(提炼函数)

    返回总目录 本节包含3个手法: 1.Extract Method(提炼函数) 2.Inline Method(内联函数) 3.Inline Temp(内联临时变量) Extract Method(提炼 ...

随机推荐

  1. MongoDB学习教程(1)

    1.简介: MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.MongoDB 旨在为WEB应用提供可扩展的高性能数据 ...

  2. Python自学笔记-Django分页器小实例

    from django.core.paginator import Paginator iter = 'abcdefhijklmnopqw' paginator = Paginator(iter,4) ...

  3. YYModel学习总结YYClassInfo(1)

    OC的run-time 机制,简直像是网络上的猫! 我在开发中很少用到,但是作为iOS开发 人家肯定会问这个东西,所以深入的学习了下. 对于 run-time的入手,YYModel的学习,简直让人美滋 ...

  4. Linq常见操作示例

    static void DeferredQuery() { var names = new List<string> { "Nino", "Alberto&q ...

  5. #tensorflow入门(1)

    tensorflow入门(1) 关于 TensorFlow TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操 ...

  6. [转]pycharm快捷键

    开始学习python用的ide是pycharm,之前做java一种用eclipse,刚开始使用pycharm快捷键与eclipse有很大不同,慢慢适应中. 下面列举了下pycharm的快捷键,内容转自 ...

  7. 【转】浅谈UML的概念和模型之UML九种图

    原文地址:浅谈UML的概念和模型之UML九种图 目录: UML的视图 UML的九种图 UML中类间的关系 上文我们介绍了,UML的视图,在每一种视图中都包含一个或多种图.本文我们重点讲解UML每种图的 ...

  8. Linux CentOS7 安装 Mysql5.7.19

    第二次安装会安装失败 1.先停止mysql服务  service mysql stop 2.检查是否卸载干净   find / -name mysql      多用几个命令检查,不要删到其他组件的 ...

  9. SPARK 创建新任务

    1.应用程序创建 SparkContext 的实例 sc 2.利用 SparkContext 的实例来创建生成 RDD 3.经过一连串的 transformation 操作,原始的 RDD 转换成为其 ...

  10. python-opencv aplpha混合

    import cv2 import os import numpy as np print os.listdir(os.getcwd()) img = cv2.imread('building.jpg ...