改善代码设计 —— 总结篇(Summary)
系列博客
1. 改善代码设计 —— 优化函数的构成(Composing Methods)
2. 改善代码设计 —— 优化物件之间的特性(Moving Features Between Objects)
3. 改善代码设计 —— 组织好你的数据(Composing Data)
4. 改善代码设计 —— 简化条件表达式(Simplifying Conditional Expressions)
5. 改善代码设计 —— 简化函数调用(Making Method Calls Simpler)
6. 改善代码设计 —— 处理概括关系(Dealing with Generalization)
找出需要重构的地方
最明显可能需要重构的地方包括: 注释, 长的方法, 长的类, 长的参数列表. 这些都是很快能看出来的.
注释 (Comments)
1. 函数中有处注释在说明下面的一个代码块在做什么事情, 通常采用 Extract Method 将这些代码放到一个单独的方法中.
2. 如果某个函数上面的注释在解释这个函数是做什么用的, 多数情况下是这个方法名的名字取得不是很好, 通常使用 Rename Method 进行重命名.
3. 如果注释在解释代码运行到这边需要满足的条件, 考虑使用 Introduce Assertion.
另外, 我觉得过分的追求代码中没有注释也是不对的, 注释需要恰到好处.
长的方法 (Long Method)
1. 寻找代码中的注释, 使用 Extract Method 将函数分成一小块一小块的方法.
2. 观察代码中有没有太多重复的代码, 使用 Extract Method 把这些代码分离出去, 在原来的代码中调用这些小方法.
长的类 (Long Class)
造成类的代码过长的原因可能有以下两点:
1. 随着时间的推移, 类中在不停的增加新的功能. 可以使用 Extract Class, Extract Subclass, Extract Interface 解决这个问题.
2. 类中有很多涉及界面的代码, 比如更新某个控件. 可以使用 Duplicate Observed Data 来帮助提取一个用于更新界面的类, 也就是所谓的 "界面与业务分离", 不过负责更新界面的这个类要写好更新的同步机制.
长的参数列表 (Long Parameter List)
1. 如果参数能通过某个函数直接获得, 应该去除该参数项, 使用 Replace Parameter with Method, 在函数中直接调用.
2. 如果某个物件能够提供函数中所需的所有参数, 则可以将整个物件作为参数传递给函数, Preserve Whole Object.
3. 如果有好几个函数都包含某几个参数, 这几个参数很有可能就是所谓的数据泥团 (Data Clumps), 如果合理, 尝试使用 Introduce Parameter Object, 将数据泥团封装到一个物件中, 让函数直接调用这个物件.
重构, 各抒己见
一提到重构, 不少人有一肚子的口水要喷. 一部分人心怀激动的感概重构所带来的诸多好处, 一少些人愤懑它所带来的不属于自己的利益, 甚至是某次不恰当的重构所带来的毁灭性结果. 还有很多人在讨论某项重构究竟值不值得去做 (这往往应该根据不同情况具体分析后做出不同的选择).
对于重构, 就好比你想用积木搭一个建筑物, 重构就像是把一块木头削成一个个小积木的过程, 而如何去搭建, 大部分是设计模式所要解决的问题. 重构所能带来的好处大多数的共识是: 重构后代码能够更让别人读懂和理解, 能发现代码隐藏的缺陷, 帮助改善软件设计, 新需求来临时能提高编程效率。
记得我第一个独立完成的程序是一个课程表软件 (左图), 用 VB.NET 写的, 花了三天功夫写了 2000 多行, 当时一共写了近 10 个界面用于包括设置一个星期中每天的课程还有其它一些杂七杂八的内容. 当时我也知道 "重复" 的代码很多, 但只想着 "能运行就好了", 于是还光明正大的把一大块代码复制到另外几个模板里. 如果想对这样的代码做点优化的话, 这时不应该是重构, 而应该重写. 后来我也不用这么笨拙的工具来存储课程表了, 直接用 HTML+CSS 写一个网页.
不应该先乱七八糟的写完一堆代码之后再思考怎么去改善, 应该在写得过程中不断的尝试着对现有的代码作出一些优化, 最起码别出现太让人费解的变量名和方法名.
重构是一项需要不少时间的工作, 如果系统即将到了发布的 deadline, 这时并不适合大范围的重构.
很多人觉得用不到重构, 他们觉得重构得不恰当会导致原本好歹能运行的系统工作不正常. 或者重构需要他们大把大把的精力和脑细胞, 而重构带来的利益很可能不属于他. 还有一些人不太喜欢频繁的函数调用, 认为重构会降低一些系统性能等等原因. 但不要因为不会使用到重构, 而不去学习它, 更不用去抨击重构带来实际好处 (往往因为你没体会到).
参考
这几篇都是我看书并联想自己写过的代码的总结, 废话较少, 特别感谢不少细心的园友帮我纠正一些错误, 还提出了一些很有价值的建议.
参考 《重构 —— 改善既有代码设计》, 《重构手册》 , 还有自己的一些理解和经验.