Duplicated code (also known as code clones) can be a potential big
trouble for the maintenance of your project. Not all clones are harmful [1] or
equally harmful [2]. However, if you find yourself repeatedly applying the same
changes (e.g., bug fix) in multiple places in your code, you should definitely
consider to refactor [3] this duplication. Merging such clones into a single
copy will make future maintenance faster and less error-prone.

Why is tool support necessary for
the refactoring of clones?

Software clones tend to diverge after the initial copy-and-paste. This
happens because developers have to adjust the copied code to a new context
and/or different requirements. Therefore, clones tend to have non-trivial
differences as the project evolves (e.g., different methods being called, or completely
different logic in parts of the implemented algorithm). Unfortunately, the
current state-of-the-art IDEs support the refactoring of clones with trivial
differences (i.e., identical clones with variations in whitespace, layout,
comments, and variable identifiers).

JDeodorant [4] is an Eclipse plugin
that can help developers to inspect the differences between clones in Java
projects, and refactor them safely, if possible. More specifically, JDeodorant
applies a sophisticated static source code analysis to examine whether the
parameterization of the differences appearing in the clones is free of side effects. We refer to this feature
as refactorability analysis [5]. If
all examined preconditions pass successfully, JDeodorant can proceed with the
refactoring of the clones.

Feature 1: Clone import and clone
group exploration

JDeodorant can import results from 5 popular clone detection tools, namely CCFinder, ConQAT, NiCad, Deckard, and CloneDR. In addition, JDeodorant can analyze any pair of methods selected by the developer from the Eclipse Package Explorer view.

While importing the results, JDeodorant automatically checks the syntactic correctness of the clone fragments, and fixes any discrepancies by removing incomplete statements and adding the missing closing brackets from incomplete blocks of code. Additionally, the tool filters out the clones that extend beyond the body of a method (i.e., class-level clones).

The imported results are presented to the user in a tree-like view, as shown in Figure 1. The clones are organized into groups based on their similarity (i.e., a clone group contains two or more clone instances).

The clone groups are also analyzed to discover subclone relationships between them. Group A is a subclone of group B, if every clone instance in A is a sub-clone (i.e., a partial code fragment) of an instance in B. The subclone information appears as a link in the last column of the clone group table to help the user navigate between clone groups having such a relationship.

By clicking on the “Show only clone groups for the files opened in the editor” checkbox, the user can filter the clone groups table to display only the clones being relevant to the context (i.e., appearing in the files) he/she is currently working on.

All clones are constantly monitored for modifications. If the developer refactors or updates some code associated with the imported clones, the clone group table is automatically updated by disabling the clones affected by the modification (disabled clones appear with strikethrough text), and by re-computing the offsets of other clones belonging to the same modified Java files (shifted clones appear with text highlighted in green). In this way, the user can continue with the inspection and refactoring of other clone groups without having to import new results from external tools.

Figure 1: Presentation of the imported clone
detection results to the user

Feature 2: Clone visualization and
refactorability analysis

The user can right-click on any pair of clones from the same clone
group, or any pair of methods from the Eclipse Package Explorer and select
“Refactor Duplicated Code…” from the popup menu. The outcome of the clone pair
analysis is presented to the user as shown in Figure 2.

Figure 2: Clone pair visualization and refactorability
analysis

The analyzed clone fragments appear as two side-by-side trees, where
each pair of tree nodes in the same row represents a pair of mapped statements
in the first and second clone fragment, respectively. The user can inspect the
clones in a synchronized manner, by expanding and collapsing the nodes
corresponding to control statements (i.e., loops, conditionals, try blocks).
The code is highlighted in 3 different colors to help the developer inspect and
understand the differences between the clones.

Yellow: Represents differences in expressions between matched statements. These expressions are evaluated to the same type, but have a different syntactic structure or identifier.

Red: Represents unmapped statements that do not have a matching statement in the other clone fragment (also known as clone gaps).

Green: Represents semantically equivalent statements, i.e., statements of different AST types performing exactly the same functionality. In Figure 2, we can see a for loop in the left clone matched with a while loop in the right clone having the same initializer and updater as separate statements.

By hovering over a pair of statements highlighted in yellow, a tooltip
appears providing semantic information about the type of each difference based
on the program elements (e.g., variables, method calls, literals, class instantiations)
appearing in the difference. Currently, JDeodorant supports over 20 difference
types, including some more advanced ones, such as the replacement of a direct field
access with the corresponding getter
method call, and the replacement of a direct field assignment with the
corresponding setter method call. In
addition, the tooltip may also include information about precondition violations, if the expressions appearing in the
differences cannot be safely parameterized.

Semantically equivalent differences, and renamed variables are not
examined against preconditions, since they should not be parameterized. JDeodorant
automatically detects the local variables that have been consistently renamed between the clone fragments (as shown in the
bottom-right side of Figure 2).

Feature 3: Clone refactoring

Based on the location of the clones, JDeodorant
determines automatically the best refactoring strategy:

1.Extract
Method (clones belong to the same Java file)

2.Extract
and Pull Up Method (clones have a common superclass)

a)Introduce Template Method (clones
call local methods from the subclasses)

b)Extract Superclass (clones have an external
common superclass, or the common superclass has additional subclasses)

As shown in Figure 3,
JDeodorant can generate a detailed preview
of the refactoring to be applied, where the developer can inspect all the
changes that will take place at a fine-grained level. Finally, the user can undo and redo the applied refactorings, since they are recorded in the
change history of Eclipse.