《重构改善既有代码的设计》之重构列表--在对象之间搬移特性(一)

2023-12-16 14:58

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

一、Move Method(搬移函数)

你的程序中,有个函数与其所贮类之外的类进行更多交流。

在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数编程一个单纯的委托函数,或是将旧函数完全移除。

动机

“搬移函数”是重构理论的支柱。如果一个类有太多的行为,或如果一个类与另一个类有太多合作而形成的高度耦合,我就会搬移函数。通过这种手段,可以使系统中的类更简单,这些类最终也将更干净利落的实现系统交付的任务。

做法

1、检查源类中被源函数所使用的一切特性(包括字段和函数),考虑它们是否也该被搬移。

如果某个特性只被你打算搬移的那个函数用到,就应该将它一起搬移。如果另有其他函数使用了这个特性,你可以考虑将使用该特性的所有函数全部一并移除。有时候,搬移一组函数比逐一搬移简单些。

2、检查源类的子类和超类,看看是否有该函数的其他声明。

如果出现其他声明,你或许无法进行搬移,除非目标类也同样表现出多态性。

3、在目标函数中声明这个函数。

你可以为此函数选择一个新名称---对目标类更有意义的名称。

4、将源函数的代码复制到目标函数中。调整后者后,使其能在新家中正常运行。

如果目标函数使用了源类中的特性,你得决定如何从目标函数引用源对象。如果目标类中没有相应的引用机制,就把源对象的引用当做参数,传给新建立的目标函数。

如果源函数包含异常处理,你得判断逻辑上应该由哪个类来处理这一异常。如果应该由源类来负责,就把异常留在原地。

5、编译目标类。

6、决定如何从源函数正确引用目标对象。

可能会有一个现成的字段或函数帮助你取得目标对象。如果没有,就看能否轻松建立一个这样的函数。如果还是不行,就得在源类中新建一个字段来保存目标对象。这可能是一个永久性修改,但你也可以让它是暂时性的,因为后继的其他重构项目可能会把这个新建字段去掉。

7、修改源函数,使之成为一个纯委托函数。

8、编译、测试

9、决定是否删除源函数,或将它当做一个委托函数保留下来。

如果你经常要在源对象中引用目标函数,那么将源函数作为委托函数保留下来会比较简单。

10、如果要移除源函数,请将源类中对源函数的所以调用,替换为对目标函数的调用。

你可以每修改一个引用点就编译并测试一次。也可以通过一次“查找/替换”改掉所有引用点,这通常简单一点。

11、编译测试

二、Move Field(搬移字段)

你的程序中,某个字段被其所贮类植物的另一个类更多的使用。

在目标类新建一个字段,修改源字段的所有用户,令它们改用新字段。

动机

在类之间移动状态和行为,是重构过程中必不可少的措施。随着系统发展,你将会发现自己需要的新的类,并需要将现有的工作责任拖到新的类中。在这个星期看似合理而正确的设计决策,到了下个星期可能不再正确。这没问题。如果你从来没有遇到这种情况,那才有问题。

如果我发现,对于一个字段,在其所贮之外的另一个类中有更多函数使用了它,我就会考虑搬移这个字段。上述所谓“使用”可能是通过设值 取值函数间接进行的。我也可能移动该字段的用户(某个函数),这取决于是否需要保持接口不受变化。如果这些函数看上去很适合待在原地,我就选择搬移字段。

使用Extract Method时,我也可能需要搬移字段。此时我回先搬移字段,然后再搬移函数。

做法

1、如果字段的访问级是public,使用Encapsulate Field将它封装起来。

如果你有可能移动那些频繁访问该字段的函数,或如果有许多函数访问某个字段,先适应Self Encapsulate Field也许会有帮助。

2、编译测试

3、在目标类中建立于源字段相同的字段,并同时建立相应的设值 取值函数。

4、编译目标类

5、决定如何在源对象中引用目标对象。

首先看是否有一个现成的字段或函数可以助你得到目标对象。如果没有,就看能否轻易建立这样一个函数。如果还不行,就得在源类中新建一个字段来存放目标对象。这可能是个永久性修改,但你也可以让它是暂时的,因为后续重构可能会把这个新建字段给去掉。

6、删除源字段。

7、将所有源字段的引用替换为对某个目标函数的调用。

如果需要读取该变量,就把对源字段的引用替换为对目标取值函数的调用;如果要对该变量赋值,就把对源字段的引用替换成对设值函数的调用。

如果源字段不是private的,就必须在源类的所有子类中查找源字段的引用点,并进行相应替换。

8、编译、测试。

这篇关于《重构改善既有代码的设计》之重构列表--在对象之间搬移特性(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

Java集合之Iterator迭代器实现代码解析

《Java集合之Iterator迭代器实现代码解析》迭代器Iterator是Java集合框架中的一个核心接口,位于java.util包下,它定义了一种标准的元素访问机制,为各种集合类型提供了一种统一的... 目录一、什么是Iterator二、Iterator的核心方法三、基本使用示例四、Iterator的工

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

Python 常用数据类型详解之字符串、列表、字典操作方法

《Python常用数据类型详解之字符串、列表、字典操作方法》在Python中,字符串、列表和字典是最常用的数据类型,它们在数据处理、程序设计和算法实现中扮演着重要角色,接下来通过本文给大家介绍这三种... 目录一、字符串(String)(一)创建字符串(二)字符串操作1. 字符串连接2. 字符串重复3. 字

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

Vue实现路由守卫的示例代码

《Vue实现路由守卫的示例代码》Vue路由守卫是控制页面导航的钩子函数,主要用于鉴权、数据预加载等场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、概念二、类型三、实战一、概念路由守卫(Navigation Guards)本质上就是 在路

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

Python屏幕抓取和录制的详细代码示例

《Python屏幕抓取和录制的详细代码示例》随着现代计算机性能的提高和网络速度的加快,越来越多的用户需要对他们的屏幕进行录制,:本文主要介绍Python屏幕抓取和录制的相关资料,需要的朋友可以参考... 目录一、常用 python 屏幕抓取库二、pyautogui 截屏示例三、mss 高性能截图四、Pill