摘抄《重构-改善既有代码的设计》

什么是重构(Refactoring)?

所谓重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。重构是一种有纪律的、经过训练的、有条不紊的程序整理方法,可以将整理过程中不小心引人错误的几率降到最低。本质上说,重构就是“在代码写好之后改进它的设计”。

Code refactoring is the process of changing a computer program's source code without modifying its external functional behavior in order to improve some of the nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity to improve the maintainability of the source code, as well as a more expressive internal architecture or object model to improve extensibility.

重构定义:

  • 重构(名词):对软件内部结构的一种调整,目的是在不改变“软件之可察行为”前提下,提高其可理解性,降低其修改成本。
  • 重构(动词):使用一系列重构法则(手法),在不改变“软件之可察行为”前提下,调整其结构。

为何重构?

  • 改进软件设计
  • 使软件容易被理解
  • 助你找到臭虫(Bugs)
  • 助你提供编程速度

你会发现所谓设计不再是一切动作的前提,而是在整个开发过程中逐渐浮现出来。

GoF (Design Paterns):“设计模式为重构提供了目标”。

Fred Brooks:“应对并处理变化,是软件开发的根本复杂性之一”。

为什么重构有用(Why Refactoring Works)?

  • 程序有两面价值:”今天可以为你做什么“和“明天可以为你做什么”。大多数时候,我们只关注前者。

  • 我们无法完全预期明天的需求。如果我纯粹只为今天工作,明天我将完全无法工作。重构是一条摆脱束缚的道路。

  • 程序难以相与的原因包括:

    • 难以阅读的程序,难以修改。
    • 逻辑重复(Duplicated logic)的程序,难以修改。
    • 添加新行为时需要修改既有代码者,难以修改。
    • 带复杂条件逻辑(complex conditional logic)的代码,难以修改。

    同时我们希望程序:

    • 容易阅读。
    • 所有逻辑都只在唯一地点指定。
    • 新的改动不会危机现有行为。
    • 尽可能简单表达条件逻辑。
  • 每一个软件模块都具有三项职责。第一个是它运行起来所完成的功能。第二个是它要应对变化。第三是要和阅读它的人进行沟通。

  • 重构是这样一个过程:它在一个目前可运行的程序上进行,企图在“不改变程序行为”的情况下赋予上述美好性质,使我们能够继续保持告诉开发,从而增加程序的价值。

何时重构?

  • 如果你发现自己需要为程序添加一个特性,而代码结构是你无法很方便的那么做,那就先重构那个程序,是特性的添加比较容易进行,然后再添加特性。
  • 重构之前,首先检查自己是否有一套可靠的测试机制。这些测试必须有自我检验(self-checking)能力。
  • 不要专门拨出时间重构,重构应该随时随地进行。你不应该为重构而重构,你之所以重构,是因为你想做别的什么事,而重构可以帮助你把那些事做好。
  • 三次法则(The Rule of Three):事不过三,三则重构(Three strikes and you refactor)。第一次做某件事时只管去做,第二次做类似的事会产生反感,但无论如何还是做了,第三次再做类似的事,你就应该重构。
  • 添加功能时一并重构。
  • 修补错误是一并重构。
  • 复审代码(Code review)时一并重构。

何时不该重构?

  • 代码根本无法工作或者太糟糕,重构还不如重写来的简单。
  • 在项目的最后期限,应该避免重构。

间接层和重构(Indirection and Refactoring)

  • Computer Science is the discipline that believes all problems can be solved with one more layer of indirection. — Dennis DeBruler

    计算机科学是这用一门科学:它相信所有问题都可以通过多一个间接层来解决。 — Dennis DeBruler

  • 由于软件工程师对间接层如此醉心,你应该不会惊讶大多数重构都为程序引人了更多间接层。重构往往把大型对象拆成数个小型对象,把大型函数拆成数个小型函数。

  • 间接层是一把双刃剑,每次把一个东西分成两份,你就需要多管理一个东西。

  • 间接层的价值包括:

    • 允许逻辑共享(To enable sharing of logic)。
    • 分开解释“意图”和“实现”(To explain intention and implementation separately)。
    • 将变化加以隔离(To isolate change)。
    • 将条件逻辑加以编码(To encode conditional logic)。
  • “事后抽象出中间层”与“小心翼翼的事前设计”的比较:

    • 后者很容易出错。
    • 使用前者时发生全盘错误的危险更小。
  • 找出不值得的中间层,并将其拿掉,亦是重构的一部分。

修改接口(Changing interfaces)

  • 如果某个函数的所有调用动作都在你的控制之下,那么即使修改函数名也不会有任何问题。
  • 只有当需要修改的接口系那些被“找不到,即使找到也不能修改”的代码使用时,接口的修改才会成为问题。公开接口(public interface) vs 已发布接口(published interface)。
  • 对于已发布接口,你必须同时维护新旧两个接口,直到你的所有用户都有时间对这个变化做出反应。应该尽量让旧接口调用新接口。千万不要拷贝函数实现代码,你将会陷入“重复代码(duplicated code)”的泥潭中难以自拔。你还应该将旧接口标记为“deprecated”。
  • 不要过早发布接口。请修改你的代码拥有权政策,使重构更顺畅。

构筑测试体系

  • 确保所有测试都完全自动化,让他们检查自己的测试结果。
  • 一整组(a suite of)测试就是一个强大的“臭虫”侦测机,能够大大缩减查找“臭虫”所需要的时间。
  • 频繁地运行测试。每次编译请把测试也考虑进去,一天至少执行每个测试一次。
  • 每次获得臭虫捉报(bug report),请先撰写一个单元测试来揭发这个臭虫。
  • 编写未臻完善的测试并实际运行,好过对完美测试的无尽期待。
  • 考虑可能出错的边界条件,把测试的火力集中在那儿。
  • 当事情被大家认为应该会出错时,别忘了检查彼时是否有异常如预期般的被抛出。
  • 不要因为“测试无法捕捉所有臭虫”,就不撰写测试代码,因为测试的确可以捕捉的大多数臭虫。

代码的坏味道(Bad Smells in Code)

  • 重复的代码(Duplicated Code)
  • 过长函数(Long Method)
  • 过大类(Large Class)
  • 过长参数列(Long Parameter List)
  • 发散式变化(Divergent Change) - 一个class受多种变化的影响。
  • 散弹式修改(Shotgun Surgery) - 一种变化引发多个class相应修改。
  • 依恋情节(Feature Envy)
  • 数据泥团(Data Clumps)
  • 基本型别偏执(Primitive Obsession)
  • Switch惊愫现身(Switch Statements)
  • 平行继承体系(Parallel Inheritance Hierarchies)
  • 冗赘类(Lazy Class)
  • 夸夸其谈的未来性(Speculative Generality)
  • 令人迷惑的暂时值域(Temporary Field)
  • 过度耦合的消息链(Message Chains)
  • 中间转手人(Middle Man)
  • 狎昵关系(Inappropriate Intimacy)
  • 异曲同工的类(Alternative Classes with Different Interfaces)
  • 不完美的程序库类(Incomplete Library Class)
  • 纯稚的数据类(Data Class)
  • 被拒绝的遗赠(Refused Bequest)
  • 过多的注释(Comments)

其他重构要点

  • 重构技术系以微小的步伐修改程序。如果你犯下错误,很容易便可发现它。
  • 任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类能够理解的代码,才是优秀的程序员。
    • 改变变量名称以使程序清晰是绝对值得的行为,可以大胆去做。
  • 当你感觉需要撰写注释,请先尝试重构,试着让所有注释都变得多余。
  • 重构与设计彼此互补。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值