代码整洁之道(重构)

前言

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

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

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

重构背景

“如果尿布臭了,就换掉它”。

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

什么是重构

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

  • 不改变软件可观察行为的前提下,改善其内部结构
  • 以提高理解性和降低修改成本

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

何时重构?

我们需要明确的一点是: 重构不是一件应该特地拨出一段时间来做的事情。重构不是目的,但是重构可以帮助你把事情做好。

事不过三,三则重构

  • 重复性工作,既有的代码无法帮助你轻松添加新特性时
  • 修补bug时,排查逻辑困难
  • code review 可以让他人来复审代码检查是否具备可读性,可理解性
  • 太多的代码无注释,已然连自己都无法快速理清代码逻辑

重构的衡量指标

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

抓重点 抓重点啦

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

但是 重构和 设计模式一样,也是需要一个"学习——领悟——突破"的过程。第一步的学习让你了解基本的重构手法,第二步的实践勾起你对重构手法的回忆以及重温应用,第三步的应用以及实践经验激发你的思考,领悟以及总结,以致于灵活运用。
但凡是人,总是在不断学习,不断温习,以达到具体场景具体应用,灵活自如。

重构是一个很大的话题,《重构》作者本人也是经历了N多的项目,以及多年的经验才总结出来的重构技巧。

重构技巧

《重构》一书作者总结的重构手法实在是太多了,只能通过图片来展示一下所有作者总结的重构列表。
具体的补充,大家可以看看《重构》一书。

重构的实践

作者推荐的一种做法:

  • 随机挑选一个目标 先给自己选择一个目标(譬如“去掉一堆不必要的子类”),然后朝着目标前进,每一步走得小而坚定
  • 没把握就停下来 当你无法证明自己所做的一切能够保证原有程序的逻辑和语义时,请你停下来思考:既有的重构是改善了还是毫无成果需要撤销。
  • 保证每次重构后的测试都能正常跑通

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

重构案例

故事场景

有三种类型的电影,顾客可以进行租赁

租赁规则

价格计算规则:

普通片儿 —— 起步价2¥,超过2天的部分每天每部电影收费1.3元
新片儿    —— 每天每部3元
儿童片    —— 起步价2¥,超过3天的部分每天每部电影收费0.8元

积分计算规则:

每借一部电影积分加1,新片每部加2

原始代码

CODEPEN

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

类图

有兴趣的可以先看看原始代码,考虑一下其中的原始对象关系,再行考虑如何重构代码。原始代码其实是有很多问题可以挖掘的,下面是我们的讨论整理:

  • 划分职责关系,遵循单一职责原则

    • statement打印账单函数承担了很多功能,包括收费计算,积分计算以及结果展示等等

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

部分重构

这里为了更好的展示重构的手法,使用TS,根据上面的讨论进行了部分重构,重构的方式其实是根据业务未来的扩展方向而定,并没有最优解,有兴趣的可以加入我们,抛出你的见解~

CODEPEN执行结果:

重构后的类图关系

基本技巧

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

推荐书籍

