重构之重新组织函数(ExTract Method)

                                                                             引用自 Refactoring Improving the Design of Existing Code ---Martin Fowler


 

1.Extract Method(提炼函数)

 

范例(Examples)

1、无局部变量(No Local Variables)

 

public class ExtractMethodWithoutLocalVariable {

        //1、无局部变量(No Local Variables)
        public void printUserInfoWithoutLocalVariables()
        {
            System.out.println("******************************");
            System.out.println("************用户信息**********");
            System.out.println("******************************");


        }
        //改为
        public void printUserInfoWithoutLocalVariablesAdvanced(){

            printStart();

            System.out.println("Name="+"王有财"+"Age="+"26"+"Sex"+"男性");

        }

        public void printStart(){
            System.out.println("******************************");
            System.out.println("************用户信息**********");
            System.out.println("******************************");
        }
}

 

2、有局部变量(Using Local Variables)

public class ExtractMethodWithLocalVariable {


    //1、有局部变量(No Local Variables)
    public void printUserInfoWithoutLocalVariables()
    {
        System.out.println("******************************");
        System.out.println("************用户信息**********");
        System.out.println("******************************");

        String name = "王有财";
        String age = "26";
        String sex = "男性";
        System.out.println("Name="+name+"Age="+age+"Sex"+sex);
    }

    //改为
    public void printUserInfoWithoutLocalVariablesAdvanced(){

        printStart();
        String name = "spring yang";
        String age = "26";
        String sex = "Man";
        printPersonalValue(name,age,sex);

    }

    public void printStart(){
        System.out.println("******************************");
        System.out.println("************用户信息**********");
        System.out.println("******************************");
    }

    public void printPersonalValue(String name,String age,String sex){
        System.out.println("Name="+name+"Age="+age+"Sex"+sex);
    }




}

3、对局部变量现赋值(Reassigning)

如果被提炼代码对局部变量赋值,问题就变得复杂了。这里我们只讨论临时变量的问题。如果你发现源函数的参数被赋值,应该马上使用Remove Assignments to Parameters。

public class ExtractMethodWithReassigningValue {

    //如果被提炼代码对局部变量赋值,问题就变得复杂了。
    //如果你发现源函数的参数被赋值,应该马上使用Remove Assignments to Parameters。
    public void printSum()
    {
        double result = 0;
        for (int i = 0; i <= 100; i++)
            result += i;
        System.out.println("From 1 add to 100 result is"+result);
    }

    public void printSumAdvanced(){
        printInfo(sum());
    }

    public double sum(){
        double result = 0;
        for (int i = 0; i <= 100; i++)
            result += i;

        return result;
    }

    public void printInfo(double sum){
        double result = sum;
        System.out.println("From 1 add to 100 result is"+result);
    }
}

 


 

动机:

                   Extract Method (提炼函数)是最常用的重构手法之一。当看见一个过长的函数或者一段需要注释才能让人理解用途的代码,就应该将这段代码放进一个独立函数中。

      简短而命名良好的函数的好处:

      首先,如果每个函数的粒度都很小,那么函数被复用的机会就更大;其次,这会使高层函数读起来就想一系列注释;

      再次,如果函数都是细粒度,那么函数的覆写也会更容易些。一个函数多长才算合适?长度不是问题,关键在于函数名称和函数本体之间的语义距离。如果提炼可以强化代码的清晰度,那就去做,就算函数        名称必提炼出来的代码还长也无所谓。

做法:

1、创造一个新函数,根据这个函数的意图对它命名(以它“做什么“命名,而不是以它“怎样做”命名)。

即使你想要提炼的代码非常简单,例如只是一条消息或一个函数调用,只要新函数的名称能够以更好方式昭示代码意图,你也应该提炼它。但如果你想不出一个更有意义的名称,就别动。

2、将提炼出的代码从源函数复制到新建的明白函数中。

3、仔细检查提炼出的代码,看看其中是否引用了“作用域限于源函数”的变量(包括局部变量和源函数参数)。

4、检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量。

5、检查被提炼代码段,看看是否有任何局部变量的值被它改变。如果一个临时变量值被修改了,看看是否可以将被提炼代码处理为一个查询,并将结果赋值给修改变量。如果很难这样做,或如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动提炼出来。你可能需要先使用 Split Temporary Variable(分解临时变量),然后再尝试提炼。也可以使用 Replace Temp with Query(以查询取代临时变量)将临时变量消灭掉。

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

7、处理完所有局部变量后,进行编译。

8、在源函数中,将被提炼代码段替换给对目标函数的调用。

     如果你将如何临时变量移到目标函数中,请检查它们原本的声明式是否在被提炼代码段的外围。如果是,现在可以删除这些声明式了。

9、编译,测试。


 

 

posted on 2019-12-02 09:30  低调的小郭  阅读(966)  评论(0编辑  收藏  举报