路漫漫其修远兮,吾将上下而求索——小酌重构系列[0]开篇有益

相信博客园的读者大多都是千万“码农”中的一员,每个人都写过很多代码,但并不是每一个人都能写出高质量的代码。
rome is not built in one day !——完成高质量的代码也不是一蹴而就的。为了写出高质量的代码,我们需要借助一些手段,“代码重构”基本上是最常用的手段,甚至是唯一的手段。

重构需要你花一些心思去琢磨自己的代码,这好比自己种的花花草草,看你怎么对待它们。你不给它们浇水、除虫、晒太阳,它们可能会长虫、生病。如果你用心地去对待它们,它们可能会枝繁叶茂,花开茂盛。但是,即使你已经很专心地去打理它们了,它们也不一定是“健康的”,毕竟每一种花草都有自己的习性,代码也是如此。

为何要重构?

做一件事情之前,我们都应该先反问自己Why。

我也问过自己:为什么要对代码进行重构?项目一个接一个地做,我哪有什么时间去重构代码,我还要控制团队的项目成本!
Oh, Shit!为了让代码看起来更好一些,我们花了一些时间在代码重构上,项目的成本又超了!向公司领导汇报时,又要编造合适的理由了!

我们不应该仅仅实现可执行的系统功能,更应该提供高质量的代码,提升系统的设计以让其适应更多的变化,如果超出的成本是在可以接受的范围内,它将符合我们“将来的利益”。

持续利益的提升

何谓“将来的利益”?如果代码的质量较为可靠,则会为以后的维护、升级奠定良好的基础。倘若已完成的代码质量不高、不够整洁,在系统维护、升级时,不说花在代码修改上的时间,仅阅读理解代码就将花去你大量的时间。如果你需要对项目持续地维护、升级,这该是多么长久的一个痛苦啊!到这里,你能理解了吧,这些”低质量代码“产生的将来成本将远超于你现在重构的成本。正所谓“长痛不如短痛”,要自宫就赶紧的,这样才能早点练成“葵花宝典”。

2B地说,重构是为了将来不要掉进自己挖的坑里。
普通地说,重构是为了提高代码的可读性和可维护性。
文艺地说,重构是为了让代码的身姿妖娆美如画。

设计的提升

没有完美的产品,也没有完美的设计,设计的最终目的是为用户创造价值。

大多数系统或产品的设计是伴随着需求持续演变的,设计调整时,重构又是必备的利器。重构的过程,是对设计过程的整理,也是对设计细节的推敲。设计既然是不完美的,那么在重构的思考过程中我们总是能发现一些设计上的瑕疵。发现了瑕疵,我们就可以通过重构加以改善。小到对字段、方法的重构,大到对工程结构、系统架构的重构,都是设计的改变。
这个过程可能让你痛苦,可能让你快乐。

何时才重构?

假如你是生活在大山里的樵夫,为了维持每天的生计,你觉得什么时间上山砍柴最合适?
是早晨、午后、傍晚、还是晚上?我觉得在早晨和午后较为合适,早晨是最佳时机。
为什么呢?早晨是人精神最饱满的时候,也是时间最充分的时候,你可以预先做一些准备,比如:花些时间计划砍柴的工作量、磨好斧子、准备好捆柴的工具。
如果你选择午后,你将没有时间磨斧子,会影响砍柴的效率。
如果你选择傍晚,砍完柴了天都已经黑了,你是准备住山上吗?夜间山里面有各种野生动物,你是想心惊胆战地过一夜吗?
如果你选择晚上,能不能正常上山都是个问题,你别迷路在山间,后半夜的时间都花去早出路了。

讲这个例子,并不是为了体现做什么事情都一定要趁早,而是为了说明无论做什么事情,选择合适的时机非常重要。当然趁早做一些事情,也能更早发现问题。

重构亦是如此。重构是一把利器,选择合适的时机重构或许会让我们的收益超出预期。

下面几项是我觉得可能需要重构的时机:

  1. 代码中存在着重复的代码
  2. 代码中存在过大的类或过长的方法
  3. 代码中存在强依赖、紧耦合的结构
  4. 代码的运算逻辑难以理解
  5. 代码不能清晰地描述现实对象的特征、行为以及对象间的关系

