代码重构技术探究

举报
Jet Ding 发表于 2020/09/28 15:39:03 2020/09/28
【摘要】 【重构解决的痛点】1. 代码存在太多的重复;2. 单个函数体太大;3. 单个代码文件太大;4. 模块之间的耦合性太高;5. 单个工程的体量过大;

image.png

【引言】

 

最近有同事抱怨重构工作比较难做,一是沟通上存在一些问题,主要还是因为对业务逻辑不是很了解。

 

我们说如果在这种情况下强行进行重构的话,可能会产生很多的副作用。

 

要想很好的进行重构工作,必须要对业务逻辑非常清楚,对项目的整体架构也非常清楚才行。

 

另外一个必要条件是要有充足的测试案例,并且测试执行速度比较快,不然的话,重构的工作会受到一些延迟,进展也比较缓慢。

 

此外,前段时间软件学院的刘杰珍(340654)给软件教练们作软件可信认证的相关介绍时,提到了目前的可信认证包括如下的内容:

 

设计模式,重构,面向对象设计,编程语言高阶特性,其中编程语言包括C, C++, Java, Go, Python, Javascript

 

针对以上内容,目前已经做了:

 

ü  C语言技术特点的总结《C语言的技术特点探究



接下来,我们通过这篇文章来研究分析一下代码重构技术。

 

【重构解决的痛点】

 

1. 代码存在太多的重复;

2. 单个函数体太大;

3. 单个代码文件太大;

4. 模块之间的耦合性太高;

5. 单个工程的体量过大;

 

以上种种问题会导致项目的后期维护和扩展非常困难。为了解决以上痛点,我们需要对现有的代码进行重构,接下来我们先看一个例子。

 

【例子】 

 

如下代码的需求是实现玩家向四个方向的移动。

 

public Position WalkNorth()

{

   var player = GetPlayer();

   player.Move("N");

   return player.NewPosition;

}

 

public Position WalkSouth()

{

   var player = GetPlayer();

   player.Move("S");

   return player.NewPosition;

}

 

public Position WalkEast()

{

   var player = GetPlayer();

   player.Move("E");

   return player.NewPosition;

}

 

public Position WalkWest()

{

   var player = GetPlayer();

   player.Move("W");

   return player.NewPosition;

}

 

我们发现其中的重复代码比较多,于是我们进行了如下的重构。

 

public Position Walk(string direction)

