JMove: A novel heuristic and tool to detect move method refactoring opportunities 阅读笔记

1、原文结构

Section 1, introduction.
Section 2 briefly presents previous research on strategies for recommending Move Method refactorings.
Section 3 details our recommendation approach, including its main algorithms and functions. The section also presents a detailed example and a supporting tool.
Section 4 presents the evaluation using 195 synthesized Move Method opportunities, from 10 open-source systems.
Section 5 reports a comparative study of the recommendations provided by JMove, JDeodorant, inCode, and Methodbook in two open-source systems.
Section 6 conducts a study with expert developers.
Section 7 concludes the paper.

本次笔记主要针对原文重要的第三章节而作,以求学习JMove所采用的重要算法和思想。

2、原文第三章及翻译

3.Proposed approach

Our approach detects methods located in incorrect classes and then suggests moving such methods to more suitable ones. More specifically, we first evaluate the set of static dependencies established by a given method m located in a class C, as illustrated in Fig. 1. After that, we compute two similarity coefficients: (a) the average similarity between the set of dependencies established by method m and by the remaining methods in C; and (b) the average similarity between the dependencies established by method m and by the methods in another class Ci. If the similarity measured in the step (b) is greater than the similarity measured in (a), we infer that m is more similar to the methods in Ci than to the methods in its current class C. Therefore, Ci is a potential candidate class to receive m. In the remainder of this section, we describe the proposed recommendation algorithm (Section 3.1), the similarity functions that play a central role in this algorithm (Section 3.2), and the strategy we designed to decide the most suitable class to receive a particular method (Section 3.3). We also empirically assess our defined thresholds through a calibration experiment (Section 3.4). Moreover, we describe a supporting tool (Section 3.5) and present four examples of Move Method refactorings suggested by JMove and two state-of-the-art tools (Section 3.6). Finally, we document the limitations of our approach (Section 3.7).
我们的方法会检测到位于不正确的类中的方法,然后建议将这些方法移动到更合适的方法中。更具体地说,我们首先评估由位于C类中的给定方法m所建立的静态依赖关系集,如图1所示。然后,我们计算两个相似系数: (a)是方法m建立的依赖集与C中其余方法之间的平均相似度;(b)是方法m和另一类Ci方法建立的依赖集之间的平均相似度。如果步骤(b)中测量的相似度大于(a)中测量的相似度,我们推断m更类似于Ci中的方法,而不是当前类c中的方法。因此,Ci是接收m的潜在候选类。在本节的其余部分中,我们将描述所提出的推荐算法(第3.1节),相似度函数在这个算法中起着核心作用(第3.2节),以及我们设计的用于决定最适合的类来接收特定方法的策略(第3.3节)。我们还通过校准实验(第3.4节)对我们定义的阈值进行了经验性评估。此外,我们还描述了一个支持工具(第3.5节),并给出了四个由JMove建议的移动方法重构的例子和两个最先进的工具(第3.6节)。最后,我们记录了我们的方法的局限性(第3.7节)。
在这里插入图片描述
3.1. Recommendation algorithm

Algorithm 1 presents the proposed recommendation algorithm. Assume a system S with a method m implemented in a class C. For all class Ci ∈ S, the algorithm verifies whether m is more similar to the methods in Ci than to the methods in its original class C (line 6). In the positive cases, we insert Ci in a set T that contains the candidate classes to receive m (line 7). Finally, we search in T for the most suitable class to receive m (line 10). In case we find such a class C, we make a recommendation to move m to C (line 11).
算法1提出了推荐移动算法。假设一个系统S的方法m在C类中实现。对于所有类Ci∈S,算法验证m是否更类似于Ci中的方法,而不是其原始类C中的方法(第6行)。若m更类似于Ci中的方法,我们在集合T中插入Ci,其中包含接收m的候选类(第7行)。最后,我们在T中搜索最适合的类来接收m(第10行)。如果我们发现这样的C’类,我们建议将m移到C’(第11行)。

Algorithm 1 Recommendation algorithm.
Input: Target system S
Output: Set with Move Method recommendations
1: Recommendations ← ∅
2: for all method m ∈ S do
3: C = get_class(m)
4: T ← ∅
5: for all class Ci ∈ S do
6: if similarity(m,Ci) > similarity(m,C) then
7: T ← T ∪ {Ci}
8: end if
9: end for
10: C’ = best_class(m, T )
11: Recommendations ← Recommendations ∪ { move(m,C’)}
12: end for

This algorithm relies on two key functions: (a) similarity(m, C) that computes the average similarity between method m and the methods in a class C; and (b) best_class(m, T ) that receives a set T of candidate classes to receive m and returns the most suitable one. These functions are detailed in the following sections:
该算法依赖于两个关键函数: (a) similarity(m,C),它计算方法m和一个类C中的方法之间的平均相似度;(b) best_class(m,T),它以候选类的集合T以及待移动的方法m为参数,返回最合适接收m的一个候选类。这些函数将在下文被详细叙述:

3.2. Similarity function

Our approach relies on the set of static dependencies established by a method m to compute its similarity with the methods in a class C, as described in Algorithm 2. Initially, we compute the similarity between method m and each method m’ in C (line 4). In the end, the similarity between m and C is the arithmetic mean of the similarity coefficients computed in the previous step. In this algorithm, NOM(C)denotes the number of methods in a class C (lines 8 and 10).
如算法2所述,我们的方法依赖于由方法m建立的静态依赖集来计算其与C类中的方法的相似性。首先,我们计算C中方法m和每个方法m’之间的相似性(第4行)。最后,m和C之间的相似度是上一步计算的相似度系数的算术平均值。在该算法中,NOM(C)表示C类中方法的数量(第8行和第10行)。

Algorithm 2 Similarity Algorithm.
Input: Method m and a class C
Output: Similarity coefficient between m and C
1: sim ← 0
2: for all method m’ ∈ C do
3: if m = m’ then
4: sim = sim + meth_sim(m, m’)
5: end if
6: end for
7: if m ∈ C then
8: return sim / [NOM(C)− 1]
9: else
10: return sim / NOM(C)
11: end if

The key function in Algorithm 2 is meth_sim(m, m’), which computes the similarity between the sets of dependencies established by two methods (line 4). We decided for the use of the Jaccard coefficient, since it has been used in similar approaches (Simon et al., 2001; Tsantalis and Chatzigeorgiou, 2009; Fokaefs et al., 2007; Tsantalis and Chatzigeorgiou, 2011), defined as
算法2中的关键函数是meth_sim(m,m’),它计算由两种方法建立的依赖关系集之间的相似性(第4行)。我们决定在该函数中使用Jaccard相似度,因为它已被用于相似的方法中。定义如下:
在这里插入图片描述
In this definition, Dep(m) is a set with the dependencies established by method m. This set includes the types the implementation of m establishes dependency with. More specifically, we consider the following dependencies:
在这个定义中,Dep(m)是一个由方法m建立的依赖关系的集合。这个集合包括了m的各种实现方式所建立的依赖关系的类型。更具体地说,我们考虑了以下依赖关系:

• Method calls: if method m calls another method m’ , the class of m’ is added to Dep(m).
• Field accesses: if method m reads from or writes to a field f, the type of f is added to Dep(m). When f is declared in the same class of m, then the class itself is also added to Dep(m).
• Object instantiations: if method m creates an object of a type C, then C is included in Dep(m).
• Local declarations: if method m declares a variable or formal parameter v, the type of v is included in Dep(m).
• Return types: the return type of m is added to Dep(m).
• Exceptions: if method m can raise an exception E or if method m handles E internally, then the type of E is added to Dep(m).
• Annotations: if method m receives an annotation A, then the type of A is included in Dep(m).
• 方法调用:如果方法m调用另一个方法m’,则m’所在的类被添加到Dep(m)中。
• 字段访问:如果方法m从字段f中读取或写入,则会将f的类型添加到Dep(m)中。当f在m的同一个类中声明时,那么该类本身也被添加到Dep(m)中。
• 对象实例化:如果方法m创建了一个类型为C的对象,那么C将包含在Dep(m)中。
• 局部声明:如果方法m声明一个变量或形参v,则v的类型包含在Dep(m)中。
• 返回类型:将m返回值的类型添加到Dep(m)中。
• 异常:如果方法m可以引发异常E,或者方法m在内部处理E,则E的类型被添加到Dep(m)中。
• 注释:如果方法m接收到注释A,则A的类型包含在Dep(m)中。

When building the dependency sets we ignore the following types: (a) primitive types; and (b) types and annotations from java.lang and java.util (such as String, HashTable, Object, and SupressWarnings). Since virtually all classes may establish dependencies with these types, they do not actually contribute for the measure of similarity. This decision is quite similar to the one followed by text retrieval systems that exclude stop words because they are not helpful in describing the content of a document.
在构建依赖集时,我们忽略以下类型: (a)原始类型;(b)来自java.lang和java.util的类和注释(如String, HashTable, Object, 和SupressWarnings)。由于几乎所有的类都可能与这些类型建立依赖关系,因此它们实际上并没有对相似性的度量有贡献。这个决定与文本检索系统非常相似,因为它们对描述文档的内容没有帮助。
For the sake of clarity, we omitted from Algorithm 2 a test that discards three kinds of methods when calculating the similarity of dependency sets:
为了清晰起见,我们在算法2中省略了一个测试,该测试在计算依赖集的相似性时将放弃如下三种方法:

• A methods m that is the only method in its class because our approach is based on the similarity between a given method and the remaining methods in the class.
• A method m whose dependency set has less than four dependencies because few dependencies are more subjected to imprecise or spurious similarity measures. We defined this threshold after experimental tests where we found that lower thresholds would contribute to an explosion in the number of recommendations (refer to Section 3.4).
• A method m without parameters and with a single statement, which is a return statement. Based on a heuristic proposed by Seng et al. (2006), the goal is to filter out getter methods, which by their very nature are rarely implemented in incorrect locations. The same happens with setter methods, but they are filtered out by the Move Method preconditions, as described in the next section.
• 一个方法m是它的类中唯一的方法。因为我们的方法基于一个给定的方法和类中的其他方法之间的相似性。
• 方法m的依赖集中的依赖数量小于4个。因为很少的依赖度更容易导致算得不精确或虚假的相似度。我们在实验测试后定义了这个阈值,其中我们发现较低的阈值会导致建议数量的激增(参考第3.4节)。
• 一个没有参数且只有一个返回语句的方法m。基于Seng等人(2006)提出的启发式方法,其目标是过滤掉getter方法,由于这些方法的本质,很少在不正确的位置实现。同样的方法也发生在setter方法上,但是它们被Move Method的前提条件过滤掉了,如下一节所述。

3.3. Target class selection

Assume that T is now a list with classes C1,C2, . . .,Cn that are more similar to a method m than its current class C, as computed by Algorithm 1. Assume also that the classes in T are in descending order by their similarity with m—i.e., most similar classes first—as computed by Algorithm 2.
假设T现在是一个包含类C1、C2、…,Cn的列表,它们比m当前所在的类C更类似于m,就如算法1计算出来的那样。假设T中的类根据与m的相似性按降序排列,即最相似的类排在最前方,就如算法2计算的那样。
To reduce the chances of false positives, a move recommendation is not created when: (i) T has less than three classes, and (ii) the difference between the similarity coefficient value of C1 (the first class in the list) and C (the original class of m) is less than
or equal to 25%. In such cases, we consider that the difference between the dependencies established by C1 and C is not discrepant enough to recommend a move operation.
为了减少误报的几率,当(i)T少于三个类,以及(ii)C1(列表中排在最前方的类,即与m相似度最高的类)和C(m的原始类)的相似系数值之间的差异小于或等于25%时,不创建移动建议。在这种情况下,我们认为由C1和C建立的依赖关系之间的差异并不足以推荐一个移动操作。
On the other hand, when such conditions do not hold, a recommendation move(m, Ci) is created for the first class Ci ∈ T that satisfies the preconditions of the Move Method refactoring (1 ≤ i ≤ n). Basically, as usual in the case of refactorings (Opdyke, 1992; Fowler, 1999), a Move Method has its application conditioned by a set of preconditions, fundamentally to ensure that the program’s behavior is preserved after the refactoring. For example, the target class Ci should not contain a method with the same signature of method m. When such preconditions are not satisfied by a pair (C, Ci), we automatically verify the next pair (C,Ci+1). No recommendation is returned when the refactoring preconditions fail for all pair of classes in T.
另一方面,当这些造成误报的条件不成立时,就会为列表T中符合Move Method重构前提条件的首个类Ci生成一个移动推荐move(m,Ci)。基本上,就像重构的情况一样(Opdyke,1992;Fowler,1999),一个Move Method的应用有一组前提条件,从根本上来讲,这是为了确保程序的行为在重构后得到保留。例如,目标类Ci不应该包含与方法m具有相同签名的方法。当一对(C,Ci)不满足这些前提条件时,我们自动验证下一对(C,Ci+1)。当T中没有类满足重构前提条件时,不返回任何建议。
We currently rely on preconditions of the Move Method automatic refactoring engine provided by the Eclipse IDE. However, it is well-known that Eclipse implements weak preconditions for some refactorings (Steimann and Thies, 2009; Schäefer and de Moor, 2010; Soares et al., 2013). For this reason, we strengthened the Eclipse preconditions by supporting the following five preconditions originally proposed by Tsantalis et al. (Tsantalis and Chatzigeorgiou, 2009):
我们目前依赖于Eclipse IDE提供的Move Method自动重构引擎中提出的关于方法移动的前提条件。然而,众所周知,Eclipse为某些重构实现的是弱前提条件(Steimann and Thies, 2009; Schäefer and de Moor, 2010; Soares et al., 2013)。因此,我们通过支持以下由Tsantalis提出的五个前提条件,弥补了Eclipse提供的前提条件的不足。(Tsantalis and Chatzigeorgiou, 2009):

• The target class should not inherit a method having the same signature of the moved method.
• The method to be moved should not override an inherited method in its original class.
• The method to be moved should not be synchronized.
• The method to be moved should not contain assignments to its original class fields (including inherited fields).
• The method to be moved should have a one-to-one relationship with the target class.
• 目标类不应该继承具有与被移动方法相同签名的方法。
• 要移动的方法不应该覆盖其原始类中的已继承的方法。
• 要移动的方法不应该是synchronized的。
• 要移动的方法不应该包含对其原始类字段(包括继承得来的字段)的空间分配。
• 要移动的方法应该与目标类有一对一的关系。

3.4. Threshold calibration

As stated in the previous sections, JMove relies on two thresholds to reduce the number of false positives: (i) A move recommendation is not created for methods whose number of dependencies is less than four; (ii) a move recommendation is not created when the number of candidate classes is less than three and the difference between the similarity coefficient value of C1 (the top recommended class) and C (the original class where the method is) is less than 25%.
如前几节所述,JMove依赖于两个阈值来减少假阳性的数量:(i)对于一个依赖少于四个的方法,移动推荐将不会被创建;(ii)当候选类少于三个,或C1(最推荐的类)和C(方法原来所在的类)与待移动方法的相似度系数的差异小于25%时,移动推荐将不会被创建。
We defined these thresholds after a preliminary empirical assessment using JHotDraw, an open-source system with a stable and well-documented architecture. Our primary assumption for using JHotDraw in this calibration is that most JHotDraw’s methods are likely to be in their proper classes, since JHotDraw is developed and maintained by a small number of expert developers. Therefore, the rationale behind our calibration experiment is to set the thresholds up with the less restrictive values that recommend fewer recommendations.
我们在使用JHotDraw进行初步的经验评估后定义了这些阈值,JHotDraw是一个开源系统,具有稳定和良好文档化的架构。我们在此校准中使用JHotDraw的主要假设是,大多数JHotDraw的方法很可能在其适当的类中,因为JHotDraw是由少数专家开发人员开发和维护的。因此,我们的校准实验背后的基本原理是用造成限制较少的值来设置阈值,推荐更少的建议。
Number of dependencies: We ran JMove in the JHotDraw system, switching the minimum number of dependencies a method
must have to be analyzed. Table 1 reports the results. We chose less than four dependencies because this configuration provides a small number of recommendations (15) but at the same time the number of methods analyzed is still representative (2171).
依赖关系的数量:我们在JHotDraw系统中运行JMove,切换用于分析的方法所具有的依赖关系的最小数量。表1展示了这些结果。我们选择了少于4个依赖关系,因为这种配置提供了少量的建议(15),但同时所分析的方法的数量仍然具有代表性(2171)。
在这里插入图片描述
Other thresholds: We re-ran JMove in the JHotDraw system, switching the minimum number of candidate classes as well as the
minimum difference between C1 (the top recommended class) and C (the original class where the method is). In this test, we only consider methods with at least four dependencies (as concluded in the previous calibration). Fig. 2 reports the results. First, it is important to highlight the importance of threshold W. The number of recommendations drops from 15 to 9 recommendations when we enable this threshold, setting its value as 25% or 50%. Moreover, threshold C has also a positive impact in the results. When it is disabled (C < 0), we always have the highest number of recommendations (15 recommendations).Therefore, we decided to set these thresholds as follows: less than three candidates (threshold C) and the difference less than 25% (threshold W) since it is the less restrictive pair value (C, W) that achieves the minimal number of recommendations in JHotDraw (nine recommendations).
其他阈值:我们在JHotDraw系统中重新运行JMove,切换候选类的最小数量,以及C1(最推荐的类)和C(方法所在的原始类)之间的最小差异。在这个测试中,我们只考虑至少有四种依赖关系的方法(如之前校准中的结论)。报告结果如图2所示。首先,强调阈值W的重要性很重要。当我们启用这个阈值并将其值设置为25%或50%时,建议的数量从15个减少到9个。此外,阈值C对结果也有积极的影响。当它被禁用时(C < 0),我们总能得到最多的建议(15个建议)。因此,我们决定将这些阈值设置为:小于3个候选值(阈值C),差异小于25%(阈值W),因为这是能达到在JHotDraw中得到最小推荐数量(9个建议)这一目标的限制最少的对值(C,W)。

3.5. Tool support

We implemented a prototype tool, called JMove, that supports our approach. Basically, JMove is an Eclipse plug-in that
implements Algorithms 1 and 2. Fig. 3 illustrates the tool’s interface using our previous running example, where method getAllCustomers from the persistence layer was purposely implemented in class CustomerView. As can be noticed, JMove adds a report panel to the IDE, which is used to display the Move Method recommendations.
我们实现了一个名为JMove的原型工具,它支持我们的方法。基本上,JMove是一个实现算法1和算法2的Eclipse插件。图3使用我们之前运行的示例说明了该工具的接口,其中方法从持久性层获取all客户是故意在类客户视图中实现的。可以注意到,JMove向IDE添加了一个报告面板,用于显示Move Method建议。
在这里插入图片描述
Fig. 4 illustrates the main modules from JMove’s architecture. First, module Dependency Set Extraction is used to extract the dependency sets that characterize the methods in our approach. Second, module Similarity Measurement implements Algorithms 1 and 2. Third, module Recommender System implements function best_class(m, T).
图4显示了JMove架构中的主要模块。首先,使用依赖集模块提取来提取我们方法中方法的依赖集。第二,相似度度量模块实现了算法1和算法2。第三,推荐系统模块实现了函数best_class(m,T)。
在这里插入图片描述
3.6. Examples

In this section, we present four examples of Move Method refactorings suggested in JHotDraw by JMove and two state-of the-art tools—JDeodorant and inCode—we previously introduced in Sections 2.1 and 2.2.
在本节中,我们将介绍JMove以及两个最先进的工具jdeodorant和inCode在JHotDraw中建议的四个Move Method重构的例子。我们之前在第2.1和2.2节中介绍过jdeodorant和inCode。

