重构 - 代码整洁之道

做者简介 新茗 蚂蚁金服·数据体验技术团队前端

前言

以前也介绍过咱们团队的前端项目从零开始经历8个月迭代业务代码10万行(仅为产品长期规划需求的20%),至今仍然在不断迭代的过程。git

团队成员除了设计好的架构来管理这种复杂度极高的前端应用,还开始补充设计模式以及重构方面的知识,目的是为了让项目代码在不断迭代的过程当中优化项目代码,保持代码的新鲜度,鲁棒性,可维护性… 让后续加入的团队新人也能够快速加入咱们的产品开发中程序员

PS: 无论对于何种语言,重构都是软件开发过程当中不可或缺的一部分。若是已经了解重构的基础,能够直接跳往至文章后面的重构案例部分。github

重构背景

“若是尿布臭了,就换掉它”。设计模式

  • 随着业务需求的不断加入,代码随着时间的推移变得愈来愈糟。
  • 这其中可能包括如下坏味道(仅列举):
    • 重复的代码
    • 过长的函数
      • 遵循一条原则: 每当感受须要注释来讲明什么的时候,能够尝试将须要说明的东西写进一个函数中
    • 冗赘类
      • 当子类没有作足够的工做的时候,或者说在可见的预期内,不会有新的状况出现,考虑将类内联化。
    • 过长的类
      • 这种状况容易出现冗余代码。好比若是类内出现了多个变量带有相同的前缀或者后缀,这意味着你能够考虑把他们提炼到某个组件内,或者考虑这个组件是否能够成为子类,使用提炼类的手法来重构。

什么是重构

咱们回过头来看一下"什么是重构"架构

  • 不改变软件可观察行为的前提下,改善其内部结构函数

  • 以提升理解性和下降修改为本工具

    摘自《重构 - 改善既有代码的设计》(下面简称《重构》)
    复制代码

什么时候重构?

咱们须要明确的一点是: 重构不是一件应该特意拨出一段时间来作的事情。重构不是目的,可是重构能够帮助你把事情作好。学习

事不过三,三则重构开发工具

  1. 重复性工做,既有的代码没法帮助你轻松添加新特性时
  2. 修补bug时,排查逻辑困难
  3. code review 可让他人来复审代码检查是否具有可读性,可理解性
  4. 太多的代码无注释,已然连本身都没法快速理清代码逻辑

重构的衡量指标

  • 数量: 代码的行数
  • 质量: 代码复杂度,耦合度,可读性,架构依赖复杂度等
  • 成本: 花费的时间
  • 回报(成果): 支持后续功能的快速叠加,解决现有因代码设计问题没法优化的矛盾等

抓重点 抓重点啦

说了这么多废话,其实你们都明白没有与实践结合的理论都是空虚的。

可是 重构设计模式同样,也是须要一个"学习——领悟——突破"的过程。第一步的学习让你了解基本的重构手法,第二步的实践勾起你对重构手法的回忆以及重温应用,第三步的应用以及实践经验激发你的思考,领悟以及总结,以至于灵活运用。

但凡是人,老是在不断学习,不断温习,以达到具体场景具体应用,灵活自如。 重构是一个很大的话题,《重构》做者本人也是经历了N多的项目,以及多年的经验才总结出来的重构技巧。

重构技巧

《重构》一书做者总结的重构手法实在是太多了,只能经过图片来展现一下全部做者总结的重构列表。
具体的补充,你们能够看看《重构》一书。

重构的实践

做者推荐的一种作法:

  1. 随机挑选一个目标 先给本身选择一个目标(譬如“去掉一堆没必要要的子类”),而后朝着目标前进,每一步走得小而坚决
  2. 没把握就停下来 当你没法证实本身所作的一切可以保证原有程序的逻辑和语义时,请你停下来思考:既有的重构是改善了仍是毫无成果须要撤销。
  3. 保证每次重构后的测试都能正常跑通

做为开发者, 应当把重构做为开发的一部分,一边开发一边重构。在快速堆叠代码,实现基本需求功能的基础上,写好测试用例,保证功能不变,逐步重构。
这也是咱们团队要求每一个人都掌握重构这门必备技能的缘由。优秀的程序员应当尽可能避免低质量的代码。

重构案例

故事场景

  1. 有三种类型的电影,顾客能够进行租赁
  2. 租赁规则
    1. 价格计算规则:
      普通片儿 —— 起步价2¥,超过2天的部分天天每部电影收费1.3元
      新片儿 —— 天天每部3元
      儿童片 —— 起步价2¥,超过3天的部分天天每部电影收费0.8元
    2. 积分计算规则:
      每借一部电影积分加1,新片每部加2

原始代码

程序结果:(请保证重构后结果不变~)

  • 类图

有兴趣的能够先看看原始代码,考虑一下其中的原始对象关系,再行考虑如何重构代码。 原始代码实际上是有不少问题能够挖掘的,下面是咱们的讨论整理:

  • 划分职责关系,遵循单一职责原则
    • statement打印帐单函数承担了不少功能,包括收费计算,积分计算以及结果展现等等
      • 解法1: 6.1 Extract Method(提炼函数) —— 最经常使用的重构手法
      • 解法2: 9.1 Decompose Conditional(分解条件表达式)
    • 用户类中承担了不属于它的职责,包括:收费规则、积分规则。这些职责应该是属于电影类型的。
  • 整理清楚其中的业务逻辑,好比收费规则和积分规则 - 见故事场景
  • 不要直接访问对象的数据。容易发生其余对象改变该对象的数据,而拥有该数据的对象却一无所知。
    • 解法:8.10 Encapsulate Field(封装字段手法) —— 使数据和行为想分离
  • 重构不该该被外界所感知,保证testcases依然可行

部分重构

这里为了更好的展现重构的手法,使用TS,根据上面的讨论进行了部分重构,重构的方式实际上是根据业务将来的扩展方向而定,并无最优解,有兴趣的能够加入咱们,抛出你的看法~

  • 重构后的类图关系

基本技巧

  • 小步前进,频繁测试(保证足够的测试来支持你的重构行动)
  • 使用智能开发工具(好比VSCode右键能够将过长的函数代码拆解函数化)

推荐书籍

重构实际上是一件须要长期投入,而且投入产出比很高的事情。对重构感兴趣的同窗能够关注专栏或者发送简历至'tao.qit####alibaba-inc.com'.replace('####', '@'),欢迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

相关文章
相关标签/搜索