24种坏味道以及重构手法
| 序号 | 坏味道 | 理解 | 重构手法 |
|---|---|---|---|
| 1 | 神秘命名 | 神秘命名坏味道多了,花在猜谜上的时间会越来越多 | 命名是编程中最难的几件事之一,没有确切的教程,做到见名知意就好了 |
| 2 | 重复代码 | 阅读重复代码时,需要加倍仔细,修改时需要找到所有副本来修改 | 抽离成公共函数,以功能命名 |
| 3 | 过长函数 | 函数过长,难以理解,且高耦合,不利于拆解重组 | 代码行数不要超过一个屏幕,一个函数代码低于 80 行 |
| 4 | 过长参数列表 | 每次调用都需要去看函数的实现 | 1. 把标记参数移除,取而代之的是几个语义更加清晰的函数 2. 重新组织参数,使数据项之间的关系更加明晰(可以用类的属性来存数据,方法来操作数据) |
| 5 | 全局数据 | 全局的数据避免直接修改,没有机制探测出是哪发生了修改 | 封装访问和修改全局数据的函数,访问时进行浅拷贝 |
| 6 | 可变数据 | 对函数参数修改会导致出乎意料的结果和难以发现的 bug | 浅拷贝一份数据 |
| 7 | 发散式变化 | 函数内部有会变化数据或方法,都需要修改这个函数 | 将会发生变化的每个子模块封装成一个函数,当他们改变时,只需要修改子模块的函数 |
| 8 | 散弹式修改 | 这个和重复代码有点像,重复代码经常引起散弹式修改。当需要修改的代码散布四处,很难找到他们,挨个修改 | 把散布的数据封装到一个类里面,相关的逻辑放到一起管理 |
| 9 | 依恋情节 | 两个模块(如:类)的数据交流(访问)格外频繁,远超模块内部 | 搬移功能,将数据交流紧密的部分放到一个模块中 |
| 10 | 数据泥团 | 类里面把存储了太多数据,有些数据只会一起出现 | 这种数据应该定义他们自己的对象 |
| 11 | 基本类型偏执 | 类里面一个数据太多的操作逻辑 | 将这个数据以及操作单独封装一个类 |
| 12 | 重复的 switch | 想要增加一个分支时,需要更新所有的 switch,复杂的条件逻辑是最难理解的东西之一 | 使用工厂函数创建实例方法,子类继承父类,子类重写父类的条件逻辑函数,修改和增添特性都变得简单了 |
| 13 | 循环语句 | 尽量不要使用循环,需要花费时间来理清楚逻辑 | 推荐使用 JS 管道函数,逻辑更清晰 |
| 14 | 冗赘的元素 | 在重构过程中会出现很多新的结构,没有什么帮助 | 删除这些新结构,还原到原来的函数里面去 |
| 15 | 夸夸其谈通用性 | 代码存在冗余 | 去掉多余的类,封装到一个类中 |
| 16 | 临时字段 | 代码重复,影响核心逻辑的代码可读性 | 移除重复判断,把临时字段收拢到一个地方,进行统一管理 |
| 17 | 过长的消息链 | 一长串取值函数,一长串临时变量 | 提炼函数,将一长串取值放到函数里去 |
| 18 | 中间人 | 只转发函数,没有自己的功能的就是中间人 | 去掉中间人,直接调用目标函数 |
| 19 | 内幕交易 | 将访问其他模块数据的过程隐藏,虽然增加了耦合,但是无可避免 | 在内部读取其他模块,然后返回 |
| 20 | 过大的类 | 过大的类可能包含基本类型偏执、重复的 switch、中间人等 | 采用重构手法,多次提炼后可以避免过大的类 |
| 21 | 异曲同工的类 | 两个类里面有相同的东西 | 提取超类来避免两个类里面有相同的东西 |
| 22 | 纯数据类 | 纯数据类没有存在的意义,直接读取对象就可以了 | 可以将行为搬移的纯数据类里面,这个纯数据类就有存在的意义了 |
| 23 | 被拒绝的遗赠 | 超类的字段只有一个或少数子类有关 | 将其从超类中挪走,放到真正关心它的子类中去 |
| 24 | 注释 | 注释常常被用作“除臭剂” | 可以尝试重构,让注释变得多余 |
上次更新: 2023/12/16, 09:22:46