读书笔记-重构方法之一:提炼方法(Extract Method)

第六章 重新组织你的函数

6.1  Extract Method(提炼方法)

对付过长函数,一般重要的重构方法就是Extract Method,他把一段代码从原先的函数中提取出来,放在单独的函数中。简洁而清晰,短小而精炼。

1 void printOwing (douoble amount)
2 {
3     printBanner();
4     //print details
5     System.out.println(“name:”+_name);
6     System.out.println(“amount”+amount);
7 }

提炼后:

 1 void printOwing (douoble amount)
 2
 3 {
 4
 5     printBanner();
 6
 7     printDetails();
 8
 9 }
10
11 Void printDetails(double amount)
12
13 {
14
15     System.out.println(“name:”+_name);
16
17     System.out.println(“amount”+amount);
18
19 }

Extract Method最大的困难就是处理局部变量,所以需要注意一下步奏。

做法:

1、创造一个新的函数,根据这个函数的意图来给他命名(以它[做什么]命名,而不是以它[怎么做]命名)。

2、将提炼出来的代码从源函数(source)拷贝到新建的目标函数(target)中。

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

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

5、检查被提炼码,看看是否有任何局部变量的值被它改变,或者被修改的变量不止一个,就不能原封不动的提炼出来了。

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

7、处理完所有的局部变量,在原函数中调用。

实例:

范例一:无局部变量

提炼前:

 1 Void printOwing()
 2
 3 {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=0.0;
 8
 9
10
11     //print banner
12
13     System.out.println(“*****************************”);
14
15     System.out.println(“********Customer Owes********”);
16
17     System.out.println(“*****************************”);
18
19
20
21     //calculate outstanding
22
23     While(e.hasMoreElements())
24
25     {
26
27     Order each=(Order) e.nextElement();
28
29     Outstanding+=each.getAmount();
30
31     }
32
33
34
35     //print details
36
37     System.out.println(“name:”+_name);
38
39     System.out.println(“amount”+outstanding);
40
41 }

我们可以轻松的提炼出 print banner 的代码。

 1     Void printOwing()
 2
 3     {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=0.0;
 8
 9     print Banner();
10
11     //calculate outstanding
12
13     While(e.hasMoreElements())
14
15     {
16
17     Order each=(Order) e.nextElement();
18
19     Outstanding+=each.getAmount();
20
21     }
22
23     //print details
24
25     System.out.println(“name:”+_name);
26
27     System.out.println(“amount”+outstanding);
28
29     }
30
31     Void printBanner()
32
33     {
34
35     //print banner
36
37     System.out.println(“*****************************”);
38
39     System.out.println(“********Customer Owes********”);
40
41     System.out.println(“*****************************”);
42
43     }

范例二:有局部变量

局部变量最简单的情况是:被提炼码只是读取这些变量的值,并不修改它们,这种情况下可以简单地将它们当做参数传给目标函数。

提炼前:

 1     Void printOwing()
 2
 3     {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=0.0;
 8
 9     print Banner();
10
11     //calculate outstanding
12
13     While(e.hasMoreElements())
14
15     {
16
17     Order each=(Order) e.nextElement();
18
19     Outstanding+=each.getAmount();
20
21     }
22
23     //print details
24
25     System.out.println(“name:”+_name);
26
27     System.out.println(“amount”+outstanding);
28     }

提炼后:

 1   void printOwing()
 2
 3     {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=0.0;
 8
 9     print Banner();
10
11     //calculate outstanding
12
13     While(e.hasMoreElements())
14
15     {
16
17     Order each=(Order) e.nextElement();
18
19     Outstanding+=each.getAmount();
20
21     }
22
23     printDetails(outstanding);
24
25     }
26
27     Void printDetails(double outstanding)
28
29     {
30
31     System.out.println(“name:”+ _name);
32
33     System.out.println(“amount”+ outstanding);
34
35     }

处理多个局部变量也可以使用上述这种方法。

范例三:对局部变量再赋值