Example #1: Code 1 shows our first example in which method calculateLayout2—a large method moved from class LocatorLayouter—does not access any service from its class AttributeKey. As a result, the dependency set of calculateLayout2 is very different from the dependency sets of the other methods in AttributeKey, as follows:
示例 #1:代码1显示了我们的第一个示例,在这个示例中,calculateLayout2——一个从LocatorLayouter类移动过来的大型方法——不从它所在的类AttributeKey访问任何服务。因此,calculateLayout2的依赖集与AttributeKey中其他方法的依赖集有很大的不同,如下所示:
Similarity(calculateLayout2, AttributeKey) = 0.03
In fact, this method is more similar to the methods in class LocatorLayouter. To illustrate, we report the similarity between calculateLayout2 and the three methods in LocatorLayouter:
实际上,这个方法更类似于LocatorLayouter类中的方法。为了说明这一点,我们列出了calculateLayout2和LocatorLayouter中的三种方法之间的相似性:
meth_sim(calculateLayout2, layout) = 1.00
meth_sim(calculateLayout2, calculateLayout) = 0.5
meth_sim(calculateLayout2, getLocator) = 0.43
As result, we have that
因此,我们有如下结果:
Similarity(calculateLayout2, LocatorLayouter) = 0.64

Due to this high similarity, JMove correctly recommends moving calculateLayout2 back to its original class LocatorLayouter. JDeodorant does not make a recommendation to move this method back. Basically, in the case of getter methods, as the getLocator call in line 6, JDeodorant considers that the method envies not the target object type (LocatorLayouter) but the type returned by the call (Locator). However, it is not possible to move calculateLayout2 to Locator because the refactoring preconditions fail in this particular case. Finally, inCode also fails in suggesting to move calculateLayout2 because the ATFD
(Access to Foreign Data) metric considers only accesses to external fields, e.g., direct access to fields from external classes or via getter methods. In calculateLayout2, nonetheless, only methods from the method’s own class (LocatorLayouter) are called.
由于这种高度相似性,JMove正确地建议将calculateLayout2移回原来的LocatorLayouter类。JDeodorant没有建议将此方法移回去。基本上,对于getter方法,正如第6行中对getLocator的调用一样,JDeodorant认为该方法羡慕的不是目标对象类型(LocatorLayouter),而是调用的方法返回的类型(Locator)。但是,不可能将calculateLayout2移动到Locator,因为这种特殊情况不符合重构前提条件。最后,inCode也没有建议移动calculateLayout2,因为ATFD(Access to Foreign Data,访问外部数据)度量只考虑对外部字段的访问,例如,通过外部类或通过getter方法来访问字段。尽管如此,在calculateLayout2中,只调用来自该方法自己的类(LocatorLayouter)的方法。
在这里插入图片描述

Example #2: Code 2 shows the second example discussed here. Similar to the previous example, method fireAreaInvalidated2 does not access any service from class DrawingEditorProxy. However, it calls three methods from AbstractTool (lines 4–6) and the Move Method preconditions are satisfied. For this reason, JDeodorant infers that AbstractTool is the most suitable class for the method. JMove also suggests to move fireAreaInvalidated2 back to AbstractTool because the method is more similar to this class than to its current class, as indicated by the similarity function results:
示例#2:代码2显示了这里讨论的第二个示例。与前面的示例类似,方法fireAreaInvalidated2不会从 DrawingEditorProxy类访问任何服务。但是,它从AbstractTool类中调用了三个方法(第4-6行),并且满足了Move Method的先决条件。因此,JDeodorant推断出AbstractTool是最适合该方法的类。JMove也建议将其移回AbstractTool,因为该方法更类似于这个类而不是当前的类。相似性函数计算结果如下所示:
Similarity(f ireAreaInvalidated2, DrawingEditorProxy) = 0.03
Similarity(f ireAreaInvalidated2, AbstractTool) = 0.17
在这里插入图片描述

