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

2023-12-16 14:58

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

七、Remove Assignments to Parameters(移除对函数的赋值)

代码对一个参数进行赋值

以一个临时变量取代该参数的位置

Int discount(int inputVal,int quantity,int yearToDate){

If(inputVal > 50)

    inputVal -= 2;

}

转换后:

Int discount(int inputVal,int quantity,int yearToDate){

Int result = inputVal;

If(inputVal > 50)

    result -= 2;

}

动机

首先,我要确定大家都清楚“对参数赋值”这个说法的意思。如果你把一个名为foo的对象作为参数传给某个函数,那么“对参数赋值”意味着改变foo,使它引用另一个对象。如果你在“被传入参数”身上进行什么操作,那没问题,我也总是这样干。我只针对“foo被改变而指向另个一个对象”这种情况讨论:

Void aMethod(Object foo){

foo.modifyInSomeWay();//that is ok.

Foo = anotherObject;//trouble and despair will follow you.

}

在按值传递的情况下,对参数的任何修改,都不会对调用端造成任何影响。那些用过按引用传递方式的人可能会在这一点上犯糊涂。

另一个让人糊涂的地方是函数本体内。如果你只以参数表示“被传递进来的东西”,那么代码会清晰很多,因为这种用法在所有语言中都表现出相同语义。

Java中,不要对参数赋值:如果你手上的代码已经这样做了,请使用Remove Assignments to Parameters.

做法

1、建立一个临时变量,把待处理的参数值赋予它。

2、以“对参数赋值”为界,将其后所有对此参数的引用点,全部替换为“对此临时变量的引用”。

3、修改赋值语句,使其改为对新建之临时变量赋值。

4、编译、测试。

八、Replace Method with Method Object(以函数对象取代函数)

你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method

将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。

Class Order ....

  Double price(){

    Double  primaryBasePrice

Double  secondaryBsePrice;

Double  teriaryBasePrice;

//long computation

  }

动机

有时局部变量的存在会增加函数分解的难度。如果一个函数之中局部变量泛滥成灾,那么想分解这个函数是非常困难的。Replace Temp with Query可以助你减轻这一负担,但有时候你会发现根本无法拆解需要拆解的函数。这种情况下,你应该把手伸进工具箱的深处,祭出函数对象这一法宝。

Replace Method with Method Object会将所有局部变量都变成函数对象的字段。然后你就可以对这个新对象使用Extract Method创造出新函数,从而将原本的大型函数拆解变短。

做法

1、建立一个新类,根据待处理函数的用途,为这个类命名。

2、在新类中建立一个final 字段,用以保存原先大型函数所有的对象。我们将这个字段成为“源对象”。同时,针对原函数的每个临时变量和每个参数,在新类中建立一个对应的字段保存之。

3、在新类中建立一个构造函数,接受源对象以及原函数的所有参数作为参数。

4、在新类中建立一个compute()函数。

5、将原函数的代码复制到compute()函数中。如果需要调用源对象的任何函数,请通过源对象调用。

6、编译

7、将旧函数的函数本体替换为这样一条语句:“创建上述新类的一个新对象,而后调用其中的compute()函数”。

九、Sustitute Algorithm(替换算法)

你想要把某个算法替换为另一个更清晰的算法。

将函数本体替换为另一个算法。

String foundPerson(String[] people){

For(int i =0;i<people.length;i++){

If(people[i].equals("Don")){

Return "Don";

}

If(people[i].equals("Json")){

Return "Json";

}

If(people[i].equals("Kent")){

Return "Kent";

}

}

Return "";

}

转换后:

String foundPerson(String[] people){

List candidates = Arrays.asList(new String[] {"Don","Json","Kent"});

For(int i = 0 ;i<people.length;i++){

If(condidates.contains(people[i])){

Return people[i];

}

}

}

动机

如果你发现做一件事可以有更清晰的方式,就应该以较清晰的方式取代复杂的方式。

做法

1、准备好另一个(替换用)算法,让它通过编译。

2、针对现有测试,执行上述新算法。如果结果和原本结果相同,重构结束。

3、如果测试结果不同于原先,在测试和调试过程中,以就算法为比较参照标准。

注:对于每一个测试用例,分别以新旧两种算法执行,并观察两者结果是否相同。这可以帮助你看到哪一个测试用例出现麻烦,以及出现了怎样的麻烦。

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



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

相关文章

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu