Refactoring
- 重构是
在不改变软件可观察行为的前提下改善其内部结构。
案例 #
- 变量名称是代码清晰的关键。
- 最好不要在另一个对象的属性基础上运用 switch 语句。
重构原则 #
- 消除重复代码,确定所有事物和行为在代码中只表述一次。
何时重构 #
三次法则 #
- 事不过三,三则重构。
添加功能时重构 #
- 代码的设计无法帮助我轻松添加我所需要的特性。
修补错误时重构 #
复审代码时重构 #
重构的难题 #
- 数据库
- 修改接口
- 不要过早发布接口,请修改你的代码所有权政策,使重构更顺畅。
- 难以通过重构手法完成的设计改动
- 何时不该重构
代码的坏味道 #
Duplicated Code(重复代码) #
-
Method
- Extract Method (110)
- Pull Up Method (332)
- Form Template Method (345)
- Substitute Algorithm (139)
- Extract Class (149)
Long Method (过长函数) #
-
Method
- Extract Method (110)
- Replace Temp with Query (120)
- Introduce Parameter Object (295)
- Preserve Whole Object (135)
- Decompose Condition (238)
Long Class (过长的类) #
-
Method
- Extract Class (149)
- Extract Subclass (330)
- Extract Interface (341)
- Duplicate Observed Data (189)
Long Parameter List (过长参数列) #
-
Method
- Replace Parameter with Method (292)
- Preserve Whole Object (288)
- Introduce Parameter Object (295)
Divergent Change (发散式变化) #
-
一个类受多种变化的影响。
-
针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个新类内的所有内容都应该反应此变化。
-
Method
- Extract Class (149)
Shotgun Surgery (霰弹式修改) #
-
一个变化引起多个类相应的修改。
-
Method
- Move Method (142)
- Move Field (146)
- Inline Class (154)
Feature Envy(依恋情结) #
-
函数对某个类的兴趣高过对自己所处类的兴趣。
-
一个函数会用到几个类的功能:判断哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起。
-
Method
- Move Method (142)
- Extract Method (110)
Data Clumps (数据泥团) #
-
不必在意 Data Clumps 只用上新对象的一部分字段。
-
Method
- Extract Class (149)
- Introduce Parameter Object (295)
- Preserve Whole Object (288)
Primitive Obsession (基本类型偏执) #
-
Method
- Replace Data Value with Object (175)
- Replace Type Code with Class (218)
- Replace Type Code with Subclasses (223)
- Replace Type Code with State/Strategy (227)
Switch Statements (switch 惊悚现身) #
-
Switch 语句的问题在于重复
-
Method
- Extract Method (110)
- Move Method (142)
- Replace Type Code with Subclasses (223)
- Replace Type Code with State/Strategy (227)
- Replace Conditional with Polymorphism (255)
- Replace Parameter with Explicit Methods (285)
- Introduce Null Object (260)
Parallel Inheritance Hierarchies (平行继承体系) #
-
让一个继承体系的实例引用另一个继承体系的实例
-
Method
- Move Method (142)
- Move Field (146)
Lazy Class (冗赘类) #
-
Method
- Collapse Hierarchy (344)
- Inline Class (154)
Speculative Generality (夸夸其谈未来性) #
-
如果函数和类的唯一用户是测试用例。
-
Method
- Collapse Hierarchy (344)
- Inline Class (154)
- Remove Parameter (277)
- Rename Method (273)
Temporary Field (令人迷惑的暂时字段) #
-
Method
- Extract Class (149)
- Introduce Null Object (260)
Message Chains (过度耦合的消息链) #
-
客户代码将与查找过程中的导航结构紧密结合。
-
Method
- Hide Delegate (157)
- Extract Method (110)
- Move Method (142)
Middle Man (中间人) #
-
过度使用委托。
-
Method
- Remove Middle Method (160)
- Inline Method (117)
- Replace Delegation with Inheritance (355)
Inappropriate Intimacy (狎xia昵ni关系) #
-
两个类过于亲密
-
Method
- Move Method (142)
- Change Bidirectional Association to Unidirectional (200)
- Extract Class (149)
- Hide Delegate (157)
- Replace Inheritance with Delegation (352)
Alternative Classes with Different Interfaces (异曲同工的类) #
-
如果两个函数做同一件事,却有着不用的签名。
-
Method
- Rename Method (273)
- Move Method (142)
- Extract Superclass (336)
Incomplete Library Class (不完美的库类) #
-
Method
- Introduce Foreign Method (162)
- Introduce Local Extension (164)
Data Class (纯稚的数据类) #
-
不会说话的数据容器
-
Method
- Encapsulate Field (206)
- Encapsulate Collection (208)
- Remove Setting Method (300)
- Move Method (142)
- Extract Method (110)
- Hide Method (303)
Refused Bequest (被拒绝的馈赠) #
-
Method
- Push Down Method (208)
- Push Down Field (329)
- Replace Inheritance with Delegation (352)
Comments (过多的注释) #
-
当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余。
-
Method
- Extract Method (110)
- Rename Method (273)
- Introduce Assertion (267)
构筑测试体系 #
- 频繁运行测试
- 编写测试代码时,往往一开始先让它们失败
- 每当收到 bug 报告时,请写一个单元测试来暴露这个 bug
- 测试你最担心出错的部分
- 考虑可能出错的边界条件 (包括特殊的,可能导致测试失败的情况)
- 当事情被认为应该会出错时,别忘了检查是否抛出了预期的异常
重构列表 #
重构记录的格式 #
- 名称 (name)
- 概要 (summary)
- 动机 (motivation)
- 做法 (mechanics)
- 范例 (examples)
重构手法有多成熟 #
- 小步前进,频繁测试
- 设计模式为重构行为提供了目标
重新组织函数 #
-
Extract Method (提炼函数)
- 局部变量
-
Inline Method (内联函数)
-
Inline Temp (内联临时变量)
-
Replace Temp with Query (以查询取代临时变量)
- Previous: jQuery
- Next: My Subscribe Telegram Channel