浅谈程序重构识别的研究与实现

2015-06-02 22:38张宝春
教育界·下旬 2015年4期
关键词:度量代码重构

张宝春

一、研究背景

软件也是有生命周期的,在软件使用过程中,软件需要升级、更改,以适应新的需求。一般软件的更改都是迫于外部的压力,譬如客户要求或者是行业竞争。而这些更改必然会对程序原有的结构造成破坏,降低质量,提高程序复杂度,结果软件使用的维护成本被提高,以后再次升级将会变得困难。Brooks指出所有软件都存在这个问题,而且修复进行得越晚,成本越高,代价越大,直到代价超过重新开发。解决这个问题,需要一种能够提高软件质量同时降低程序复杂度的技术。重构就是能够解决这个问题的一项重要技术手段。重构是指在不改变软件外部行为的前提下,以提高软件内部质量为目的,对软件实施更改的一种技术。重构过程有三个阶段:

1.识别:找出需要重构的地方,确定重构的方式;

2.代码实施:对需要重构的位置的代码进行重构;

3.验证:验证重构后和重构前的程序能否实现相同的功能,不能因为重构改变代码的功能。

我们重构的目的是最终让系统更加简单,也就是说,让系统职责分配更清晰,代码复杂度更低。

重构的主要功能是通过软件的修复来提高软件的性能。因此,重构可作为一项软件辅助技术应用到大部分软件的维护活动中去:

1.重构是一种重要的预防性维护措施。它既不修正错误,又不增加新功能,而是用于提高代码可读性或改变代码内部结构与设计。它通过对类、变量和方法的重新分配,降低代码冗余度,提高软件质量(如模块性、重用性、复杂性、可维护性、可理解性和效率)。

2.重构可用于逆向工程中,它能够分析遗留系统,使恶化的代码重新组织,转换成良好的形式。特别是我们需要给现有程序添加新的功能很困难的时候,开发人员先进行代码重构,新功能的添加就会特别简单。

重构的过程是对代码进行更改,这涉及装程序,所以重构不是一个简单的轻量级的软件技术,需要花费大量的精力和时间:

1.识别程序中哪些地方存在“坏味道”、哪些代码需要被重构是重构的难点,因为对于“坏味道”的理解取决于很多因素,在很大程度上存在主观性。因此,如何自动识别重构对象是限制重构技术发展的瓶颈,目前大部分工作都是基于人工的代码检测,大大降低重构效率,这也是制约重构发展的最大障碍。

2.在重构实施阶段,需要对“坏味道”进行调整,使得问题代码按照预期的方式进行调整。对这些代码的修改必定会影响到程序中的其他部分,需要为不同的“坏味道”设计安全的程序转换。为了避免重构过程牵涉到整个程序,要限定重构的规模。在同一个程序中,同样类型的“坏味道”会重复多次出现,只是表现形式不同,要使一次重构实施能同时修改所有具有相同类型的问题代码。这些都是在重构实施阶段需要被考虑的问题。

3.重构后的代码必须能够正确运行,并具有与原程序相同的行为。不幸的是,对正确性和行为不变性的研究十分缺乏。这主要是因为程序的行为会涉及运行时的动态信息,而重构是一种静态的代码分析技术。要把动态的行为通过静态的方式来验证,是一项重大挑战。

我们可以通过一种形式化的图转换技术,建立一个完整的重构模型。首先,把程序转换成等价的图表示,识别出图中具有不合理关系的“坏味道”作为重构对象;然后,通过程序切片技术,提取与重构对象相关的语句,按照图转换规则对其实施重构;最后,验证被转换的图仍表示一个正确的程序,且转换前后具有相同的行为。

二、重构识别的现状

目前,对重构对象的识别主要依靠手动方法,这样不但效率低,而且正确性不高,从而制约了重构技术的发展。因此,自动识别重构对象对重构技术的发展非常重要。现有的重构识别方法主要通过程序分析、可视化和度量等技术来辅助实现。

识别重构对象的方法之一是静态分析。Kamiy首先提出一种自动识别克隆代码的技术,消除程序中的冗余代码。Katao利用动态分析技术,开发出能够自动检测程序不变量的工具Daikon,进而删除不影响程序运行的不变量。

另外一种识别重构对象的方法是可视化技术,它根据不同需求,将程序在不同层次进行抽象,然后在这个抽象层次上发现潜在的“坏味道”。Simon利用基于度量的可视化技术,把程序的内聚度在2D图上抽象出来,辅助维护人员识别重构对象。Bohnet将组件之间的交互(调用关系)可视化在3D空间,在不同的抽象层次(从方法间的交互到系统间的交互)上分析组件之间的交互,从而识别不合理的调用关系。

度量技术也是重构识别的重要方法。如Chidamber提出的LCOM度量可反映一个类中的方法与属性之间交互的紧密程度。Briand提出一种针对类的接口的度量,来分析这个类的接口定义的是否合理。Sheetz等通过Fan-out度量,来反映一个类与外界的耦合度,这可以帮助识别程序中类间交互的“坏味道”。Ott在一些简单度量的基础之上,定义了一种基于切片的内聚度度量,通过计算一个指定的变量在模块内的切片,可间接地计算该模块的内聚度,从而识别出一些重构对象。而Simon也结合前人思想,定义出能够精确反应模块内聚度的度量函数,根据元素间共享的属性个数来决定模块的内聚度。这些方法都可用来辅助维护人员识别程序中某种“坏味道”。