当然,每个人对重构、对系统、对业务、对用户的理解是不同的,所以每个人选择重构的时机也尽不相同。你大可不必参考这几项,结合周围的环境选择合适自己的(这本身也是一个时机选择)就好。即使出现这几种情形,重构也不一定是必须的,这取决于你们的项目经验、你们心中的准则,也取决于你们看待产品、看待项目的方式。

重构的策略

代码重构有很多策略,我将基于《31 Days Refactoring》和《Clean Code》这两本书,以及OOP(面向对象编程)的概念介绍一些常用的重构策略。当然,我不是将书中的内容搬到这里,我会尽可能地加入自己的理解。

下面列出了我将要讲的重构系列的主题,它们基本都来源于《31 Days Refactoring》。是的,这本书只有50多页,你懂点英文,这本书你花1个小时或许就看完了。重构的代码大家都能读懂,我不想徒有其“表”,我想更深层次地理解其“意”,不仅于自己,也于读到这一系列文章的人。

方法、字段重构

  1. 移动方法 (2016-04-24)
  2. 提取方法、提取方法对象 (2016-04-26)
  3. 方法、字段的提升和降低 (2016-05-01)
  4. 分解方法 (2016-05-02)
  5. 为布尔方法命名 (2016-05-03)
  6. 引入对象参数 (2016-05-04)

类、接口重构

  1. 使用委派代替继承 (2016-05-07)
  2. 提取接口 (2016-05-08)
  3. 解除依赖 (2016-05-09)
  4. 分离职责 (2016-05-11)
  5. 提取基类、提取子类、合并子类 (2016-05-12)  
  6. 去除上帝类 (2016-05-14)
  7. 去除中间类
  8. 使用多态代替条件判断

设计模式重构

  1. 策略模式代替Switch
  2. 引入契约式设计
  3. 提取工厂类

一般性重构

  1. 重命名
  2. 分解复杂判断
  3. 用条件判断代替异常
  4. 避免双重否定
  5. 尽快返回
  6. 封装条件
  7. 封装集合

你们也看到了,列举的这些重构策略都是一些基本技巧,即使学会这些技巧也不能让你马上成为“重构”大师,我自身也不是什么代码高手。

重构的双刃剑

事物总是存在两面性的,重构亦是如此。重构是一把双刃剑,用得好则能卸磨杀驴,用不好则伤己伤人。
并不是每一次重构,都能然让你的收益大于支出。重构可能会产生新的bug,加重项目的开发负担,甚至让项目版本回滚(这些事情我都已经碰过瓷儿了)。在设计层面,不当地重构可能会破坏原有的设计,甚至破坏系统现有的功能。

正所谓“不破不立”,你不去用剑,不和剑交流,不被剑伤,你永远无法成为一名好剑客。

后话

最后,我想引用屈原的一句名言:“路漫漫其修远兮,吾将上下而求索”。

我无法让你们在看完这一系列文章后,就能“深度”领会重构的“意”了,这仍然需要你自己去琢磨代码层面的一些事儿,也许是一个方法,也许是项目的架构。

另外,我个人是不推荐“1天学会xxx”、“3天掌握xxx”、”8天弄懂xxx“的。你读完了文章,不代表你真的理解了。你需要自己去思考,自己去实践。1天也好,3天也罢,若你肯花时间专心地去领会一件事情,并坚持不懈地为之努力,你迟早是懂的。他人讲得天花乱坠,你听过看过之后,也不过是过眼云烟。

读到这一系列文章的读者,如果有不同的见解,或者察觉文章中的描述有误,欢迎来讨论或指正。通过这一系列文章,我希望读者会有所收益,也希望自己对重构能有一个更深的理解。如果您觉得文章对您有用,请不要吝啬您的“推荐”;但如果您觉得它一无是处,请您不要客气地点击“反对”,您的反对也是给予我的一种磨砺,它会让我持续学习和改进。

“多么痛的领悟~,维护曾是你的全部~~。愿你挣脱烂代码的枷锁,各种坑的束缚,别再为项目受苦~~~”。结尾献给各位一首歌,祝大家周末愉快!

posted @ 2016-04-23 08:10  keepfool  阅读(9219)  评论(23编辑  收藏  举报