首页 > 其他分享 >《重构:改善既有代码的设计》读书笔记二

《重构:改善既有代码的设计》读书笔记二

时间:2023-12-20 22:55:17浏览次数:27  
标签:重构 函数 读书笔记 代码 提炼 修改 Extract Method

二、代码的坏味道

1、Duplicated Code(重复代码)

坏味道首当其冲的就是Duplicated Code,如果你在一个以上的地点看到相同的重复结构,那么这个坏味道就可以确定了,设法将它们合而为一

  • 同一个类中两个或更多的函数含有相同的表达式

    利用Extract Method(提炼方法)提炼重复代码,然后引用新提炼的函数

  • 互为兄弟的子类含有相同的表达式

    利用Extract Method(提炼方法)提炼重复代码,然后Pull Up Method(函数上移)堆到超类

  • 互为兄弟的子类,含有部分相同的表达式

    一般常见相似的两个函数以相同的顺序执行大致的操作,但是各操作不完全一样

    利用Extract Method(提炼方法)提炼重复代码,可能发现是可以运用Form Template Method(塑造模板函数)

  • 有些函数以不用的算法做相同的事

    使用Substitute Algorithm(替换算法)将其他函数替换掉

  • 两个互不相关的类出现Duplicated Code

    利用Extract Class(提炼类) 将重复代码提炼到一个独立的类中,然后引用新类。

2、Long Method(过长的函数)

很久以前程序员就已经认识到程序越长越难理解,在早期编程语言,调用子程序需要额外开销,所以不愿意使用小函数。现在OO语言几乎已经完全免除了进程内的调用动作开销

函数命名原则:每当感觉需要注释说明点什么的时候,就可以把需要说明的东西写进一个独立函数中,并以其"用途"命名,哪怕函数名比实现还要长,关键是要说明用途(而非实现手法)

  • 无局部变量

    利用Extract Method(提炼函数)提炼函数即可

  • 有局部变量

    如果发现局部变量是保存某一个表达式的运算结果,那么用Replace Temp with Query(以查询取代临时变量)使结构清晰后,再Extract Method(提炼函数),如果提炼了函数后发现新函数对参数赋值了,应用Remove Assignments to Parameters(移除对参数的赋值)

3、Large Class(过大的类)

如果想用单个类做太多事情,其内往往就出现了太多实例变量,一旦如此,duplicate code也就要出现了。当发现一个类中,并非所有时刻都使用所有实例变量,或者某个类中出现多个变量有着相同前缀或结尾,构的动机就出现了

  • 如果一个类中用于很多相似的字段,而且方法又都只是和某几个字段有关系,那么可以考虑这些字段是不是应该属于另一个类Extract Class(提炼类)
  • 如果你发现类中的某些行为只被一部分实例用到,其它没有用到,可以尝试Extract SubClass(提炼子类)或者Extract Class(提炼类),这两种的抉择就是委托和继承之间的抉择,Extract SubClass(提炼子类)通常更容易,但它也有限制:一旦对象创建完成,你无法再改变对象行为。而委托更灵活一些(策略模式)。

4、Long Paramenter List(过长参数列)

太长的参数列难以理解,太多的参数会造成前后不一致,不易使用,而且一旦你需要更多的数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为你很可能只需要在函数内增加一两条请求,就能得到更多数据

  • 如果向已有的对象发出一条请求,就可以取代一个参数,那么你应该激活手法 Replace Parameter with Method(以函数取代参数)。在这里"已有对象"可能是函数所属类内的一个字段也可能是另一个参数。
  • 你也可以运用 Preserve Whole Object(保持对象完整) 将来自同一个对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可使用Introduce Parameter Object 为它们制造出一个参数对象
  • 这里有一个重要的例外:有时候你明显不希望造成"被调用对象"与"较大对象"间的某种依赖关系。这时候将参数句从对象中拆解出来单独作为参数,也很合情合理。但是请注意其所引发的代码。如果参数列太长或变化太频繁,你就需要重新考虑自己的依赖结构了。

5、Divergent Change(发散式变化)

如果某个类经常因为不同的原因在不同方向上发生变化,发散式变化就出现了

  • 使用Extract Class(提炼类)把变化的职责提炼到新的类

你看着一个类说:"呃,如果新加入一个数据库,我必须修改这三个函数;如果新出现一种工具,我必须修改这四个函数。"那么此时也许将这个类分成两个会更好,这么一来每个类就可以只因为一种变化而需要修改。当然,往往只有在加入新数据库或者新金融工具后,你才能发现这一点。针对某一个外界变化的所有响应修改,都只应该发生在单一类中,而这个新类内的所有内容都应该发硬此变化。为此,你应该找出某特定原因而造成的所有变化,然后运用Extract Class(提炼类) 将他们提炼到另一个类中。

6、Shotgun Surgery(霰弹式修改)

