我是靠谱客的博主 欣慰星星,最近开发中收集的这篇文章主要介绍重构-改善既有代码的设计 读书心得(二),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

    • 第七章
    • 第八章 重新组织数据
    • 第九章
    • 第十章 简化函数调用

第七章

  1. 在对象之间搬移特性
    在这里插入图片描述
    如果一个类有太多行为,或者与另一个类有太多合作形成高度耦合,就可以搬移函数。如果被搬移函数只引用了原类的一个字段,那么只需将这个字段作为参数传递过来,如果调用了原类的函数,那么必须将源对象传递过来。如果需要很多原类特性,那就要进一步重构,比如分解目标函数,把其中一部分移回原类。
  2. move field
    对于一个字段,如果另一个类有更多函数使用了它,就可以考虑move。如果是public的字段,考虑先封装起来。本书写的有点早,现代java ide早就有成熟的move field refactor工具了。可以先利用ide迁移过来,再考虑是否要做封装。
  3. 提炼类
    在这里插入图片描述
    实际工作中,类会不断成长扩展,一开始可能只有一种功能,慢慢地随着责任不断增加,类会变得过分复杂,此时你需要考虑哪些部分可以分离出去,形成一个单独的类。某些数据和函数总是一起出现,那么它们就应该分离出去。还有一个extract class的信号:如果你发现子类化只影响类的部分特性,或者某些特性需要以另一种方式来子类化,这就意味着你需要分解原来的类。
    有一个需要考虑的事情是是否公开新类,这个需要具体情况具体分析。
  4. inline class
    在这里插入图片描述
    如果一个类不再承担足够责任,挑选这一萎缩类的最频繁用户,以inline class手法将萎缩类塞进另一个类中。
  5. 隐藏委托关系 hide delegate
    如果client先通过服务对象的字段得到另一个对象,然后调用后者的函数,那么客户就必须知晓这一层委托关系。万一委托关系变化,client也得相应变化。可以在服务对象上放置一个委托函数,将委托关系隐藏起来。这样即使委托关系发生变化,变化也被限制在服务对象中,不会波及客户。
    在这里插入图片描述
  6. 移除中间人 remove middle man
    跟上一条是相反的,如果频繁使用上一条,会导致委托函数越来越多,服务类完全变成了一个中间人,此时你就应该让client直接调用受托类。
    这两条规则怎么使用取决于系统需要的隐藏的程度。不过重构的好处是你不必现在就做决定,你可以在系统运行过程中不断进行调整。随着系统的变化,合适的隐藏程度这个尺度也相应改变。重构的意义:你永远不必说对不起,只要把出问题的地方修补好就行了。
  7. 引入外加函数
    你正在使用一个第三方类,它很好用,但你又需要一个新服务,但这个类无法提供,而且你不能修改类的源码,所以你不得不在客户端编码。如果你在多处需要这段代码,就应该抽成一个函数来调用,避免重复代码。
  8. 引入本地扩展 Introduce Local Extension
    上一条的加强版,如果引入了很多外加函数,就新建一个类来包括这些函数,可以用子类和包装类的方法来做。

第八章 重新组织数据

  1. 对象取代数据值
    比如一开始你用一个String来表示customer,但系统后来又增加了客户地址,信用等级等信息,String明显不够用了,你需要构造一个Customer类来表示一个customer。
  2. 值对象改为引用对象
    引用对象:每个对象对应真实世界中的一个事物,比如客户对象,账户对象。值对象:对象是否相同完全由值来定义,比如日期,钱。值对象有很多个副本存在是没有意义的浪费。有时候我们会在多个地方引用值对象,我们希望对这个对象的修改能影响到所有引用它的地方,这个时候我们需要把值对象变成引用对象。解决方案:提前创建好引用对象或动态对象,用工厂方法返回这些对象。
  3. 引用对象改为值对象
    引用对象有时又需要转换成值对象。值对象有个非常重要的特性:不可变。这在并发系统中特别好用。比如Money对象有币种和金额两个Field,那么Money对象通常是不可变的。但并不是说你的薪资不能改变,而是在你改变薪资的时候,需要用另一个Money对象来取代现有的Money对象。解决方案:先确保是不可变对象,然后去掉工厂方法,开放构造函数,重写equals和hashcode方法
  4. 以对象取代数组
    人们很难记住“数组的第一个元素是人名”这样的约定。如果你用对象就不一样,你可以运用字段名和函数名来传达这样的信息。
  5. 以字面常量取代魔法数
    魔法数:拥有特殊含义,却不能明确表现出这种意义的数字。比如重力常量,π等。这些数字发生改变,就必须在程序中找到所有魔法数修改,非常麻烦。
    解决方案:声明一个常量来表示魔法数。
  6. 封装集合
    不返回集合本身,可以返回一个集合的复制给client。可以提供集合的增删方法,但不要提供set集合的方法。
  7. 以数据类取代记录
    你可能面对一个遗留的用非面向对象语言写的程序,或者从数据库读出的记录,它们都是记录型结构(struct),这时候你有必要创建一个数据类,对于记录中的每个数据,在类中都有一个对应的field。
  8. 以类取代类型码
    现在java中有更好的解决方案,用Enum。
  9. 以State/Strategy取代类型码
    通过例子来看更直观些:
    在这里插入图片描述在这里插入图片描述
    新建一个抽象类,把ENGINEER,MANAGER,SALESMAN变成抽象类的子类:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    再把switch语句移到它应该呆的类中:
    在这里插入图片描述在这里插入图片描述
  10. 以字段取代子类
    如果子类只是用来返回常量数据,那就可以消除它,避免继承带来的额外复杂性。
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

