《重构改善既有代码的设计》之重构列表--重新组织函数(一)

2023-12-16 14:58

本文主要是介绍《重构改善既有代码的设计》之重构列表--重新组织函数(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Extract Method(提炼函数)

你有一段代码可以被组织在一起并独立出来。

将这段代码放进一个独立函数中,并让函数名称解释该函数的用途。

Void printOwing(double amount){

printBanner();

//print details

System.out.println("name:" + _name);

System.out.println("amount:" + amount);

}

提炼后:

Void printOwing(double amount){

printBanner();

printDetails();

}

 

void printDetails(){

//print details

System.out.println("name:" + _name);

System.out.println("amount:" + amount);

}

动机

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

有几个原因造成我喜欢简短而命名良好的函数。首先,如果每个函数的粒度都很小,那么函数被复用的机会就更大;其次,这会使高层函数读起来就像一系列注释;再次,如果函数都是细粒度,那么函数的覆写也会更容易些。

做法

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

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

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

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

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

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

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

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

9、编译、测试。

二、Inline Method(内联函数)

    一个函数的本体与名称同样清晰易懂。

在函数调用点插入函数本体,然后移除该函数。 

int Rating(){

    Return(moreThanFiveLateDliveries())?2:1;

}

Boolean moreThanFiveLateDeliveries(){

Return _numberOfLateDeliveries > 5;

}

转换后:

int Rating(){

    Return (_numberOfLateDeliveries > 5)?2:1;

}

动机

本书经常以简短的函数表现动作意图,这样会使代码更清晰易懂。但有时候你会遇到某些函数,其内部代码函数名称一样清晰易读。也可能你重构了函数,使得其内容和其名称变得同样清晰。果真如此,你就应该去掉这个函数,直接使用其中的代码。间接性可能带来帮助,但非必要的间接性总是让人不舒服。

另一种需要使用Inline Method 的情况是:你手上有一群组织不甚合理的函数。你可以将它们都内联到一个大型函数中,再从中提炼出组织合理的小型函数。

做法

1、检查函数,确定它不具多态性。

?  如果子类继承了这个函数,就不要将此函数内联,因为子类无法覆写一个根本不存在的函数。

2、找出这个函数的所有引用点。

3、将这个函数的所有被调用点都替换为函数本体。

4、编译、测试。

5、删除该函数的定义。

三、Inline Temp(内联临时变量)   

你有一个临时变量,只被一个简单表达式赋值一次,而它妨碍了其他重构手法。

将所有对该变量的引用动作,替换为对它赋值的那个表达式本身。

Double basePrice = anOrder.basePrices();

Return (basePrice > 1000);

转换后:

Return ( anOrder.basePrices() > 1000);

动机

Inline Temp多半是作为Replace Temp with Query的一部分使用,所以真正的动机出现在后者那儿。唯一单独使用Inline Temp的情况是:你发现某个临时变量被赋予某个函数调用的返回值。一般来说,这样的临时变量不会有任何危害,可以放心地把它留在那儿。但如果这个临时变量妨碍了其他重构手法,例如Extract Method,你就应该将它内联化。

做法

1、检查给临时变量赋值的语句,确保等号右边表达式没有副作用。

2、如果这个临时变量并未声明为final ,那么就将它声明为final ,然后编译。(这可以检查该临时变量是否真的只被赋值一次)

3、找到该临时变量的所有引用点,将它们替换为“为临时变量赋值”的表达式。

4、每次修改后,编译并测试。

5、修改完所有引用点后,删除该临时变量的声明和赋值语句。

6、编译、测试。

这篇关于《重构改善既有代码的设计》之重构列表--重新组织函数(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/500874

相关文章

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

MyBatis设计SQL返回布尔值(Boolean)的常见方法

《MyBatis设计SQL返回布尔值(Boolean)的常见方法》这篇文章主要为大家详细介绍了MyBatis设计SQL返回布尔值(Boolean)的几种常见方法,文中的示例代码讲解详细,感兴趣的小伙伴... 目录方案一:使用COUNT查询存在性(推荐)方案二:条件表达式直接返回布尔方案三:存在性检查(EXI

深入解析 Java Future 类及代码示例

《深入解析JavaFuture类及代码示例》JavaFuture是java.util.concurrent包中用于表示异步计算结果的核心接口,下面给大家介绍JavaFuture类及实例代码,感兴... 目录一、Future 类概述二、核心工作机制代码示例执行流程2. 状态机模型3. 核心方法解析行为总结:三

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

pandas实现数据concat拼接的示例代码

《pandas实现数据concat拼接的示例代码》pandas.concat用于合并DataFrame或Series,本文主要介绍了pandas实现数据concat拼接的示例代码,具有一定的参考价值,... 目录语法示例:使用pandas.concat合并数据默认的concat:参数axis=0,join=

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.