资讯专栏INFORMATION COLUMN

重构-改善既有代码的设计(六)--重新组织函数

CoyPan / 1998人阅读

摘要:函数重构重构有很大一部分都是在重构函数。这条也要具体情况具体使用函数对象取代函数函数对象代替函数大函数变成类你有一个大型函数,其中对局部变量的使用使你无法采用提炼函数。将这个大型函数放进一个多带带对象中,如此一来局部变量就成了对象内的字段。

函数重构

重构有很大一部分都是在重构函数。尤其是长函数。这是问题的根源。以下是重构方法

Extract Method 提炼函数

提炼函数:(由复杂的函数提炼出独立的函数或者说大函数分解成由小函数组成)你有一段代码可以被组织在一起并独立出来。将这段代码放进一个独立函数,并让函数名称解释该函数的用途。

重构前

void printOwing() {   
    //print banner  
    System.out.println(“*********”);  
    System.out.println(“Banner”);  
    System.out.println(“*********”);  
    //print details  
    System.out.println ("name: " + _name);   
        System.out.println ("amount " + getOutstanding());   
}  

重构后

                                           
void printOwing()  {  
    printBanner();   
    printDetails(getOutstanding());   
}   
  
Void printBanner()  {  
    //print banner  
    System.out.println(“*********”);  
    System.out.println(“Banner”);  
    System.out.println(“*********”);  
}  
void printDetails (double outstanding)   {   
    System.out.println ("name: " + _name);   
    System.out.println ("amount " + outstanding);   
}

Inline Method 内联函数

内联函数:(直接使用函数体代替函数调用 ) 一个函数调用的本体与名称同样清楚易懂。在函数调用点插入函数体,然后移除该函数
重构前

int getRating() {  
    return moreThanfiveLateDeliverise() ? 2 : 1;  
}  
bool moreThanfiveLateDeliverise() {  
    return _numberOfLateLiveries > 5;  
}  

                                                       

重构后

int getRating(){  
     return _numberOfLateLiveries > 5 ? 2 : 1;  
}  
Inline Temp 内联临时变量

内联临时变量:(表达式代替临时变量)你有一个临时变量,只被一个简单表达式赋值一次,而它妨碍了其他重构手法。将所有对该变量的引用动作,替换为对它赋值的那个表达式自身
重构前

double basePrice = anOrder.BasePrice();  
return basePrice(>1000);  
     

                                                  

重构后

return (anOrder.BasePrice() >1000);
Replace Temp with Query 以查询代替临时变量

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

重构前

