Replace Temp with Query,顾名思义,表示你用查询来替换临时变量本身,临时变量对于函数来说是只有当前函数可见的,如果你在同类的别的地方要用到这个变量你就必须重新写表达式来获取这个变量,这样的话你就会在不经意间让你的函数变得复杂起来,所以如果你想要使用Extract Method,那么Replace Temp with Query是必不可少的一个步骤。而我们前面介绍的Inline Temp其实是这个手法的一部分,两者的区别在于Inline Temp已经有了表达式自身,只需要做简单的替换就可以,表示用表达式本身把临时变量给去掉。而Replace Temp with Query更加全面,里面包含了提炼表达式到函数本身,然后替换引用点(Inline Temp)。如果你把所有的临时变量都替换为一个查询,你的类的结构和逻辑将非常清晰,这样将更加有利于你的重构和进行优化。

这个重构手法有个很重要的前提就是临时变量只能被赋值一次,或者赋值给临时变量的表达式不受别的条件约束进行改变。对于其他情况,可能你应该需要Split Temporary Variable或Separate Query from Modifer把情况弄的简单点之后再运用本手法。对于有那种收集结果的临时变量或者循环中要进行累积的变量,你需要将程序的逻辑复制到查询函数中去。

做法一般都是找到只被赋值一次的临时变量,然后用const加以修饰进行编译(表示之后没有对这个变量进行修改),然后将所有对这个变量等号右边的表达式提炼到一个函数中去(这个步骤其实已经是Inline Temp的前提条件),然后将这个函数先声明为private(如果以后有别的类需要再改为public,这样可以保证接口的整洁性),判断这个查询函数本身会不会修改对象内容,如果会的话就需要运用Separate Query from Modifer进行重构。这些步骤都做好之后,就可以用Inline Temp将之前做好的函数进行变量替换。

有些同学可能会担心性能问题,我明明一个变量放在那好好的,你不要用,导致你每次去使用多要做一次查询。对于这种情况大可放心,重构的目的是让程序更加清晰,有了更加清晰的程序之后再具体做优化也不迟,况且根据二八原则,仅仅这条查询语句倘若你系统真的出现了性能问题也不大可能,如果实在是因为这条语句,你也可以把变量再放回去。

下面来看下具体例子:

double getPrice()
{
int basePrice = m_quanity * m_itemPrice;
double discountFactor;
if (basePrice > )
{
discountFactor = 0.95
}
else
{
discountFactor = 0.98
}
return basePrice * discountFactor;
}

例子很简单,但是有两个临时变量,可以看到basePrice和discountFactor都被赋值了一次,如果我想重构这个函数,我们上面讲到了,Extract Method之前要做Replace Temp with Query,那么用Query来取代这两个临时变量那会让我们更加清晰重构的路线。

首先第一步,我们来进行basePrice的提炼,在之前加上const,进行编译,发现没有问题。

double getPrice()
{
const int basePrice = m_quanity * m_itemPrice;
double discountFactor;
if (basePrice > )
{
discountFactor = 0.95
}
else
{
discountFactor = 0.98
}
return basePrice * discountFactor;
}

然后我们将等号之后的提炼到独立小函数中去(为了确保查询函数本身的特质--不修改对象本身,我们这里可以利用C++特性给函数加上const限定)

int basePrice() const
{
return m_quanity * m_itemPrice;
}

这样原来的函数就变成了

double getPrice()
{
const int basePrice = basePrice();
double discountFactor;
if (basePrice > )
{
discountFactor = 0.95
}
else
{
discountFactor = 0.98
}
return basePrice * discountFactor;
}

然后逐步使用Inline Temp把对basePrice的地方进行替换并进行编译测试,最后直接把basePrice的声明去掉。重复这个动作来进行提炼discountFactor得到

double getPrice() const
{
return basePrice() * discountFactor();
} int basePrice() const
{
return m_quanity * m_itemPrice;
}

double discountFactor()
{
    if (basePrice() > 1000)
    {
        return 0.95
    }
    else
    {
        return 0.98
    }
}

可以看到,在提炼discountFactor的时候,对于临时变量basePrice如果没有进行提炼,那么就需要将这个临时变量传进去。像这样

double discountFactor(int basePrice)
{
if (basePrice > )
{
return 0.95
}
else
{
return 0.98
}
}