{

   var player = GetPlayer();

   player.Move(direction);

   return player.NewPosition;

 

经过重构以后,代码量大大减少,增强了代码的可读性,便于扩展和维护。

 

【概述】

 

在计算机编程和软件设计中,代码重构是指在不改变外部行为的情况下,对现有的计算机代码进行重构的过程。

 

重构是为了改善软件的设计、结构和实现,同时保留其现有的功能。

重构的潜在优势包括提高代码的可读性和降低复杂度。

 

这些都可以提高源代码的可维护性,并创建一个更简单、更干净或更有表现力的内部架构或对象模型,从而提高程序的可扩展性。

 

通常情况下,重构采用了一系列标准化的微观重构,每一个微观重构都是对计算机程序源代码进行微小的修改,这些修改不改变软件的功能需求。

 

许多开发环境都提供了自动化机制来执行这些基本的重构操作。

 

对于重构工作:

 

u 如果做得好,可以简化底层逻辑降低复杂度,从而帮助软件开发人员发现和修复系统中隐藏或潜伏的错误或漏洞。

u 如果做得不好,它可能引入新的bug,或者改变现有的功能。

 

【动机】

 

重构的动机通常是因为注意到代码中存在了不好的“味道”。

比如,某些方法非常的长,或者是几个函数的近似重复。

 

一旦意识到这类问题,可以通过重构源代码,将其转化为一个新的形式,去除这些坏的"味道"

 

对于一个较长的函数,可以提取出多个较小的子函数。

或者对于重复的函数,可以把重复的部分放在一个共享函数里面。

 

这种情况下,如果不进行重构,会导致技术债的积累。而进行重构是消除技术债的方法之一。

 

【重构的好处】

 

重构活动的好处一般有两类:

 

【可维护性】

 

因为源代码更容易阅读,对于代码作者的意图就更容易把握,所以修复bug就比较容易些。

 

可能的手段如:

l  通过将大型的函数或者组件缩减为一组单独的、命名良好的、单一目的的函数或者组件来实现。

l  可以通过将一些方法移到一个更合适的类中。

l  或者删除误导性注释来实现。

 

【可扩展性】

 

如果应用程序使用了可识别的设计模式,它会更容易扩展应用程序的功能,而且这些设计模式可能提供了一些以前不存在的灵活性。

 

【挑战】

 

重构需要提取软件系统结构、数据模型和应用程序内部的依赖关系,以便于获得对现有软件系统知识的了解。

 

【知识不全能力所限】

 

u 有时候,团队的更替或者开发人员的离职,会导致对整个软件系统的理解不充分,对于系统相关的知识可能掌握的不全面。

u 进一步的代码重构活动需要额外的努力才能重新获得这些知识。

u 重构活动产生的架构方面的修改可能会使软件系统的结构体系进一步恶化。

u 恶化会影响体系结构的特性,如可维护性和可理解性,这可能导致软件系统的完全重新开发。

 

【如何改善】

 

当使用工具和相关技术提供有关算法和代码执行顺序的数据时,代码重构活动就有了软件智能的保障,为软件系统结构、数据模型和组件内部依赖关系的内部状态提供一种可理解的格式,进而形成更高层次的抽象理解,然后对需要修改的内容和方式形成精炼的视图。

 

重构的一个不可缺少的步骤就是要有充足的测试案例保证现有功能不被破坏。

 

【测试】

 image.png


 

 

在重构之前,应该准备好充足的单元测试,以确保程序模块仍然能像预期的那样运行。

单元测试可以给大型的重构工作带来稳定性。

即使是大型的重构工作,也可以通过单一的原子提交来实现。

一个常见的策略是:

u 将所有的项目代码存储在一个单一的存储库中,称为monorepo,这可以让安全可靠和原子化的重构跨越多个项目。

u 有了单元测试之后,重构就是一个迭代的循环,即先做一个小的程序变换,然后测试确保正确性,然后再做另一个小的程序变换。

u 如果在任何一点上测试失败了,最后的小的改动就会被撤销,并以不同的方式再重复进行。

u 通过上面这些许多小的步骤,程序就从原来的状态到了你希望的状态。

u 为了使这个过程更加实用高效,单元测试必须运行得非常快,不然的话程序员们要花很大一部分时间等待测试结束。

u 极限编程和其他敏捷软件开发的拥护者将这项活动描述为软件开发周期中不可分割的一部分。

 

【相关技术】

 

以下是一些微重构的例子,其中一些可能只适用于某些语言。许多开发环境为这些微重构提供了自动支持。

 

例如,程序员可以点击一个变量的名称,然后在上下文菜单中选择 "封装字段"进行重构。

然后IDE会提示额外的细节,通常会有合理的默认值和代码修改的预览。

 

在程序员确认后,它将在整个代码中执行所需的更改。

 

u 有助于更多理解程序结构的技术

n  程序依赖关系图--数据和控制依赖关系的显式表示

n  系统依赖图--PDG之间过程调用的表示方式

n  软件智能----逆向工程的初始状态,以了解现有的应用内的依赖关系。

u 可实现更多抽象化的技术

n  封装字段--gettersetter方法

n  通用化类型----创建更多的通用类型,让更多的代码共享。

n  将类型检查代码改为状态/战略代码

n  用多态性取代条件性

u 将代码分解成更多逻辑碎片的技巧

n  组件化将代码分解成可重用的语义单元,这些语义单元呈现出清晰的、定义明确的、简单易用的接口。

n  提取类,将现有类中的部分代码移动到一个新的类中。

n  提取方法,将一个较大的方法的一部分提取变成一个新的方法。通过将代码分解成更小的部分,提高代码的可读性。

u 改进代码名称和位置的技巧

n  移动方法或移动字段--移动到更合适的类或源文件中

n  重命名方法或重命名字段----将名称改成一个新的、能更好地揭示其用途的名称

n  拉升----在面向对象编程(OOP)中,移到超类中去

n  下推--OOP中,移动到子类

u 自动克隆检测

 

【硬件重构】

 

虽然重构这个术语最初只指软件代码的重构,但近年来,用硬件描述语言(HDL)编写的代码也正在被重构。

 

硬件重构这个术语被用作硬件描述语言中代码重构的速记术语。

由于HDLs不被大多数硬件工程师认为是编程语言,所以硬件重构被视为一个独立于传统代码重构的领域。

 

ZengHuss提出了模拟硬件描述的自动重构,在他们的方法中,重构保留了硬件设计的模拟行为。其改进的非功能测量是重构后的代码可以被标准的合成工具处理,而原始代码则不能。

 

Synopsys的研究员Mike Keating也对数字HDL的重构(尽管是手工的重构)进行了研究,他的目标是使复杂的系统更容易理解,从而提高设计者的工作效率。

 

【自动代码重构】

 

许多软件编辑器和IDE都有自动重构支持。

 

它们既可以重构应用程序代码,也可以重构测试代码,以下是其中几个例子:

 

u DMS软件重构工具包(支持CC++C#COBOLJavaPHP等语言的大规模重构)

u 基于Eclipse

n  Eclipse(适用于Java,并在较小程度上适用于C++PHPRubyJavaScript。)

n  PyDev (适用于Python)

n  Photran (Eclipse IDEFortran插件)

u Embarcadero Delphi

u 基于IntelliJ的:

n  AppCode (用于Objective-CCC++)

n  IntelliJ IDEA (用于Java)

n  PyCharm (用于Python)

n  WebStorm (用于 JavaScript)

n  Android Studio (适用于Java)

u JDeveloper (适用于Java)

u NetBeans (适用于Java)

u Smalltalk

u 基于Visual Studio:

n  Visual Studio (适用于.NETC++)

n  CodeRush (Visual Studio的附加组件)

n  Visual Assist (Visual Studio的插件,支持C#C++的重构)

u Wing IDE (适用于Python)

u Xcode(适用于CObjective-CSwift

u Qt Creator(适用于C++Objective-CQML

 


 

【小结】

 

本文对代码重构技术的概念,动机,好处,挑战和技术方法进行了学习和探讨,希望对大家有帮助。

欢迎讨论。

image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。