你的位置:首页 > ASP.net教程

[ASP.net教程]路漫漫其修远兮,吾将上下而求索——小酌重构系列[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. 移动方法
    2. 提取方法、提取方法对象
    3. 封装条件
    4. 封装集合
    5. 方法、字段的提升和降低
    6. 分解方法
    7. 用条件判断代替异常
    8. 为布尔方法命名

类、接口重构

    1. 使用委派代替继承
    2. 提取接口
    3. 解除依赖
    4. 分离职责
    5. 提取基类
    6. 提取子类
    7. 合并子类
    8. 去除上帝类
    9. 去除中间类
    10. 使用多态代替条件判断

设计模式重构

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

一般性重构

    1. 重命名
    2. 分解复杂判断
    3. 引入对象参数
    4. 用条件判断代替异常
    5. 避免双重否定
    6. 尽快返回

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

重构的双刃剑

事物总是存在两面性的,重构亦是如此。重构是一把双刃剑,用得好则能卸磨杀驴,用不好则伤己伤人。

并不是每一次重构,都能然让你的收益大于支出。重构可能会产生新的bug,加重项目的开发负担,甚至让项目版本回滚(这些事情我都已经碰过瓷儿了)。在设计层面,不当地重构可能会破坏原有的设计,甚至破坏系统现有的功能。

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

后话

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

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

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

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

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