double basePrice = _quantity*_itemPrice;  
if (basePrice > 1000) {  
    return basePrice * 0.95;  
else   
    return basePrice * 0.98;  
                                                         

重构后

if (basePrice() > 1000)  
    return basePrice() * 0.95;   
else   
    return basePrice() * 0.98;   
……  
double basePrice() {   
    return _quantity * _itemPrice;   
}    

注:这一条我始终不觉得合理。如果从性能上看。明显重构前的性能会比第二种更好。而且更容易理解

Introduce Explaining Variable 引入解释性变量

引入解释性变量:(复杂表达式分解为临时解释性变量)你有一个复杂的表达式。将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途。
重构前

if (Platform.ToUpperCass().indexOf("MAC") > -1 && (Browser.ToUpperCass().indexOf("Ie") > -1) && WasInitalized() ) {  
    //do something  
 }  

重构后
const bool imMacOs = Platform.ToUpperCass().indexOf("MAC") > -1;
const bool isIeBrowser = Browser.ToUpperCass().indexOf("Ie") > -1;
const bool wasInitalized = WasInitalized();
if (imMacOs && isIeBrowser && wasInitalized)
{

//do something  

}
注:这一条和上上条并没有冲突。上上条指的是单纯地取值函数,如get方法。这一条针对无法理解的方法链

Split Temporary Variable 分解临时变量

分解临时变量:(临时变量不应该被赋值超过一次)你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果。针对每次赋值,创造一个独立、对应的临时变量
重构前

double temp = 2 + (_height + _width);  
Console.WriteLine(temp);  
temp = _height * _width;  
Console.WriteLine(temp);  

                                                        

重构后

const double perimeter = 2 + (_height + _width);  
Console.WriteLine(perimeter);  
const double area = _height * _width;  
Console.WriteLine(area);

 
Remove Assigments to Parameters 移除对参数的赋值

移除对参数的赋值:(不要对参数赋值)代码对一个 参数赋值。以一个临时变量取代该参数的位置。
重构前

int discount (int inputVal, int quantity, int yearToDate){   
    if (inputVal > 50) inputVal -= 2;   
}  
     

重构后

int discount (int inputVal, int quantity, int yearToDate) {   
     int result = inputVal;   
     if (inputVal > 50) result -= 2;   
}  

注:如果传的是对象。除非你想要操作对象。否则就留下了bug的风险。因为对象传入方法被改变了。(这条也要具体情况具体使用)

Replace Method with Method object 函数对象取代函数

函数对象代替函数:(大函数变成类)你有一个大型函数,其中对局部变量的使用使你无法采用 Extract Method (提炼函数)。将这个大型函数放进一个多带带对象中,如此一来局部变量就成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。
重构前

class Order...  
double price() {   
    double primaryBasePrice;  
    double secondaryBasePrice;   
    double tertiaryBasePrice;   
    // long computation; ...   
}   

重构后

 class Price {   
        double primaryBasePrice;  
        double secondaryBasePrice;   
        double tertiaryBasePrice;   
        public void price(){
        // long computation; ...   
   

或者可以采用static method
Substitute Algorithm 替换算法

替换算法:(函数本体替换为另一个算法)你想要把某个算法替换为另一个更清晰地算法。将函数本体替换为另一个算法。
重构前

String foundPerson(String[] people){   
    for (int i = 0; i < people.length; i++)  {   
        if (people[i].equals ("Don")){  
             return "Don";   
         }  
         if (people[i].equals ("John")) {  
           return "John";   
         }   
         if (people[i].equals ("Kent")){   
                return "Kent";   
         }   
     }  
     return "";   
}
                                            

重构后

String foundPerson(String[] people){   
    List candidates   
             = Arrays.asList(new String[] {"Don",   "John", "Kent"});   
    for (int i=0; i

注:如果可以使用更简单并清晰的方式。就果断换方式

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69704.html

相关文章

  • Java学习路线总结,搬砖工逆袭Java架构师(全网最强)

    摘要:哪吒社区技能树打卡打卡贴函数式接口简介领域优质创作者哪吒公众号作者架构师奋斗者扫描主页左侧二维码,加入群聊,一起学习一起进步欢迎点赞收藏留言前情提要无意间听到领导们的谈话,现在公司的现状是码农太多,但能独立带队的人太少,简而言之,不缺干 ? 哪吒社区Java技能树打卡 【打卡贴 day2...

    Scorpion 评论0 收藏0
  • 读书笔记《重构 改善既有代码设计

    摘要:重构在不改变代码的外在的行为的前提下对代码进行修改最大限度的减少错误的几率本质上,就是代码写好之后修改它的设计。重构可以深入理解代码并且帮助找到。同时重构可以减少引入的机率,方便日后扩展。平行继承目的在于消除类之间的重复代码。 重构 (refactoring) 在不改变代码的外在的行为的前提下 对代码进行修改最大限度的减少错误的几率 本质上, 就是代码写好之后 修改它的设计。 1,书中...

    mdluo 评论0 收藏0
  • 重构-改善既有代码设计(五)--重构列表

    摘要:什么是重构列表重构方法需要以一种特定的格式记录下来。这些重构手法到底有多成熟本书中提到的重构手法第章。做法创造新函数,以用途命名提炼代码到函数中检查变量名是否符合规范在源函数中,将被提炼代码替换为函数引用测试范例重构前重构后 什么是重构列表 重构方法需要以一种特定的格式记录下来。按照格式记录下来的重构方法的集合叫重构列表 重构的记录格式 每个重构手法可分为5个部分: 名称 构建重构词汇...

    davidac 评论0 收藏0
  • 重构-改善既有代码设计(七)-- 在代码之间搬移特性

    摘要:前言决定把责任放在哪对于对象设计是最重要的之一。重构可以很好的解决这个问题。方法建立一个新类,将相关的字段和函数从旧类搬移到新类。方法将这个类的所有特性搬移到另一个类中,然后移除原类。让这个扩展品成为源类的子类或包装类。 前言 决定把责任放在哪对于对象设计是最重要的之一。重构可以很好的解决这个问题。以下是笔者的重构方法注:客户:调用接口客户类:使用了接口的类服务类:提供服务的类 Mov...

    solocoder 评论0 收藏0
  • 重构-改善既有代码设计(一)--重构,第一个案例

    摘要:并根据目录选读第章重构,第一个案例这是只是一个方法。绝大多数情况下,函数应该放在它所使用的数据的所属对象内最好不要在另一个对象的属性基础上运用语句。 什么是重构 在不改变代码外在行为的前提下,对代码做出修改以改进程序内部的结构简单地说就是在代码写好后改进它的设计 谁该阅读这本书 专业程序员(能够提高你的代码质量) 资深设计师和架构规划师(理解为什么需要重构,哪里需要重构) 阅读技巧...

    acrazing 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<