`

《重构》笔记 二 重新组织你的函数 Extract Methord

阅读更多

重新组织你的函数 Compsing Methords

 

 一 Extract Methord

 动机:Extract Methord是最常用的重构手法之一,当我看到一个过长函数或则一段需要注释才能让人理解用途的代码的时候,我会将这段代码放到独立的函数中去。如果函数的粒度都很小(finely grained)那么函数间彼此服用的机会就更大,其次,这会使高层函数读起来就像一系列注释,而且函数的复写(override)也会容易些。一个函数长度不是问题,关键在于,函数名称和函数本体之间的语义距离 (semantic distance),如果提炼的动作可以强化代码的清晰度,那就去做,就算函数名比提炼出的代码本身还长也无所谓。

 

做法:

  1.创造一个新的函数,根据这个函数的意图来命名它,用做什么来命名而不是怎么做,若果你想不出一个更好的名字就不要动,记住小步前进。

  2.将提炼出的函数重原函数拷贝到目标函数

  3.检查提炼的代码中是否有引用了的变量

  4.检查是否有临时变量,如果有在目标函数将他们声明为临时变量

  5.检查被提炼的代码是否有局部变量的值被它改变。如果一个临时变量值被修改了,看看是否可以将被提炼的代码处理为一个查询,并将结果赋值给相关变量。如果很难这样做或修改的变量不只一个,你可能要线使用 Split Temporay variable 然后在尝试提炼。也可以使用Replace Tem With Query将临时变量消灭掉

  6.将被提炼的代码中需要读取的局部变量,当做参数穿给目标函数

  7.处理完所有局部变量之后进行编译

  8.在原函数将被提炼的代码转为对目标函数的调用

  9编译测试

 

eg:

  a. 无局部变量 NoLocalConnectionVariables

 

private function printOwing():void {
    var outstanding:Number = 0.0;
    var e:Array = _orders;

     //trace the Banner
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");

     //calculate outstanding
     for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

     //trace details
     trace("name: "+ _name);
     trace("outstanding : " + outstanding );
}
 

    ==>

 

private function printOwing():void {
    var outstanding:Number = 0.0;
    var e:Array = _orders;

     printBanner();



     //calculate outstanding
     for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

     //trace details
     trace("name: "+ _name);
     trace("outstanding : " + outstanding );
}

private function printBanner

():void {
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");
} 

 

 

 

   b. 无局部变量 NoLocalConnectionVariables

   如果这么简单那么重构的难点在哪呢,对的就在局部变量,包括传进原函数的参数和原函数所声明的临时变量。局部变量的作用域仅限于原函数,所以当我使用 Extract Methord 时,必须花额外的功夫去处理这些变量。某些时候他们会妨碍我们,使我们无法重构。

   局部变量的最简单的情况就是,被提炼的码只是读取这些变量的值而不去修改他们,这种情况我可以直接当参数穿给目标函数。

 

 

private function printOwing():void {
    var outstanding:Number = 0.0;
    var e:Array = _orders;
 
     printBanner();

     //calculate outstanding
     for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

     //trace details
     trace("name: "+ _name);
     trace("outstanding : " + outstanding );
}

private function printBanner():void {
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");
} 

 

 

  ==》

 

 

private function printOwing():void {
    var outstanding:Number = 0.0;
    var e:Array = _orders;
 
     printBanner();

     //calculate outstanding
     for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

     printDetails

(outstanding );
}

private function printBanner():void {
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");
} 

private fuction printDetails

(outstanding :Number):void {
   trace("name: "+ _name);
   trace("outstanding : " + outstanding );
}

 

 

  c. 对局部变量在赋值,如果被提炼码对局部变量赋值,问题就变得复杂了,这里只看临时变量的问题,如果你发现原函数的参数被在赋值,因该马上使用 Remove Asssignments 帖哦 Parameters。被赋值的临时变来那个也分为两种情况。比较简单的的情况是:这个变量只在被提炼的代码中,如果是这样,你可以将这个临时变量的声明一到那个被提炼码中,然后一起提炼出去。另一种情况就是,被提炼码之外的的代码也使用了这个变量。这又分两种情况:如果这个变量在被提炼后为在被使用,你只需直接在目标函数中修改她就可以了;如果,被提炼码之后的的代码还使用了这个变量,你就需要,让目标函数返回改变后的值。

 

 

private function printOwing():void {
    var outstanding:Number = 0.0;
    var e:Array = _orders;
 
     printBanner();

     //calculate outstanding
     for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

     printDetails(outstanding );
}

private function printBanner():void {
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");
} 

private fuction printDetails(outstanding :Number):void {
   trace("name: "+ _name);
   trace("outstanding : " + outstanding );
}

 

 

   ==> 提炼计算的代码

 

 

 

private function printOwing():void {
     printBanner();
     var outstanding:Number = getOutSatnding

();
     printDetails(outstanding );
}

private function printBanner():void {
     trace("***************");
     trace("*Customer Owes**");
     trace("***************");
} 

private fuction printDetails(outstanding :Number):void {
   trace("name: "+ _name);
   trace("outstanding : " + outstanding );
}

private funtion getOutSatnding

():Number{
    var e:Array = _orders;
    var outstanding:Number = 0.0;
    for each(var i:Object in e) {
       outstanding+=  i.getAmount();     
     }

    return outstanding;

}
分享到:
评论

相关推荐

    Thransform.rar_Methord JAVA

    标题中的“Thransform.rar_Methord JAVA”指的是一个使用Java编程语言实现的数组转置方法,这个程序可能被设计用来帮助理解线性代数中的矩阵转置概念。线性代数是计算机科学中非常重要的一门数学分支,尤其是在处理...

    ADB工具及使用方法(ADB tool and use methord)

    通过`ADB功能使用说明.doc`文档,你可以进一步了解ADB的高级用法,如多设备管理、进程分析、性能监控等。熟练掌握ADB工具,对于Android开发者来说,不仅能提高工作效率,还能更好地理解和操控Android系统。在实际...

    Numericle computer simulation of the formation of transverse dunes using DNS methord

    由于全球荒漠化的日益严重,沙漠学领域研究沙漠形成和演变的机制对于理解全球环境变化具有重要意义。沙漠中的沙丘是一种常见的沙漠地貌特征,其形态多样,包括新月形沙丘、横向沙丘、星状沙丘等。...

    Android代码-AndGappProxy

    Test Methord: adb shell telent 127.0.0.1 9999 GET http://www.twitter.com . . . . Contact me: Blog:http://www.impjq.net Email:pengjianqing@gmail.com Twitter:http://twitter.com/pengjianqing

    music播放简单音乐(汇编语言编写)

    "methord.inc"文件可能包含了一些常用函数或宏的定义,这些在"music.asm"中被调用来实现具体的音乐播放功能。这可能包括读取文本文件、解码音乐数据、设置频率和持续时间等操作。在汇编语言中,这样的代码复用可以...

    双向滚动slider

    The Key Point is in "WLRangeSlider.m" in the methord - (void)initLayers { //z这里更改时间轴---24为24个小时 _maxValue = 24.0; _minValue = 0.0; _leftValue = 0; _rightValue = 6.5; _leftValue1=21.0; _...

    ADE_Reschedule:这是使用ADE方法进行工厂重新计划的工具

    ADE_RescheduleThis is a implement of factory rescheduling which is using ADE methord.一个运用python实现的简单的车间调度方案,采用了遗传算法的改进算法“自适应差分算法”(ADE),选择过程中采用了模拟退火...

    mqtt_server:基于C ++的mqtt_server

    React器模式下的MQTT Server 基于c ++ 0x11和accept4的简单React器使用log4cplus-... #define LOG_DEBUG my_printf #定义LOG_WARN my_printf #define LOG_ERROR my_printf #定义LOG_TRACE_METHORD my_printf #万一

Global site tag (gtag.js) - Google Analytics