关于代码重构的灵魂三问:是什么?为何?怎么作?

摘要:让咱们再回到重构的基本概念,思考咱们须要怎样的重构辅助服务。

1、背景

代码重构是每一位开发者最熟悉不过的字眼,其出现一般伴随着开发过程。在程序开发、迭代与演进的漫漫长路中,某次不经意的修改就可能破坏程序原有的设计与结构,形成代码结构的流失,而这种流失是具备累积性的,若未及时发现与重构,程序就会逐渐腐烂甚至变质,造成巨大的历史债务。其实重构就比如收拾房间,若是咱们每天打扫,那么天天花3分钟就能打扫干净,可若是一个月不打扫,你想一想须要多久才能打扫完。程序员

既然代码重构在开发过程当中这么重要,怎么能没有相应的服务来支撑它呢?咱们能不能开发出相应的“扫帚”辅助咱们天天打扫房间?亦或是“扫地机器人”自动的帮咱们打扫一个月未收拾的房间?设计模式

带着上述疑问,让咱们再回到重构的基本概念,思考咱们须要怎样的重构辅助服务。安全

1. 什么是重构

如此书中所说,所谓重构(Refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码作出修改,以改进程序的内部结构。这里的重构有两层含义,一个名词含义,一个动词含义:架构

重构(名词):对软件内部结构的一种调整, 目的是在不改变软件可观察行为的前提下,提升其可理解性, 下降其修改为本。运维

重构(动词):使用一系列重构手法, 在不改变软件可观察行为的前提下,调整其结构。函数

至此,咱们应该明白,一款好的重构辅助服务应该至少兼具不变与变两个特征:不改变软件可观测行为;优化代码结构,下降修改为本,提升可理解性。工具

2. 何时重构(什么时候应作怎样的重构)

就重构时机问题,业界也有比较激烈的讨论,有人认为重构应该随时随地地进行,不该该为了重构而重构,就好比我在添加新功能时、修补错误时、或者复审代码时均可以进行重构,咱们暂且称之为“开发时重构”,也有人认为“添加新功能”和“重构”是两顶帽子,在添加新功能时,就不该该修改既有代码,只管添加新功能,而在重构时,就不能添加功能,只管改进程序结构,一次只作一件事,咱们暂且称之为“维护式重构”。我我的认为这两种说法并不矛盾,真正好的重构应该是二者的有机结合。优化

如上图所示,红色范围是我认为比较好的重构实践。ui

我认为不管在作新功能开发时仍是在作老版本维护时,都适合作代码重构,只是适合的重构粒度不一样而已。对于开发时重构,比较适合作我的级小范围的微重构,这种重构每每影响范围小,且较为简单,不会对开发增长工做难度,例如“重命名”、“函数提取”等原子重构;对于维护时重构,比较适合作架构级大范围的复杂重构,这种重构每每是为了解决项目代码中遗留的技术债务,且一般和代码坏味道的消除结合在一块儿,例如依恋情结(Feature Envy)、数据泥团(Data Clumps)等,而这些坏味道的重构每每由一系列的重构原子操做组合而成。固然,最好将重构工做尽量多地作在开发阶段,尽可能减小新增代码对已有设计与架构的破坏。编码

看到这里,咱们是否有些似曾相识,这不就对应了上文中提到的“扫帚”以及“扫地机器人”在实际重构工做中的应用?

3. 为何须要代码智能重构服务

使用过现代IDE开发代码的同窗们应该都知道,以IntelliJ IDEA为表明的不少IDE多少都自带一些重构功能,但目前为止,这些重构都是例如“重命名”、“函数提取”等原子性重构,只对重构过程提供了部分支持,绝大部分的代码、架构坏味道重构工做仍然得靠手工完成,就比如你须要打扫一个月未打扫的房子,但手中只有一把扫帚同样。Kent Beck 说过:“手工重构仍然是很耗时的工做。正是这个简单的事实形成了不少程序愿不肯意进行重构,尽管他们知道本身应该重构,但毕竟重构的成本太大了。若是可以把重构变的像调整代码格式那么简单,程序员天然也会乐意像整理代码格式那样整理系统的设计。而这样的整理对代码的可读性、可复用性和可理解性,都能带来深远的正面影响。”正因如此,一款智能的、能够帮助开发者发现代码、架构中的坏味道而且引导开发者完成代码重构的服务尤其重要。

2、Devops全流程下的重构服务需求

对于持续交付过程当中的代码开发与发布环节,如上图虚线框所示,几乎每一步都与代码质量的看护或代码重构相关。

  1. 开发环节可大体分为两种类型:用于添加新功能的“增量式开发”以及维护老版本的“存量式维护”。对于“增量式开发”而言,须要重构服务的编码规范重构和原子重构能力在开发过程当中帮助开发人员提高代码质量与开发效率;对于“存量式整改”而言,则须要重构服务具有架构、代码坏味道的检查、重构机会点挖掘以及重构方案的推荐能力,并将相应的重构方案拆解为彼此独立且正交的原子重构能力,最终做为一个原子重构序列推荐给开发人员,在与人机交互中一步步完成重构应用。
  2. 持续发布环节,MR门禁中的代码静态检测须要触发对坏味道代码的识别,做为一种增量式检测,主要识别由新增代码引入的代码及架构坏味道, 并自动生成一次重构任务,引导开发人员进行一次重构,避免代码中技术债堆积。
  3. 生产运维环节,须要作按期的架构看护,将相应度量结果经过架构可视化图形界面展现出来,当架构某个模块腐化到一个阈值时自动报警,提示版本负责人作相应重构。

3、如何辅助开发人员实现代码分层重构

1. 都有哪些层级的重构

我的认为重构大体能够分为4个层级,这些层级之间的关系能够从上图看出,并不是是自底向上依次包含的关系,它们之间会有些重叠也有些不一样。单纯从重构自己来说,越上层级的重构操做非肯定性越强,更偏业务性,而越下层级的重构操做肯定性越强,更偏技术性。从智能重构服务的角度来说,越上层越偏检测能力,越下层越偏纯重构能力。下面咱们由下至上依次来看看不一样层级重构操做的特色与异同。

原子重构能力:上文中也有提到原子重构,原子重构到底有哪些呢?顾名思义,即不可再分的重构操做,例如重命名、移动、删除等重构操做,这些重构操做是彻底肯定性的,例如我想要抽取一段代码造成一个新方法,是否可抽,能够抽成什么样都是彻底肯定的。这些重构操做由于其不可再分性位于重构最底层。

编码规范重构:有些同窗可能会对这个层级的重构比较陌生,其实它就是基于规范和规则的重构,一般包含了咱们所说的微重构,例如对违反了命名风格的标识符进行重命名重构,亦或是对无用代码进行删除的安全删除重构等等,而且这层的重构操做彻底能够经过调用下层的1个原子重构来实现。正由于这些重构操做基于规则,其重构结果也是相对肯定的。

代码坏味道重构:代码坏味道也包括了架构坏味道,例如Feature Envy、God Class等类型,这些层级重构的目的是为了消除相应的代码坏味道,因此相对来讲更复杂,一次重构的完成每每要调用下层多个原子重构操做,例如对God Class进行重构,须要调用至少一次Extract Class原子重构。同时这层重构的非肯定性也更高,对一种代码坏味道的重构消除每每能够经过多种手段。

设计模式坏味道重构:这层重构应该属于金字塔顶端的重构,由于它涉及范围太广,更偏向于对业务的理解与预测,从具象到抽象,显得有些虚无缥缈。设计模式有7中坏味道和11中原则,目前不管学术界仍是工业界对于这类问题检测、重构相关的研究都还很少。

2. 智能重构服务在不一样层级下的应用

结合Devops下的重构服务需求与上图中的四层重构,咱们基本能够看出智能重构服务不一样层级的重构能力主要运用在开发工做流中的哪一个阶段。对于原子重构来讲,由于其肯定性以及业务无关性,最适合做为插件集成在IDE上,由开发者作增量开发时调用;对于编码规范重构来讲,适合同原子重构一块儿集成进IDE插件,在开发过程当中自动且快速的识别到违反特定规则的代码,并辅助开发者重构;对于代码坏味道重构来讲,适合在持续发布环节的门禁阶段拦截问题并引导开发者回到IDE进行代码智能重构;对于设计模式坏味道重构来讲,由于其涉及业务理解与预测,更适合放进生产运维环节,结合版本演进与迭代历史,给出架构腐化的预测以及相应重构方案的推荐。

3. 搭积木式的重构应用

既然上层重构操做均可以转化为最底层的原子重构操做,那如何表达这种转化呢?表格中列举了几种常见的重构原子操做,每种重构原子操做均可以用一个函数来表达。例如Move Method,函数名为Move Method,咱们用三个参数来明确它的行为:Source(所属类型)、Target(目标类型)以及(须要移动的方法),有了这些信息就能够明确一次Move Method原子重构。对于任何一个复杂的重构来讲,均可以表示成以下形式的原子重构序列,即一系列原子重构的组合。

就像搭积木同样,任何上层重构均可以经过搭积木的方式组合底层原子重构来实现。

4、重构服务设计原则

重构服务的设计亦如其它不少开发服务同样,最终目标都是提高用户开发效率与代码质量,若是两者皆得不到保证,那这款服务将被永远丢进垃圾堆里。从咱们在华为内部的实践经验,总结了如下几点原则:

充分的用户交互:经典的重构工做流程为“小步前进,随时可用,随时可停,随时回退”,小步修改意味着每一步出错的可能性大大减少,要遵循这个流程,就离不开工具和用户频繁的交互,要引导用户一步步的完成复杂的代码重构,每一个过程都要作到随时可用,随时可停,随时可退。

友好的重构工做界面:代码重构有点相似代码自动修复,但比代码自动修复涉及范围更广,如何让用户更好的表达重构意图、而且一目了然的看到重构对原代码架构的影响很是重要,这一部分有不少能够创新的地方。

个性化用户配置:上层级的重构每每能够有不一样的执行路径,根据代码工程不一样、业务场景不一样,同一种坏味道重构的实现方式也可能不一样,要以用户为中心,根据业务不一样、用户不一样给出个性化、定制化的重构解决方案,这一部分恰好是AI擅长的领域。

Devops服务深度集成:任何一款开发服务若是离开Devops服务就会成为一个孤立的散点,没法在开发过程当中被顺畅的使用,若是咱们能把重构服务集成进IDE、代码检视环节、代码入库环节以及验证发布环节,就可让重构工具Build In在可信开发过程当中,让重构服务触手可及。

高效:特别是在IDE上的重构分析服务,若是分析过程须要花费太长时间,程序员极可能就不会使用这些重构服务,他们宁肯手工重构。

 

点击关注,第一时间了解华为云新鲜技术~

相关文章
相关标签/搜索