Example #3: Code 3 shows an example in which all tools successfully recommend moving a method to its original class. As in the previous examples, method setEditor—moved from SVGDrawingPanel—does not access any method or field from its current class ViewToolBar. However, the method accesses 13 different attributes from class SVGDrawingPanel.
示例#3:代码3显示了一个示例,其中所有工具都成功地建议将一个方法移动到它的原始类中。与前面的示例一样,从SVGDrawingPanel类中移动而来的方法setEditor不会从其当前类ViewToolBar中访问任何方法或字段。然而,该方法从SVGDrawingPanel类中访问13个不同的属性。
For JDeodorant, a method m envies a class C’ when m accesses more attributes and methods from C’ than from its own class. Therefore, JDeodorant correctly infers that class SVGDrawingPanel is the most suitable class for the method. inCode also successfully identified setEditor as a misplaced method. Particularly, the three rules that compose the detection strategy described in Section 2.2 are satisfied in this case: (i) The method accesses 13 different attributes from the external class SVGDrawingPanel; (ii) the method does not access any service from its current class; and (iii) only attributes of class
SVGDrawingPanel are accessed by the method. JMove also suggests to move setEditor back to SVGDrawingPanel because the method is more similar to SVGDrawingPanel than to any other class in the system.
对于JDeoderant,当m访问来自C’的类的属性和方法时,方法m“羡慕”类C’。因此,JDeodorant正确地推断出SVGDrawingPanel是最适合该方法的类。inCode也成功地将setEditor识别为一个错误的方法。特别地,在这种情况下,满足了构成第2.2节中描述的检测策略的三个规则:(i)该方法从外部类SVGDrawingPanel访问了13个不同的属性;(ii)该方法不从其当前类访问任何服务;和(iii)该方法仅访问了SVGDrawingPanel类的属性。JMove也建议将setEditor移回SVGDrawingPanel,因为该方法更类似于SVGDrawingPanel,而不是系统中的任何其他类。
在这里插入图片描述

Example #4: In Code 4, method loadDrawing does not access any service from its new class ProgressIndicator. However, it calls four methods from its original class SVGApplet (lines 3–5) and the Move Method preconditions are satisfied. For this reason, JDeodorant correctly infers that SVGApplet is the most suitable class for the method. inCode fails in recommending to move loadDrawing because it only calls methods (not fields) from SVGApplet. Finally, JMove also fails because the method is not similar in terms of dependencies to the other methods in SVGApplet. Due to its specific task of loading a Drawing, the dependency set of the method contains many particular types, such as URL (line 5), URLConnection (line 6), BufferedInputStream (line 10), and IOException (line 12). For this reason, it has a low similarity to its original class:
示例#4:在代码4中,loadDrawing方法不会从其新类ProgressIndicator访问任何服务。但是,它从其原始的类SVGApplet中调用了4个方法(第3-5行),并且满足了Move Method的先决条件。因此,JDeodorant正确地推断出SVGApplet是最适合该方法的类。inCode无法建议移动loadDrawing,因为它只调用SVGApplet中的方法(而不是字段)。最后,JMove也失败了,因为该方法在依赖性方面与SVGApplet中的其他方法的依赖性并不相似。由于其加载图形的特定任务,该方法的依赖集包含许多特定类型,如URL(第5行)、URLConnection(第6行)、BufferedInputStream(第10行)和IOExcenit(第12行)。因此,它与原来的类的相似性很低:
Similarity(loadDrawing, SVGApplet) = 0.07
在这里插入图片描述

3.7. Limitations

JMove does not provide recommendations for methods that have less than four dependencies and for methods that are the single methods in their classes (as explained in Section 3.2). Furthermore, we do not recommend to move methods that do not attend the refactoring preconditions. This decision is based on the fact that the moving operation, in this case, typically requires a more complex restructuring both in the source and in the target classes. Finally, we do not provide suggestions to move fields since it is rare to observe fields declared in incorrect classes (Tsantalis and Chatzigeorgiou, 2009).
JMove没有为依赖关系少于4个的方法和在其类中是单个方法的方法提供建议(如第3.2节所述)。此外,我们不建议移动不涉及重构先决条件的方法。此决定是基于这样一个事实:在此情况下,移动操作通常需要在源类和目标类中进行更复杂的重组。最后,我们没有提供移动字段的建议,因为很少观察到在不正确的类中声明的字段(Tsantalis and Chatzigeorgiou, 2009)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值