马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

重构之以查询取代临时变量(Replace Temp with Query)

  [复制链接]
查看5343 | 回复16 | 2019-2-25 23:13:01 | 显示全部楼层 |阅读模式
      临时变量,在我们写一个函数时或多或少都会要用到;相信大家也有遇到过,就因为要用到一个临时变量,而要写很长很长的一段逻辑处理才能取得,导致我们写的函数过长。不知道大家会不会有这样的感觉,看到一段这么长的一个函数就感到心烦,我就有这样的感觉;只要看到一大段代码在一个函数里面就想找出写这个函数的人打一吨(吐吐嘈就好了可别付出行动哦,毕竟我们是个有素质的人),更别说去改里面的bug了。单单去理解代码都是一件痛苦的事了,别说要了解里面的逻辑,里面的业务了。哪么我们换位思考下,自己是不是应该避免写出这样的代码呢。我们该怎么做呢?重构之以查询取代临时变量(Replace Temp with Query),就能帮助到我们。以查询取代临时变量(Replace Temp with Query)   
  1、临时变量只被赋值一次;
  2、确保提练出来的函数无任何副作用;
我们先来看一段代码
[C#] 纯文本查看 复制代码
        public double getPrice()
        {
            double basePrice = _quantity * _itemPrice;
            double discountFactor;
            if (basePrice > 1000)
            {
                discountFactor = 0.95;
            }
            else
            {
                discountFactor = 0.98;
            }
            return basePrice * discountFactor;
        }

代码中basePrice 就只做了一次赋值,后面就再也没有对这个basePrice 进行赋值操作了;所以我们可以把basePrice 这个临时变量提取出来当做一个函数。然后我们再看看提取出来对原函数有没有造成影响。从代码上可看出,只要我们的提取出来的函数返回一个double值,然后对basePrice 进行赋值,对原函数将没有任何的影响,因为原函数只关心是不是有basePrice这个变量,basePrice 变量是不是有值。所以代码可以变成下面这样
(注:这个重构有个小小的技巧,就是可以在临时变量前面加上const(常量)来初步判断他是否只做了一次赋值)
[AppleScript] 纯文本查看 复制代码

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

        private int basePrice()
        {
            return _quantity * _itemPrice;
        }

我们在来看看重构过一次的代码,从代码里面我们到还有discountFactor这个临时变量;我们是否能对他进行一次上面说的重构方法呢?我们来分析一下,代码里有两次对discountFactor进行了赋值,所以在临时变量前面加上const(常量)这一方法是不可行的。哪么就不能进行重构了吗?并不然细心的我们应该发现两次赋值是带有if(条件判断表达式)的,所以在条件判断表达式里面进行赋值其实就等于只做了一次赋值(相信这里聪明的你们都懂吧!不等的话去看看什么是条件判断表达式)。即然第一个条满足了,我们在来看看第二个条件:是否对原函数有影响;同样的原函数也只管discountFactor变量是否有值。所以我们可以重构成下面这样
[AppleScript] 纯文本查看 复制代码
       public double getPrice()
        {
            return basePrice() * discountFactor();
        }

        private int basePrice()
        {
            return _quantity * _itemPrice;
        }

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

好了,进行了两次的重构后getPrice函数代码就只有一行了;getPrice函数一目了然,提练出来的代码同样的相当简单;相对于没进行重构的getPrice函数更容易分析逻辑、了解业务,又不会被别人吐嘈何乐而不为呢!!!!




参考文献
重构——改善既有代码的设计   【美】Martin Fowler 著
                                                                         熊节 译











ibcadmin | 2019-2-26 08:51:58 | 显示全部楼层
多封装方法很好  代码简洁并且方便扩展

点评

所以代码的重构是个很重要的东西,但很多人都不会去重视  详情 回复 发表于 2019-2-26 15:41
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
wlqxm | 2019-2-26 09:11:30 | 显示全部楼层
很重要的一点:临时变量只被赋值一次。但文中例子中出现的次数是两次,并且随使用次数的增多,会带来更多的运算

点评

你说的是哪个变量,文中的例子都只赋值一次啊;如果被赋值两次就该考虑另外一种重构手法  详情 回复 发表于 2019-2-26 15:40
剑弑 | 2019-2-26 15:40:03 | 显示全部楼层
wlqxm 发表于 2019-2-26 09:11
很重要的一点:临时变量只被赋值一次。但文中例子中出现的次数是两次,并且随使用次数的增多,会带来更多的 ...

你说的是哪个变量,文中的例子都只赋值一次啊;如果被赋值两次就该考虑另外一种重构手法

点评

变量是赋值一次,但是你重构后的方法调用了两次(也就是说赋值了两次)  详情 回复 发表于 2019-2-27 09:13
剑弑 | 2019-2-26 15:41:14 | 显示全部楼层
ibcadmin 发表于 2019-2-26 08:51
多封装方法很好  代码简洁并且方便扩展

所以代码的重构是个很重要的东西,但很多人都不会去重视
wlqxm | 2019-2-27 09:13:18 | 显示全部楼层
剑弑 发表于 2019-2-26 15:40
你说的是哪个变量,文中的例子都只赋值一次啊;如果被赋值两次就该考虑另外一种重构手法

变量是赋值一次,但是你重构后的方法调用了两次(也就是说赋值了两次)

点评

basePrice()函数在整个程序来说的话,确实是有两个调用,但对于getPrice()而言,他只是做了一次的调用,至于discountFactor()函数里有调用basePrice()函数哪是discountFactor的工作了,跟getPrice并没有关系。  详情 回复 发表于 2019-2-27 11:14
剑弑 | 2019-2-27 11:14:28 | 显示全部楼层
wlqxm 发表于 2019-2-27 09:13
变量是赋值一次,但是你重构后的方法调用了两次(也就是说赋值了两次)

basePrice()函数在整个程序来说的话,确实是有两个调用,但对于getPrice()而言,他只是做了一次的调用,至于discountFactor()函数里有调用basePrice()函数哪是discountFactor的工作了,跟getPrice并没有关系。

点评

那是不是对于整个方法来说,一个方法里面有50次局部变量的使用,我重构了50个方法,其中一个是直接调用,其他是间接调用,就是做了减法?就只调用了一次?  详情 回复 发表于 2019-2-27 12:03
wlqxm | 2019-2-27 12:03:11 | 显示全部楼层
剑弑 发表于 2019-2-27 11:14
basePrice()函数在整个程序来说的话,确实是有两个调用,但对于getPrice()而言,他只是做了一次的调用,至 ...

那是不是对于整个方法来说,一个方法里面有50次局部变量的使用,我重构了50个方法,其中一个是直接调用,其他是间接调用,就是做了减法?就只调用了一次?

点评

从某种意义上来说是这样没错,如果这能让代码看起来更容易理解、代码更简洁的话为什么不这样做呢?当然如果如果从性能上考虑的话并不建议这样做,毕竟调用一个方法是有资源损耗的多了的话就影响性能了,就应该想想能  详情 回复 发表于 2019-2-27 13:58
剑弑 | 2019-2-27 13:58:43 | 显示全部楼层
wlqxm 发表于 2019-2-27 12:03
那是不是对于整个方法来说,一个方法里面有50次局部变量的使用,我重构了50个方法,其中一个是直接调 ...

从某种意义上来说是这样没错,如果这能让代码看起来更容易理解、代码更简洁的话为什么不这样做呢?当然如果如果从性能上考虑的话并不建议这样做,毕竟调用一个方法是有资源损耗的多了的话就影响性能了,就应该想想能有没有更好的重构手法了。
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则