第三章和第六章代码大坏味道 函数过长&Extract Method (1)
来源:互联网 发布:hello world java 编辑:程序博客网 时间:2024/05/01 01:59
1:重复的代码(不仅仅是函数里,还有类之间)
Extract Method是我最常用的重构手法之一。当我看见一个过长的函数或者一段需要注释才能让人理解用途的代码,我就会将这段代码放进一个独立函数中。
有数个原因造成我喜欢简短而有良好命名的函数。首先,如果每个函数的粒度都很小(finely grained),那么函数之间彼此复用的机会就更大;其次,这会使高层函数码读起来就像一系列注释;再者,如果函数都是细粒度,那么函数的覆写(overridden)也会更容易些。
而且只有当你能给小型函数很好地命名时,它们才能真正起作用,所以你需要在函数名称下点功夫。人们有时会问我,一个函数多长才算合适?在我看来,长度不是问题,关键在于函数名称和函数本体之间的语义距离(semantic distance )。如果提炼动作 (extracting )可以强化代码的清晰度,那就去做,就算函数名称比提炼出来的代码 还长也无所谓。(有点累了,明天再看。)
继续:
1:原来的代码
void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0; // print banner System.out.println ("**************************"); System.out.println ("***** Customer Owes ******"); System.out.println ("**************************"); // calculate outstanding while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } //print details System.out.println ("name:" + _name); System.out.println ("amount" + outstanding); }这个方法原来是这个样子的,按照作者的说法,不在乎多少代码,而是在于函数之间的语义的距离,所以,首先把打印banner语句提炼出来。
void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0; printBanner(); // calculate outstanding while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } //print details System.out.println ("name:" + _name); System.out.println ("amount" + outstanding); } void printBanner() { // print banner System.out.println ("**************************"); System.out.println ("***** Customer Owes ******"); System.out.println ("**************************"); }
再往下走,打印details的两条语句用到了一个局部变量outstanding。那么提炼为一个带一个参数的函数,最后变为:
void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0; printBanner(); // calculate outstanding while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } printDetails(outstanding); } void printDetails (double outstanding) { System.out.println ("name:" + _name); System.out.println ("amount" + outstanding); }
看上面的printOwing函数,计算变量值的那一段代码也可以提炼出来。只不过这个代码里面对于局部变量outstanding赋值了,所以要在提炼出来的方法里声明一个变量作为返回值:
void printOwing() { printBanner(); double outstanding = getOutstanding(); printDetails(outstanding); } double getOutstanding() { Enumeration e = _orders.elements(); double outstanding = 0.0; while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } return outstanding; }
因为Enumeration变量只是在提炼出来的代码中用到,所以整个搬到新函数里,这样的话,看printOwing这个函数,里面只是说明每一步做什么了,非常清晰。
如果outstanding这个变量不是明确的初始化为一个值,而是调用了其它的变量,那么就作为一个参数传进来。
void printOwing(double previousAmount) { double outstanding = previousAmount * 1.2; printBanner(); outstanding = getOutstanding(outstanding); printDetails(outstanding); } double getOutstanding(double initialValue) { double result = initialValue; Enumeration e = _orders.elements(); while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); result += each.getAmount(); } return result; }
然后再整理下,得到下面的精简的函数:
void printOwing(double previousAmount) { printBanner(); double outstanding = getOutstanding(previousAmount * 1.2); printDetails(outstanding); }
综上,如果一个函数过于复杂,那么就运用这个方法进行提炼,记住,一个函数最好只是实现一个功能。
- 第三章和第六章代码大坏味道 函数过长&Extract Method (1)
- 代码的坏味道之二 :Long Method(过长函数)
- 第三章 代码的坏味道(一)
- 第三章 代码的坏味道(二)
- 第三章代码的坏味道
- 第三章 代码的坏味道
- 看出笔记-第三章-代码坏味道
- 重构 第三章 代码的坏味道
- 代码的坏味道之四 :Long Parameter List(过长参数列)
- 代码坏味道之过长的参数列
- 《重构》读书笔记(四)——第三章 代码的坏味道
- 坏味道之3 过大类 & Extract class & Move Method & Encapsulate Field & Self Encapsulate Field
- 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)
- 代码的坏味道
- 代码的坏味道
- 代码的坏味道
- 代码中的坏味道
- 代码的坏味道
- 文字即艺术
- ExecutorService线程池
- 全局变量、静态全局变量、静态局部变量和局部变量的区别
- Oracle Length 和 Lengthb 函数说明 .(用来判断记录值里是否有中文内容)
- spring quartz
- 第三章和第六章代码大坏味道 函数过长&Extract Method (1)
- 出帐票同时打印
- android之壁纸机制
- pymongo基本操作用例
- VS2008 2010 ExtJS4 智能提示
- Analog - 模拟信号的解调
- 交通灯管理系统
- torque源码分析
- String,StringBuilder和StringBuffer的区别