重构第二版的变更
重构第一版和第二版之间变更的简要概述
2018年9月5日
从最广义的角度来说,第二版的结构遵循第一版的结构。这并不奇怪,因为第一版非常成功,我可能也会继续使用有效的方法。
第一版以四个叙事章节开头,这些章节也出现在第二版中。所有这些都遵循原书的广泛形式。
开头的示例改变了其领域,因为现在没有多少人熟悉视频商店。重构的流程基本相同:分解成函数,将计算与格式化分离,使用多态性按类型组织计算。
原则和代码坏味道章节都进行了彻底的修改。其中很多内容保留了下来,也很多内容发生了变化。我估计大约四分之三的内容发生了变化,但这只是直觉,而不是基于现实的测量。测试章节必须完全重写,特别是由于从 Java 到 JavaScript 的更改。
在这些介绍性章节之后,我继续介绍目录,我一直认为它是本书的核心。我将在稍后详细介绍目录的变更,但一个值得注意的结构变更是我将一些重构放在一起,构成一个初始章节,其中包含我认为首先学习的一组好的重构。
我删除了后面的章节,这些章节探讨了一些更切题的问题。我认为它们在第一版中有效,但现在我认为最好在我的网站上发布这样的文章。这也是我从目录中删除四个“大型重构”的原因。大型重构一直与大多数重构略有不同,我确实觉得这些示例在我的网站上通过文章展示效果更好。
目录变更
那么目录发生了什么变化呢?以下表格显示了原始 68 个重构的命运。 [1]
名称 | 页码 | 命运 | 替换 |
---|---|---|---|
添加参数 | 275 | 已替换 | ➜ 更改函数声明 |
将双向关联更改为单向关联 | 200 | 缺失 | |
将引用更改为值 | 183 | 保留 | |
将单向关联更改为双向关联 | 197 | 缺失 | |
将值更改为引用 | 179 | 保留 | |
折叠层次结构 | 344 | 保留 | |
合并条件表达式 | 240 | 保留 | |
合并重复的条件片段 | 243 | 已替换 | ➜ 滑动语句 |
分解条件 | 238 | 保留 | |
复制观察到的数据 | 189 | 缺失 | |
封装集合 | 208 | 保留 | |
封装向下转型 | 308 | 缺失 | |
封装字段 | 206 | 已替换 | ➜ 封装变量 |
提取类 | 149 | 保留 | |
提取接口 | 341 | 缺失 | |
提取方法 | 110 | 已替换 | ➜ 提取函数 |
提取子类 | 330 | 已替换 | ➜ 使用子类替换类型码 |
提取超类 | 336 | 保留 | |
提取变量 | 124 | 保留 | |
形成模板方法 | 345 | 缺失 | |
隐藏委托 | 157 | 保留 | |
隐藏方法 | 303 | 缺失 | |
内联类 | 154 | 保留 | |
内联方法 | 117 | 已替换 | ➜ 内联函数 |
内联临时变量 | 119 | 已替换 | ➜ 内联变量 |
引入断言 | 267 | 保留 | |
引入外部方法 | 162 | 缺失 | |
引入本地扩展 | 164 | 缺失 | |
引入空对象 | 260 | 已替换 | ➜ 引入特殊情况 |
引入参数对象 | 295 | 保留 | |
移动字段 | 146 | 保留 | |
移动方法 | 142 | 已替换 | ➜ 移动函数 |
参数化方法 | 283 | 已替换 | ➜ 参数化函数 |
保留整个对象 | 288 | 保留 | |
向上移动构造函数主体 | 325 | 保留 | |
向上移动字段 | 320 | 保留 | |
向上移动方法 | 322 | 保留 | |
向下移动字段 | 329 | 保留 | |
向下移动方法 | 328 | 保留 | |
删除对参数的赋值 | 131 | 已替换 | ➜ 拆分变量 |
删除控制标志 | 245 | 已替换† | ➜ 使用 break 替换控制标志 |
删除中间人 | 160 | 保留 | |
删除参数 | 277 | 已替换 | ➜ 更改函数声明 |
删除设置方法 | 300 | 保留 | |
重命名方法 | 273 | 已替换 | ➜ 更改函数声明 |
将数组替换为对象 | 186 | 缺失 | |
将条件替换为多态性 | 255 | 保留 | |
将构造函数替换为工厂方法 | 304 | 已替换 | ➜ 将构造函数替换为工厂函数 |
将数据值替换为对象 | 175 | 已替换 | ➜ 将基本类型替换为对象 |
将委托替换为继承 | 355 | 缺失 | |
将错误代码替换为异常 | 310 | 保留† | |
将异常替换为测试 | 315 | 已替换† | ➜ 将异常替换为预检查 |
将继承替换为委托 | 352 | 已替换 | ➜ 将超类替换为委托 |
将幻数替换为符号常量 | 204 | 已替换† | ➜ 替换幻数字面量 |
将方法替换为方法对象 | 135 | 已替换 | ➜ 将函数替换为命令 |
将嵌套条件替换为保护子句 | 250 | 保留 | |
将参数替换为显式方法 | 285 | 已替换 | ➜ 删除标志参数 |
将参数替换为方法 | 292 | 已替换 | ➜ 将参数替换为查询 |
将记录替换为数据类 | 217 | 已替换 | ➜ 封装记录 |
将子类替换为字段 | 232 | 已替换 | ➜ 删除子类 |
将临时变量替换为查询 | 120 | 保留 | |
将类型码替换为类 | 218 | 已替换 | ➜ 将基本类型替换为对象 |
将类型码替换为状态/策略 | 227 | 已替换 | ➜ 使用子类替换类型码 |
将类型码替换为子类 | 223 | 保留 | |
自我封装字段 | 171 | 已替换 | ➜ 封装变量 |
将查询与修改器分离 | 279 | 保留 | |
拆分临时变量 | 128 | 已替换 | ➜ 拆分变量 |
替换算法 | 139 | 保留 |
† 仅限网络版
标记为保留的重构在第二版中以相同的名称存在。标记为缺失的重构不在新版中。我从新版中删除重构的原因有很多,我可能会扩展这篇文章,在将来讨论其中的一些原因。标记为已替换的重构在新版中以不同的名称存在。其中一些只是重命名,例如,我将“拆分临时变量”更改为“拆分变量”。大多数是轻微的泛化,例如,将“提取方法”更改为“提取函数”。许多这些泛化反映了重写中面向对象程度较低。在某些情况下,第一版中的几个重构被合并:例如,添加参数、删除参数和重命名方法都被“更改函数声明”替换。与我删除的重构一样,我可能会在将来扩展这篇文章,讨论一些具体案例。 [2]
新版包含 15 个完全全新的重构,它们不是现有重构的泛化或重命名。它们是
将函数合并到类中 |
将函数合并到转换中 |
将语句移动到函数中 |
将语句移动到调用者中 |
删除死代码 |
重命名字段 |
重命名变量 |
将命令替换为函数 |
将派生变量替换为查询 |
将内联代码替换为函数调用 |
将循环替换为管道 |
将查询替换为参数 |
将子类替换为委托 |
返回修改后的值 |
拆分阶段 |
我意识到,仅凭名称并不能说明这些新重构的作用,或者泛化后的重构与第一版中的重构有何不同。我会及时更新 在线目录,以提供更多相关信息。
脚注
1: 68 不包括原书中的四个“大型重构”。正如我之前提到的,我认为这类主题最好以文章的形式在网上发布。
2: 我是否这样做取决于读者是否对此感兴趣,以及我如何将此事优先于未来几个月我想写的其他内容。