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

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

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例