三、重构工具

在以上各种技术的支持下,学者们开发出大量的重构工具。XRefactory是一种带有预处理功能的重构工具,可以对C和Java程序进行重构。Smalltalk Refactoring Browser是一个半自动化的重构工具,维护人员通过选定一段带有“坏味道”的代码,并指定使用何种重构方法,便可自动执行相应的重构。它已经集成到许多IDES之中(如VisualWorks, TogetherJ, JBuilder, Eclipse)。另外,Casais提出对Eiffel程序进行类层次关系重构的工具。Guru是一种对Self程序进行自动化重构的工具,可以从类层次结构中提取出公共部分组成新的父类,也可以从方法中提取出共享代码组成新的方法。同时,Casais和Tichelaar分别提出降低程序实体间依赖性的重构工具。Sunye把重构与CASE工具进行集成。Tourwe和Meuter指出被编译器执行的优化也可以被看作是一种自动化重构,虽然这些优化转换是对用户完全透明的,但它的目的是提高程序的效力,并保持程序的外部行为不变。

在常用的重构工具中,SlickEdit和Ref++是两款功能完善的C++重构工具,他们与Visaul Stuido平台直接集成,可以对代码实施Extract Method和Modify Parameter等十多种重构。而XRefactory]和JFactor是被广泛使用的Java自动化重构工具,被无缝集成到Eclipse平台中,实施一些简单的原子重构,辅助维护人员对程序的结构进行改善。在某些情况下,全自动化工具存在一些劣势,因为重构全部自动化,可能做了太多的工作,会使一部分被重构后的程序比之前更难理解。交互式重构工具可能不存在这样的劣势,但交互式重构工具需要大量的人机交互,这是一件耗时的事情。不论怎样,半自动化重构工具在实际应用中的使用范围最广,因为一些重构所需的知识不能从软件中被提取,却可以从人脑中得知。

四、研究内容

目前对重构技术的研究比较分散,对于重构的不同阶段,使用的技术各不相同,缺少统一的重构模型和基础技术支持。我们可以用基于程序切片的形式化方法对程序进行重构识别、实施和验证。这种形式化的重构模型以图表示作为基础技术,把一个程序用图表示出来,那么重构就相当于图转换文法中的一条产生式规则,一个重构的前置条件对应为图转换文法中一条产生式的前置条件。该方法先把程序转换成等价的图表示,所有的重构过程都在图的基础上完成,形成一个统一的重构体系。

最主要的研究内容为以下三方面:

1.重构识别

在图中构造元素之间的依赖关系,生成程序依赖图,在此基础上定义一种度量函数来计算元素间的控制关系,根据度量结果,识别元素间不合理的耦合关系,从而自动识别出程序中的“坏味道”。该技术可以自动分析源代码,指出程序中不合理的地方,改变了以往手动重构识别所带来的主观性和效率问题,解决了重构的瓶颈,为自动化重构实施打下良好基础。

2.重构实施

通过向图中的节点和边中加入类型信息,把程序依赖图扩展为类型图。类型图包含了重构实施过程所需的必要信息。在重构和类型图转换之间建立起等价关系,将程序的重构过程变为对图的转换过程。通过类型图的转换产生式表示重构,可以使重构对象按照预想的方式进行调整,并使一次重构实施能够同时修改所有具有相同类型的问题代码。为了避免重构过程牵涉到整个程序,减少重构的影响集,可以借助程序切片技术计算出与重构对象相关的代码,使重构过程仅在切片中进行。

3.重构验证

为保证重构的正确性,可以预先为重构产生式定义一些前置条件,使得能够满足条件的程序才能被重构,且保持程序的正确性。在保证重构正确性的前提下,才能验证重构是否保持程序行为的不变性。本文基于近似性原理,定义一些能够代表程序行为的图属性,通过验证在重构实施前后图的行为属性是否被改变,从而证明重构是否保证程序的行为不变性。该方法避免了使用静态方法验证程序的动态行为带来的弊端。

五、总结展望

通过识别出软件中的“坏味道”,对其实施重构,调整软件的结构使之更加合理,从而提高软件质量,进而有利于程序理解和错误定位等其他软件维护活动,大大降低软件维护的成本。随着统一重构模型技术的发展逐渐成熟,它势必会得到软件维护人员的重用,成为必不可少的一项软件维护手段。

【参考文献】

[1]Brooks F. The Mythical Man-Month [M]. New York: Addison-Wesley, 1975.

[2] Emden E V, Moonen L. Java quality assurance by detecting code smells [C] . Proceedings of Working Conference Reverse Engineering, Amsterdam, Netherlands, 2002: 97-108.

[3]Czibula I G, erban G. Improving Systems Design Using a Clustering Approach [J]. International Journal of Computer Science and Network Security, 2006, 6(12):40-48.

[4]Sunye G, Pollet D, LeTraon Y, et al. Refactoring UML models [J]. Lecture Notes in Computer Science, 2001, 21(85): 134-138.

猜你喜欢
度量代码重构
鲍文慧《度量空间之一》
模糊度量空间的强嵌入
长城叙事的重构
迷向表示分为6个不可约直和的旗流形上不变爱因斯坦度量
北方大陆 重构未来
创世代码
创世代码
创世代码
创世代码
北京的重构与再造