如果被提炼码对局部变量赋值,问题就变得复杂了,这里我们只讨论临时变量的问题。

被赋值的临时变量也分为两种情况。比较简单的情况是:这个变量只是在被提炼码中使用,这样,可以将这个临时变量的声明一道被提炼码中,然后一起提炼出去。另一种情况是:被提炼码之外的代码也是用了这个变量。

提炼前:

 1     Void printOwing()
 2
 3     {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=0.0;
 8
 9     print Banner();
10
11     //calculate outstanding
12
13     While(e.hasMoreElements())
14     {
15
16     Order each=(Order) e.nextElement();
17
18     Outstanding+=each.getAmount();
19
20     }
21
22     printDetails(outstanding);
23
24     }

提炼后:

 1  void printOwing()
 2
 3     {
 4
 5     print Banner();
 6
 7     Double outstanding=getOutstanding();
 8
 9     printDetails(outstanding);
10
11     }
12
13     Double getOutstanding()
14
15     {
16
17     Enumeration e=_orders.elements();
18
19     Ddouble outstanding=0.0;
20
21     While(e.hasMoreElements())
22
23     {
24
25     Order each=(Order) e.nextElement();
26
27     Outstanding+=each.getAmount();
28
29     }
30
31     Return outstanding();
32
33     }

Enumeration 变量e只是在被提炼码中使用到,所以可以将它整个搬到新函数中。Double 变量 outstanding在被提炼码内外都被用到,所以必须让提炼出来的新喊出返回它。

这个例子中,outstanding变量只是很简单的被初始化为一个明确的值,所以可以只在新函数中对它初始化。如果代码还对这个变量做了其他处理,就必须将它的值作为参数传给目标函数。对于这种变化,最初的代码可能是这样:

 1 Void printOwing(double previousAmount )
 2
 3 {
 4
 5     Enumeration e=_orders.elements();
 6
 7     Ddouble outstanding=previousAmount * 1.2;
 8
 9     print Banner();
10
11     //calculate outstanding
12
13     While(e.hasMoreElements())
14
15     {
16
17     Order each=(Order) e.nextElement();
18
19     Outstanding+=each.getAmount();
20
21     }
22
23     printDetails(outstanding);
24
25 }

提炼后:

Void printOwing()

{

    Ddouble outstanding=previousAmount * 1.2;

    print Banner();

    Double outstanding=getOutstanding(outstanding);

//Double outstanding=getOutstanding(previousAmount * 1.2);

    printDetails(outstanding);

}

    Double getOutstanding(double initialValue))

{

    Ddouble outstanding=initialValue;

    Enumeration e=_orders.elements();

    While(e.hasMoreElements())

    {

    Order each=(Order) e.nextElement();

    Outstanding+=each.getAmount();

    }

    Return outstanding();
}
                                                                                                    

时间: 2024-10-10 18:14:57

读书笔记-重构方法之一:提炼方法(Extract Method)的相关文章

《计算机组成原理》-读书笔记(二)运算方法和运算器

计算机中使用的数据可分为两大类: 符号数据:非数字 符号的表示(ASCII.汉字.图形等) 数值数据:数字数据的表示方法(定点.浮点)   计算机常用的数据表示格式有两种: 定点表示:小数点位置固定(可表示带符号或不带符号的纯小数.纯整数) 浮点表示:小数点位置不固定(IEEE754)   十进制数串的表示: 字符串形式 BCD(压缩) 编码方式     有权码:8421码.2421码.5211码     无权码:余三码.格雷码 自定义数据表示   数值的机器码表示:原码.反码.补码.移码  

EffectiveJava读书笔记——考虑用静态工厂方法代替构造器(一)

参考网址:http://blog.csdn.net/mingyunduoshou/article/details/6149758 http://blog.163.com/[email protected]/blog/static/10182372420133220511247/ 静态工厂方法讲解 简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实

《重构-改善既有代码的设计》读书笔记