如果每遇到某种变化,你都必须在许多不同的类作出小修改,你所面临的坏味道就是Shotgun Surgery,你如果需要修改代码有很多处,你不但很难找到它们,也很容易忘记某个重要的修改。

  • 这种情况下你应该使用 Move Method (搬移函数)和 Move Field (搬移字段)把所有需要修改的代码放进同一个类。如果眼下没有合适的类,就创造一个。如果将代码移动到同一个类,使原始类几乎为空,请尝试通过Inline Class摆脱这些现在多余的类。

发散式变化(Divergent Change) 是指"一个类受多种变化的影响",霰弹式修改(Shotgun Surgery)是指"一种变化引入引发多个类的修改"。这两种情况下,你都会希望整理代码,使"外界变化"与"需要修改的类"趋于一一对应

标签:重构,函数,读书笔记,代码,提炼,修改,Extract,Method
From: https://www.cnblogs.com/wrf1/p/17917825.html

相关文章

  • 代码随想录算法训练营第八天 | 344.反转字符串,541.反转字符串II,卡码网:54.替换数字,151.
    一、344.反转字符串题目链接:LeetCode344.反转字符串学习前:思路:相向指针。left=0,right=length-1,不停交换left和right的值时间复杂度:O(n)空间复杂度:O(1)学习后:了解swap函数通过位运算实现的方式二、541.反转字符串II题目链接:LeetCode541.反转字符串II学习前:思路:ne......
  • 【代码块】-结构体序列化与反序列化
    整理代码块代码块整理后存储,供后期使用结构体序列化与反序列化usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Text;namespacestructTest{///<summary>///结构体序列化///</summary>publicclassstructSerializable{......
  • 【代码块】-winform 获取控件属性和事件、自定义控件的自定义方法
    整理代码块代码块整理后存储,供后期使用C#获取属性,获取事件逻辑Controlcontrol=Controls.Find("button1",true)[0];//获取属性objecto=control.GetType().GetProperty("PropertyName").GetValue(control,null);//获取事件System.Reflection.EventInfoev=contr......
  • 【代码块】-计算机蜂鸣
    整理代码块代码块整理后存储,供后期使用计算机蜂鸣classProgram{staticvoidMain(string[]args){while(true){Console.WriteLine("pleasepressnum\"1\"or\"2\"");intnum=Convert.ToInt32(Console.ReadLine());......
  • 阅读笔记:《代码大全》阅读笔记十一
    当谈到软件开发的艺术和科学时,SteveMcConnell的《代码大全》是无可争议的经典之作。它是一本旨在为软件工程师和程序员提供深入洞察的指南,旨在帮助他们提升编程技能、编写高质量代码以及有效管理整个软件开发周期。这本书不仅提供了广泛的理论知识,还结合了大量实用的案例和建议,下......
  • VSCode下载.NET出错以及没有代码提示的解决办法
    Failedtodownload.NET7.0.14~x64:.NETinstallationtimedout.Youmayneedtochangethetimeouttimeifyouhaveaslowconnectionvscode安装Unity插件后提示下载.NET出错 解决办法是下载它提示的SDK手动安装,比如提示7.0.14,那么就去下载对应的SDK 安装之......
  • python代码实现保存微博文娱榜的数据Ajax异步加载
    最近有小伙伴看完蜜蜂之前分享的爬虫文章之后,使用python代码实现了自动保存网站上面的图片到本地,但是最近又有新的需求。需求描述:爬取微博文娱榜的数据,并保存到csv文件中网址:https://weibo.com/hot/entertainment需要将一下框上的两个字段都爬取下来。对于这样的需求,看过蜜蜂之前......
  • JS压缩谁最强?对比5款JS代码压缩工具
    JS压缩谁最强?对比5款JS代码压缩工具JS压缩,似乎是很简单的一个事情,通常在线就可以完成。但不同网站或工具提供的JS压缩,效果差异不小。本文,测试国内外5个JS在线压缩工具,看看谁的效果最好。测试用JS代码(注:这段代码来下面要测试的JShaman网站,以压缩这段代码为例,看不同的工具压缩后......
  • Mysql以及TCP socket的C++代码
    在使用socket编写tcp的C++程序时,遇到了一个问题:那就bind冲突了,分析原因:是因为std中有bind函数,而socket中也有,但是没有报重复定义的错误,这就有一点难办了。百度了一下:发现只要使用::bind就可以调用socket的bind。下面把这个套接字socket的server端代码贴出来:staticvoid*serv......
  • SpringBoot代码混淆与反混淆加密工具详解
    ​ SpringBoot代码混淆与反混淆加密工具详解简单就是把代码跑一哈,然后我们的代码.java文件就被编译成了.class文件   ​反编译就是针对编译生成的jar/war包里面的.class文件逆向还原回来,可以看到你的代码写的啥。比较常用的反编译工具JD-GUI,直接把编译......