《代码整洁之道》
《重构 - 改善既有代码的设计》
《修改代码的艺术》
《代码大全》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈JavaScript 代码整洁之道

    概述 一张幽默的图片:软件质量通过你在阅读代码的时候有多少报怨来进行评估 Robert C. Martin 在 <代码整洁之道> 中提到的软件工程原则,同样适用于 JavaScript.这不是一个风格参考.它指导如何用 JavaScript 编写可读.可复用.可重构的软件. 并不是每一个原则都必须严格遵循,甚至很少得到大家的认同.它们仅用于参考,不过要知道这些原则都是<代码整洁之道>的作者们累积多年的集体经验. 我们在软件工程方面的技术发展刚刚超过 50 年,我们仍然在学习很多东西

  • 让代码整洁、过程清晰的BASH Shell编程技巧

    这是我写BASH程序的招式.这里本没有什么新的内容,但是从我的经验来看,人们爱滥用BASH.他们忽略了计算机科学,而从他们的程序中创造的是"大泥球"(译注:指架构不清晰的软件系统). 在此我告诉你方法,以保护你的程序免于障碍,并保持代码的整洁. 一.不可改变的全局变量 1.尽量少用全局变量 2.以大写命名 3.只读声明 4.用全局变量来代替隐晦的$0,$1等 在我的程序中常使用的全局变量: 复制代码 代码如下: readonly PROGNAME=$(basename $0) read

  • 代码整洁之道(重构)

    前言 之前也介绍过我们团队的前端项目从零开始经历8个月迭代业务代码10万行(仅为产品长期规划需求的20%),至今仍然在不断迭代的过程. 团队成员除了设计好的架构来管理这种复杂度极高的前端应用,还开始补充设计模式以及重构方面的知识,目的是为了让项目代码在不断迭代的过程中优化项目代码,保持代码的新鲜度,鲁棒性,可维护性- 让后续加入的团队新人也可以快速加入我们的产品开发中 PS:  不管对于何种语言,重构都是软件开发过程中不可或缺的一部分.如果已经了解重构的基础,可以直接跳往至文章后面的重构案例部分

  • Vue代码整洁之去重方法整理

    在开始本篇的主题之前,让我们把上次遗留下来的问题都清理一下: 将其他组件中 axios 请求的地方封装起来. 这里就不把代码放在开头了,相关代码都放在文末,有兴趣了解的童鞋可以先往下翻. 好了, 我们现在把上篇剩下的任务给完成了,接下来我们来正式开始本篇内容吧. 去重是什么 字面上意思:去除重复,在项目中,不可避免的会出现重复代码.但是如果不好好去处理这些重复代码,那很有可能就会给你很多"惊喜". 如何为"重复" 下一个定义呢? 从最浅显的层次来看, 相同即是重复.

  • Java面试题及答案集锦(基础题122道,代码题19道)

    Java基础面试题及答案集锦(基础题122道,代码题19道),具体详情如下所示: 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象. 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性

  • Java代码精简之道(推荐)

    前言 古语有云: 道为术之灵,术为道之体:以道统术,以术得道. 其中:"道"指"规律.道理.理论","术"指"方法.技巧.技术".意思是:"道"是"术"的灵魂,"术"是"道"的肉体:可以用"道"来统管"术",也可以从"术"中获得"道". 在拜读大佬"孤尽&qu

  • 浅谈JavaScript 代码简洁之道

    测试代码质量的唯一方式:别人看你代码时说 f * k 的次数. 代码质量与其整洁度成正比.干净的代码,既在质量上较为可靠,也为后期维护.升级奠定了良好基础. 本文并不是代码风格指南,而是关于代码的可读性.复用性.扩展性探讨. 我们将从几个方面展开讨论: 变量 函数 对象和数据结构 类 SOLID 测试 异步 错误处理 代码风格 注释 变量 用有意义且常用的单词命名变量 Bad: const yyyymmdstr = moment().format('YYYY/MM/DD'); Good: con

  • PHP 代码简洁之道(小结)

    介绍 Robert C.Martin's 的 软件工程师准则 Clean Code 同样适用于 PHP.它并不是一个编码风格指南,它指导我们用 PHP 写出具有可读性,可复用性且可分解的代码. 并非所有的准则都必须严格遵守,甚至一些已经成为普遍的约定.这仅仅作为指导方针,其中许多都是 Clean Code 作者们多年来的经验. 灵感来自于 clean-code-javascript 尽管许多开发者依旧使用 PHP 5 版本,但是这篇文章中绝大多数例子都是只能在 PHP 7.1 + 版本下运行.

  • PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数

    思维导图 点击下图,可以看大图. 介绍 我把我比较喜欢的和比较关注的地方写下来和大家分享.上次我写了篇<php 跟老大的对话>.还是有很多疑问,这书帮了我不少的忙. 如果你比较繁忙,或者懒得看文字,建议你直接看截图,也会有很大的收获的.你可以通过比较截图中的代码就能知道孰优孰劣了. 代码部分我为什么用图呢?因为我经常用手机看代码,博客园的代码在手机里乱七八糟的,还是看图比较舒服. 专业术语 我们毕竟是用英文字母编码,所以用一些英语单词,更能显示出我们的专业性.以下的英文单词,你如果掌握了,与其

  • 分享令人目瞪口呆的 Java 代码技巧

    技术点 本文不是一个吹嘘的文章,不会讲很多高深的架构,相反,会讲解很多基础的问题和写法问题,如果读者自认为基础问题和写法问题都是不是问题,那请忽略这篇文章,节省出时间去做一些有意义的事情. 基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限.多租户.数据权限.工作流.三方登录.支付.短信.商城等功能. 项目地址:https://github.com/YunaiV/ruoyi-vue-pro 开发

随机推荐