可以明显的看到,这个重构手法对于函数本身来说,提高了清晰度,也让我们进行后期重构能够更加便捷。

『重构--改善既有代码的设计』读书笔记----Replace Temp with Query的更多相关文章

  1. 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object

    有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...

  2. 『重构--改善既有代码的设计』读书笔记----Replace Array with Object

    如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...

  3. 『重构--改善既有代码的设计』读书笔记----Replace Data Value with Object

    当你在一个类中使用字段的时候,发现这个字段必须要和其他数据或者行为一起使用才有意义.你就应该考虑把这个数据项改成对象.在开发初期,我们对于新类中的字段往往会采取简单的基本类型形式来保存,但随着我们开发 ...

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

    与Inline Method相同,有时候犹豫需要Extract Method,需要对一些临时变量进行内联,而这个往往是Replace Temp with Query的一部分.简单来说,当你看到这种 d ...

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

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

  6. 『重构--改善既有代码的设计』读书笔记----Extract Method

    在编程中,比较忌讳的一件事情就是长函数.因为长函数代表了你这段代码不能很好的复用以及内部可能出现很多别的地方的重复代码,而且这段长函数内部的处理逻辑你也不能很好的看清楚.因此,今天重构第一个手法就是处 ...

  7. 『重构--改善既有代码的设计』读书笔记----Change Value to Reference

    有时候你会认为某个对象应该是去全局唯一的,这就是引用(Reference)的概念.它代表当你在某个地点对他进行修改之后,那么所有共享他的对象都应该在再次访问他的时候得到相应的修改.而不会像值对象(Va ...

  8. 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data

    当MVC出现的时候,极大的推动了Model与View分离的潮流.然而对于一些已存在的老系统或者没有维护好的系统,你都会看到当前存在大把的巨大类----将Model,View,Controller都写在 ...

  9. 『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field

    如果你直接访问一个字段,你就会和这个字段直接的耦合关系变得笨拙.也就是说当这个字段权限更改,或者名称更改之后你的客户端代码都需要做相应的改变,此时你可以为这个字段建立设值和取值函数并且只以这些函数来访 ...

随机推荐

  1. (转载)PHP_Memcache函数详解

    (转载)http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/04/19/2021605.html memcache函数所有的方法列表如下: M ...

  2. 【宽搜】Vijos P1206 CoVH之再破难关

    题目链接: https://vijos.org/p/1206 题目大意: 给你开始和结束两张4x4的01图,每次操作只能够交换相邻的两个格子(有公共边),问最少的操作步数. 题目思路: [搜索] 这题 ...

  3. Java中的数据类型及相互转换方法

    本文主要讲解两个部分: 一.Java中的数据类型有哪些? 二.数字类型和字符串类型相互转换的方法? 一.Java中的数据类型有哪些: Java中的数据类型有:基本数据类型和引用数据类型: 基本数据类型 ...

  4. 编写Lex和Yacc

    大学课程设计中,有一次是编写Lex(词法分析器的生成器)和Yacc(语法分析器的生成器),编写这类工具软件不是一件容易的事情.这篇文章记录了当时编程时候的主要思想,主要还是编译原理的思想. 准备 Le ...

  5. 配置openStack使用spice

    注:因为在测试配置过程中反复配置过多次,以下内容可能并不完整,有待验证. 按官方文档(openstack-install-guide-yum-juno)搭建和配置的OpenStack默认使用novnc ...

  6. M - 昂贵的聘礼 - poj1062

    Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低 ...

  7. 第一节:Scrapy开源框架初探

       Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中.  具体开发流程如下:   一.确定待抓取网站 当您需要从某 ...

  8. STRUCTS 2 UPLOAD

    {LJ?Dragon}[标题]structs2 上传文件中文乱码问题 {LJ?Dragon}[Daily] 1.配置struts.xml文件 <?xml version="1.0&qu ...

  9. spring 定时器----quartz启动问题

    今天,突然要用到定时器,在网上查了下资料,保存下以方便后面查找: 什么是动态定时任务:是由客户制定生成的,服务端只知道该去执行什么任务,但任务的定时是不确定的(是由客户制定). 这样总不能修改配置文件 ...

  10. mysql 查询随机一条记录

    项目中 需要查询热门帖子,查询结果是多条中一条:SQL 如下,记录下