第九章

  1. 分解条件表达式
    复杂的条件逻辑是最常导致复杂度上升的原因之一。你必须编写代码检查不同的条件分支、根据不同的分支做不同的事情,然后你就会得到一个大函数。而且条件逻辑代码会使代码更难阅读。你可以将它分解为多个独立函数,为新函数命名,更清楚地表达自己的意图。
    在这里插入图片描述
  2. 合并条件表达式
    在这里插入图片描述
  3. 合并重复的条件片段
    在这里插入图片描述
  4. 以卫语句取代嵌套条件表达式
    条件表达式有两种形式,一种是所有分支都是正常行为,第二种是只有一种是正常行为,其他都是不常见的情况。对于第一种,应该用if else的条件表达式,对于第二种,如果某个条件极其罕见,就应该单独检查该条件,并在条件为真时立刻从函数中返回。这样的单独检查被称为卫语句(guard clauses)
    在这里插入图片描述在这里插入图片描述
  5. 以多态取代条件表达式
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  6. 引入Null对象
    反复地判断一个对象是否为null是非常繁琐的。我们可以引入一个空对象,它不会破坏系统的逻辑,对空对象的所有请求都和真实对象一样。但这并非总是好事,有时会造成查找问题比较困难。空对象一定是常量,我们可以用单例模式来构造它。空对象需要有一个能被识别出是空对象的方法,比如isNull(),如果client需要空对象作出不同的响应,就可以调用isNull().
  7. 引入断言
    断言不是用来检查“你认为应该为真”的条件,它是用来检查“一定必须为真”的条件的。

第十章 简化函数调用

  1. rename method
    本书作者特别提倡将复杂的处理过程分解成小函数,但要明确小函数的用途关键就是给函数起一个好名字。函数命名有个好方法,首先考虑应该给这个函数写上一句怎样的注释,然后想办法将注释变成函数名称。
  2. 添加参数
    使用这项重构的动机很简单:你必须修改一个函数,修改后的函数需要 一些过去没有的信息,所以你需要添加参数。但谨慎选择这项优化,因为这会增加参数列的长度,长参数往往伴随着坏味道。
  3. 删除参数
    当一个参数不再需要的时候,删除它。
  4. 查询和修改分离
    一个用来查询的方法,要确保它不会有修改的操作。
  5. 令函数携带参数
    你可能会发现有两个函数:它们功能类似,只是因为少数几个值导致行为略有不同,那你可以把那几个值用参数来表示,把两个函数合并成一个。
    在这里插入图片描述
  6. 以明确函数取代参数
    跟上面的优化相反。如果某个参数有多种可能的值,函数内又用条件表达式检查这些值,根据不同的值做出不同的行为,那么就应该用本项重构。
    在这里插入图片描述
  7. Preserve whole object(保持对象完整)
    有时你会从某个对象中取出若干值,将它们作为某次函数调用时的参数。此时可以考虑把对象传给函数,这样万一将来增减函数参数时只需要在函数内部改就行了。但这会造成对象的依赖,所以需要权衡利弊。更进一步,如果一个函数用了某个对象的很多值,应该考虑把这个函数放到该对象所属的类。
    在这里插入图片描述
  8. Replace Parameter with Methods(以函数取代参数)
    如果函数可以通过其他途径获得参数值,那么就不应该通过参数取得该值。过长的参数列会增加理解难度。缩减参数的办法之一就是:看看接收端是否可以通过与调用端相同的计算来取得参数值,如果可以,那么就应该将这个计算过程转移到接收端内,从而去除该项参数。如果接收端有参数发送端对象的引用,那么可以直接通过引用获得参数的值,从而去掉参数列表里的参数。如果接收端没有发送端对象的引用,那就需要你自己权衡,加入一个对象的引用是否值得。
  9. 引入参数对象
    你常会看到特定的一组参数总是一起被传递。我们可以用一个对象包装所有这些数据,再用该对象取代它们。本项重构的价值跟上面的优化类似,都是为了缩短参数列。还有一个潜在的好处是:当你把这些参数组织到一起后,往往会发现一些可被移至新建类的行为。调用函数一般会对这一组参数有一些共通的处理,如果把这些共通行为移到新对象中,可以减少很多重复代码。
    在这里插入图片描述在这里插入图片描述
    将一些行为挪到新的类:
    在这里插入图片描述
  10. Replace Error Code with Exception(异常取代错误码)
    在这里插入图片描述
  11. replace exception with test
    异常不应该被滥用。它只应该被用于异常的、罕见的行为,不应该成为条件检查的替代品。
    在这里插入图片描述

最后

以上就是欣慰星星为你收集整理的重构-改善既有代码的设计 读书心得(二)的全部内容,希望文章能够帮你解决重构-改善既有代码的设计 读书心得(二)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部