重构:改善既有代码的设计 第三章 读书笔记

目录 代码的坏味道

3.1 神秘命名(Mysterious Name)

  需要好的命名方式,有意义的命名方式

3.2 重复代码(Duplicated Code)

场景 方法
同一个类中出现重复代码 提取重复代码到一个函数中
重复代码在一个超类的不同子类中 函数上移 到 父类中
重复代码出现在无关的类中 把重复代码抽取到额外的一个类中
重复代码只是相似而不是完全相同 移动语句:把重复的代码合并在一起,然后再抽取

 

 

 3.3 过长函数(Long Function)

1- 抽取函数;

2- 减少临时变量:使用查询取代临时变量;

3- 减少参数个数;

4- 如果参数个数太多;

采用参数对象(固定的几个参数同时出现,又称“数据泥团”,提取成一个类)

保持对象完整进行简化(使用原有对象,而不是传输对象中的成员);

3.4 过长参数列表(Long Parameter List)

1- 查询取代参数;
2- 保持对象完整,直接传入原有的数据结构;
3- "数据泥团"参数包装成对象;
4- 如果某个参数被用作区分函数行为的标记;使用移除标记参数;

3.5 全局数据(Global Data)

  手段:封装变量。

    把全局数据用一个函数包装起来,至少你 就能看见修改它的地方,并开始控制对它的访问。 

  随后,最好将这个函数(及其 封装的数据)搬移到一个类或模块中,只允许模块内的代码使用它,从而尽量控 制其作用域。 

3.6 可变数据(Mutable Data),这个内容比较多,需要好好消化

  缺点:类似于全局数据;

  手段:1- 封装变量; 可以很好的看见修改它的地方

    2- 如果一个变量在不同时候被用于存储不同的东西, 可以使用拆分变量将其拆分为各自不同用途的变量

    3- 移动变量,将没有副作用的代码与执行数据更新操作的代码分开

    4- 使用将查询函数和修改函数分离

    5- 查询取代派生变量

3.7 发散式变化(Divergent Change)

  定义:如果某个模块经常因为不同的原因在不同的方向上发生变化,发散式变化就 出现了。

  方法:

  1- 两个模块有先后次序拆分将两者分开;两个模块之间通过一个清晰的数据结构进行沟通

  2- 两个模块之间来回调用:创建适当的模块,然后用搬移函数把处理逻辑分开;

  3- 函数内部混合了两类处理逻辑应该先用提炼函数(106)将其分开,然后再做 搬移。

  4- 如果模块是以类的形式定义的,就可以用提炼类来做拆分。

3.8 霰弹式修改(Shotgun Surgery)

  表现:必须在许多不同的类内做出很多小修改

  方法: 1- 搬移函数和搬移字段,把所有需要修 改的代码放进同一个模块里。

  2- 如果有很多函数都在操作相似的数据,可以使用函数组合成类;

      3- 面对霰弹式修改,一个常用的策略就是使用与内联(inline)相关的重构—— 如内联函数或是内联类——把本不该分散的逻辑拽回一处。

3.9 依恋情结(Feature Envy)

  表现:个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于在自己所处模块内部的交流,这就是依恋情结的典型情况。

  方法:提取函数 + 搬迁函数
3.10 数据泥团(Data Clumps)

  定义:总是绑在一起出现的数据

  方法:提炼到一个独立对象中
3.11 基本类型偏执(Primitive Obsession)

  表现:用基本类型代替复杂的数据结构;

  方法:用对象取代基本类型。
3.12 重复的switch (Repeated Switches)

  方法:使用多台进行代替
3.13 循环语句(Loops)

  方法:使用管道方式取代循环
3.14 冗赘的元素(Lazy Element)
3.15 夸夸其谈通用性(Speculative Generality)

  过分抽取,不必要的代码逻辑,去掉多余代码;
3.16 临时字段(Temporary Field)
3.17 过长的消息链(Message Chains)

  表现:一个类调用另外一个类,类再调类,类再调类;

  方法原话:这时候应该使用隐藏委托关系(189)。你可以在消息链的不同位置采用这 种重构手法。理论上,你可以重构消息链上的所有对象,但这么做就会把所有中 间对象都变成“中间人”。通常更好的选择是:先观察消息链最终得到的对象是用 来干什么的,看看能否以提炼函数(106)把使用该对象的代码提炼到一个独立 的函数中,再运用搬移函数(198)把这个函数推入消息链。如果还有许多客户 端代码需要访问链上的其他对象,同样添加一个函数来完成此事。

3.18 中间人(Middle Man)
3.19 内幕交易(Insider Trading)

  表现:模块之间有大量的交流;此时不应该在模块之间建起高墙;

  方法:1- 搬移函数和搬移字段,减少私下交流;

    2- 如果有共同的部分,可以尝试创建一个新的模块,公共数据放在一个管理良好的地方;

                 或者隐藏委托关系,把一个模块编程两者的中介;
3.20 过大的类(Large Class)
3.21 异曲同工的类(Alternative Classes with Different Interfaces)

3.22 纯数据类(Data Class)

  进行封装处理
3.23 被拒绝的遗赠(Refused Bequest)

  表现:主要出现在集成抽象类 或 实现接口的时候出现;一些类并不需要实现其中的方法
3.24 注释(Comments)

posted @ 2022-11-25 10:45  上海小墨子  阅读(51)  评论(0编辑  收藏  举报