重构,第一个案例 1.1 起点 如果发现现有的代码结构使你无法很方便地添加新特性,那就先重构,使特性的添加比较容易进行后,再添加特性; 1.2 重构的第一步 为即将修改的代码建立可靠的测试环境 – 是人就会犯错,所以需要可靠的测试; 测试结果能够自我检验 – 成功"OK",失败列出失败清单并打印行号 (自动化对比测试结果是提高效率的前提); 1.3 分解并重组"巨型"函数 切分提炼长函数(Extract Method),并移至更合适的类(Move Method) –

《代码阅读方法与实践之读书笔记之一》

阅读代码是程序员的基本技能,同时也是软件开发.维护.演进.审查和重用过程中不可或缺的组成部分.<代码阅读方法与实践之读书笔记之一>这本书围绕代码阅读,详细论述了相关的知识与技能.我希望通过仔细阅读并学习本书,可以快速地提高我的代码阅读的技能与技巧,进而从现有的优秀代码.算法.构架.设计中汲取营养,提高自身的开发与设计能力.此次读了此书的前四章,以下是我从中汲取到的宝贵养分: 从第一章<导论>一节中我体会到了我们要养成一个经常花时间阅读别人编写的高品质代码的习惯,因为阅读高品质的代码

新随笔--读书笔记《学会提问》:学习提出好问题的思维方法

新随笔--读书笔记<学会提问>:学习提出好问题的思维方法 书中要点摘录: "对自己的所见所闻如何回应,你必须做出选择: 1.你把别人的观点当成自己的观点. 2. 对对方的观点进行批判后,再接收." 批注: 我平时也有这个问题,常常会不加思考的接受别人的观点,通常是比我资深或更专业的人的观点,大多数时候确实没有经过分析. 日后需要注意: 1. 或许他的论点是片面的,或已过时的,我没有分析,简单接受,时间长了会影响我的思维习惯. 2. 如果对观点进行批判后再接受,更能将谈话深入

《C#图解教程》读书笔记之三:方法

本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.方法那些事儿 (1)方法的结构:方法头-指定方法的特征,方法体-可执行代码的语句序列: (2)方法的调用:参数.值参数.引用参数.输出参数.参数数组: ①参数: 形参-本地变量,声明在参数列表中:形参的值在代码开始之前被初始化: 实参-实参的值用于初始化形参: ②值参数: 为形参在栈上分配内存,将实参的值复制到形参: ③引用参数: 不为形参在栈上分配内存,形参的参数名作为实参变量的别名指向同一位置,必须使用ref关

iOS开发中的那些的约定俗成(1)————《编写高质量iOS与OS X代码的52个有效方法》读书笔记(第一章)

iOS开发中的那些的约定俗成(1) ----<编写高质量iOS与OS X代码的52个有效方法>读书笔记(第一章) 前言 "我要成为一个高产的开发人员.""想要混的好,就得多努力." 写这些东西是因为毕竟看了书,但是看书看过去之后,也许印象不是很深刻,有些东西现在也理解不了,那我就把我理解的,现在就可以用到的东西,简单的写出来就好,让自己今后看到就能明白其中的意思. 还有就是锻炼一下表达,编辑能力,慢慢的提升自己,随时随地的都要有一个锻炼的心. 最后当然就

Effective Java读书笔记(3对于所有对象都通用的方法)

3.1 覆盖equals时请遵守通用约定 什么时候应该覆盖Object.equals()方法呢? 如果类具有自己特有的"逻辑相等"概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖equals方法. Object.equals()方法具有自反性.对称性.传递性.一致性和与null比较返回false的特点. 实现高质量equals方法的诀窍: (1)使用==操作符检查"参数是否为这个对象的引用".如果是,则返回true,这

《ASP.NET MVC高级编程(4版)》读书笔记(5)表单和HTML辅助方法

5.1 表单使用 5.1.1 action 和 method 特性 <form action="/Home/Index"> <input name="q" type="text"/> <input value="提交" type="submit" /> </form> 如果没有 method 默认是: get 方法. 5.1.2 GET 方法还是 POST 方