附录 A 坏味道与手法对照表
第 2 章讲了 24 种坏味道。这张表把每种坏味道和对付它的手法对应起来,手法后面的数字是章号。闻到一种味道时,从左往右看:先看排在前面的手法,它们最常用。
| 坏味道 | 一句话 | 常用手法 |
|---|---|---|
| 神秘命名 | 名字没说清楚是什么 | 改变函数声明 6、变量改名 7、字段改名 31 |
| 重复代码 | 同样的逻辑写了两遍 | 提炼函数 4、移动语句 25、函数上移 51、合并条件表达式 36、函数参数化 43、提炼超类 54 |
| 过长函数 | 靠注释分段的函数 | 提炼函数 4、以查询取代临时变量 16、分解条件表达式 35、以卫语句取代嵌套条件表达式 37、以命令取代函数 49 |
| 过长参数列表 | 调用处要数位置 | 引入参数对象 9、保持对象完整 45、以查询取代参数 46、移除标记参数 44、函数组合成类 10 |
| 全局数据 | 谁都能改的变量 | 封装变量 8、以参数取代查询 46 |
| 可变数据 | 值在悄悄变化 | 封装变量 8、拆分变量 30、将查询函数和修改函数分离 42、以查询取代派生变量 32、将引用对象改为值对象 33、移除设值函数 47 |
| 发散式变化 | 一个类因多种原因被改 | 拆分阶段 11、搬移函数 21、提炼类 17 |
| 霰弹式修改 | 一个改动碰很多处 | 搬移函数 21、搬移字段 22、函数组合成类 10、函数组合成变换 10、内联函数 4、内联类 17 |
| 依恋情结 | 函数用别人的数据比自己的多 | 搬移函数 21、提炼函数 4 |
| 数据泥团 | 总是一起出现的几个值 | 引入参数对象 9、提炼类 17、保持对象完整 45 |
| 基本类型偏执 | 用字符串、数字存带规则的值 | 以对象取代基本类型 15、以子类取代类型码 52、以多态取代条件表达式 38 |
| 重复的 switch | 同一个分支出现在多处 | 以多态取代条件表达式 38、以子类取代类型码 52 |
| 循环 | 在做筛选和转换的循环 | 以管道取代循环 27、拆分循环 26 |
| 冗赘的元素 | 没有分量的类或函数 | 内联函数 4、内联类 17、折叠继承体系 55、移除子类 53 |
| 夸夸其谈通用性 | 为将来准备的、没人用的东西 | 折叠继承体系 55、内联函数 4、内联类 17、改变函数声明 6、移除死代码 28 |
| 临时字段 | 只在某段时间有效的字段 | 提炼类 17、搬移函数 21、引入特例 39 |
| 过长的消息链 | 调用方写着 a.b.c.d | 隐藏委托关系 18、提炼函数 4、搬移函数 21 |
| 中间人 | 全是转发的类 | 移除中间人 18、内联函数 4、以委托取代超类 56 |
| 内幕交易 | 两个类互摸私有数据 | 搬移函数 21、搬移字段 22、隐藏委托关系 18、以委托取代子类 56 |
| 过大的类 | 字段靠前缀分组 | 提炼类 17、提炼超类 54、以子类取代类型码 52、以委托取代子类 56 |
| 异曲同工的类 | 做同样的事但接口不同 | 改变函数声明 6、搬移函数 21、提炼超类 54 |
| 纯数据类 | 只有字段没有行为 | 封装记录 13、移除设值函数 47、搬移函数 21、提炼函数 4 |
| 被拒绝的遗赠 | 子类不想要父类的东西 | 函数下移 51、字段下移 51、以委托取代子类 56、以委托取代超类 56 |
| 注释 | 解释“在干什么”的注释 | 提炼函数 4、改变函数声明 6、引入断言 40 |
反过来查:一个手法治哪些味道
Section titled “反过来查:一个手法治哪些味道”有时你已经想到了一个手法,想确认它在解决什么问题。下面列出治的味道最多的几个手法,它们也是最值得先练熟的。
| 手法 | 章 | 主要对付的坏味道 |
|---|---|---|
| 提炼函数 | 4 | 过长函数、重复代码、依恋情结、过长的消息链、注释、纯数据类 |
| 搬移函数 | 21 | 依恋情结、霰弹式修改、发散式变化、内幕交易、临时字段、异曲同工的类 |
| 提炼类 | 17 | 过大的类、数据泥团、发散式变化、临时字段 |
| 内联函数、内联类 | 4、17 | 冗赘的元素、夸夸其谈通用性、中间人、霰弹式修改 |
| 改变函数声明 | 6 | 神秘命名、异曲同工的类、夸夸其谈通用性 |
| 以多态取代条件表达式 | 38 | 重复的 switch、基本类型偏执 |
| 封装变量 | 8 | 全局数据、可变数据 |
| 引入参数对象 | 9 | 过长参数列表、数据泥团 |