1 \documentclass[USenglish]{ifimaster}
3 \usepackage[utf8]{inputenc}
4 \usepackage[T1]{fontenc,url}
6 \usepackage{babel,textcomp,csquotes,ifimasterforside,varioref,graphicx}
7 \usepackage[style=numeric-comp,backend=bibtex]{biblatex}
11 \usepackage{perpage} %the perpage package
12 \MakePerPage{footnote} %the perpage package command
15 \newtheorem*{wordDef}{Definition}
17 \newcommand{\definition}[1]{\begin{wordDef}#1\end{wordDef}}
18 \newcommand{\see}[1]{(see \ref{#1})}
19 \newcommand{\explanation}[3]{\noindent\textbf{\textit{#1}}\\*\emph{When:}
20 #2\\*\emph{How:} #3\\*[-7px]}
21 \newcommand{\type}[1]{\texttt{#1}}
22 \newcommand{\typeref}[1]{\footnote{\type{#1}}}
23 \newcommand{\typewithref}[2]{\type{#2}\typeref{#1.#2}}
24 \newcommand{\method}[1]{\type{#1}}
25 \newcommand{\methodref}[2]{\footnote{\type{#1}\method{\##2()}}}
26 \newcommand{\methodwithref}[2]{\method{#2}\footnote{\type{#1}\method{\##2()}}}
30 \subtitle{An unfinished essay}
31 \author{Erlend Kristiansen}
33 \bibliography{bibliography/master-thesis-erlenkr-bibliography}
51 \chapter{Introduction}
53 \section{What is Refactoring?}
55 This question is best answered dividing the answer into two parts. First
56 defining the concept of a refactoring, then discuss what the discipline of
57 refactoring is all about. And to make it clear already from the beginning: The
58 discussions in this report must be seen in the context of object oriented
59 programming languages. All though the techniques discussed may be applicable to
60 languages from other paradigms, they will not be the subject of this report.
62 \subsection{Defining refactoring}
63 Martin Fowler, in his masterpiece on refactoring \cite{refactoring}, defines a
64 refactoring like this:
66 \emph{Refactoring} (noun): a change made to the \todo{what does he mean by
67 internal?} internal structure of software to make it easier to understand and
68 cheaper to modify without changing its observable
69 behavior.~\cite{refactoring} % page 53
71 This definition assign additional meaning to the word \emph{refactoring}, beyond
72 the composition of the prefix \emph{re-}, usually meaning something like
73 ``again'' or ``anew'', and the word \emph{factoring}, that can mean to determine
74 the \emph{factors} of something. Where a \emph{factor} would be close to the
75 mathematical definition of something that divides a quantity, without leaving a
76 remainder. Fowler is mixing the \emph{motivation} behind refactoring into his
77 definition. Instead it could be made clean, only considering the mechanical and
78 behavioral aspects of refactoring. That is to factor the program again, putting
79 it together in a different way than before, while preserving the behavior of the
80 program. An alternative definition could then be:
82 \definition{A refactoring is a transformation
83 done to a program without altering its external behavior.}
85 From this we can conclude that a refactoring primarily changes how the
86 \emph{code} of a program is perceived by the \emph{programmer}, and not the
87 behavior experienced by any user of the program. Although the logical meaning is
88 preserved, such changes could potentially alter the program's behavior when it
89 comes to performance gain or -penalties. So any logic depending on the
90 performance of a program could make the program behave differently after a
93 In the extreme case one could argue that such a thing as \emph{software
94 obfuscation} is to refactor. If we where to define it as a refactoring, it could
95 be defined as a composite refactoring \see{intro_composite}, consisting of, for
96 instance, a series of rename refactorings. (But it could of course be much more
97 complex, and the mechanics of it would not exactly be carved in stone.) To
98 perform some serious obfuscation one would also take advantage of techniques not
99 found among established refactorings, such as removing whitespace. This might
100 not even generate a different syntax tree for languages not sensitive to
101 whitespace, placing it in the gray area of what kind of transformations is to be
102 considered refactorings.
104 Finally, to \emph{refactor} is (quoting Martin Fowler)
106 \ldots to restructure software by applying a series of refactorings without
107 changing its observable behavior.~\cite{refactoring} % page 54, definition
110 \todo{subsection with the history of refactoring?}
112 \subsection{Motivation}\todo{better headline?}
113 To get a grasp of what refactoring is all about, we can answer this question:
114 \emph{Why do people refactor?} Possible answers could include: ``To remove
115 duplication'' or ``to break up long methods''. Practitioners of the art of
116 Design Patterns~\cite{dp} could say that they do it to introduce a long-needed
117 pattern into their program's design. So it's safe to say that peoples'
118 intentions are to make their programs \emph{better} in some sense. But what
119 aspects of the programs are becoming improved?
121 As already mentioned, people often refactor to get rid of duplication. Moving
122 identical or similar code into methods, and maybe pushing those up or down in
123 their class hierarchies. Making template methods for overlapping algorithms
124 \todo{better?: functionality} and so on. It's all about gathering what belongs
125 together and putting it all in one place. And the result? The code is easier to
126 maintain. When removing the implicit coupling between the code snippets, the
127 location of a bug is limited to only one place, and new functionality need only
128 to be added this one place, instead of a number of places people might not even
131 The same people find out that their program contains a lot of long and
132 hard-to-grasp methods. Then what do they do? They begin dividing their methods
133 into smaller ones, using the \emph{Extract Method}
134 refactoring~\cite{refactoring}. Then they may discover something about their
135 program that they weren't aware of before; revealing bugs they didn't know about
136 or couldn't find due to the complex structure of their program. \todo{Proof?}
137 Making the methods smaller and giving good names to the new ones clarifies the
138 algorithms and enhances the \emph{understandability} of the program. This makes
139 simple refactoring an excellent method for exploring unknown program code, or
140 code that you had forgotten that you wrote!
142 The word \emph{simple} came up in the last section. In fact, most basic
143 refactorings are simple. The true power of them are revealed first when they are
144 combined into larger --- higher level --- refactorings, called \emph{composite
145 refactorings} \see{intro_composite}. Often the goal of such a series of
146 refactorings is a design pattern. Thus the \emph{design} can be evolved
147 throughout the lifetime of a program, opposed to designing up-front. It's all
148 about being structured and taking small steps to improve the design.
150 Many refactorings are aimed at lowering the coupling between different classes
151 and different layers of logic. Say for instance that the coupling between the
152 user interface and the business logic of a program is lowered. Then the business
153 logic of the program could much easier be the target of automated tests,
154 increasing the productivity in the software development process. It is also
155 easier to distribute (e.g. between computers) the different components of a
156 program if they are sufficiently decoupled.
158 Another effect of refactoring is that with the increased separation of concerns
159 coming out of many refactorings, the \emph{performance} is improved. When
160 profiling programs, the problem parts are narrowed down to smaller parts of the
161 code, which are easier to tune, and optimization can be performed only where
162 needed and in a more effective way.
164 Refactoring program code --- with a goal in mind --- can give the code itself
165 more value. That is in the form of robustness to bugs, understandability and
166 maintainability. With the first as an obvious advantage, but with the following
167 two being also very important for software development. By incorporating
168 refactoring in the development process, bugs are found faster, new functionality
169 is added more easily and code is easier to understand by the next person exposed
170 to it, which might as well be the person who wrote it. The consequence of this,
171 is that refactoring can increase the average productivity of the development
172 process, and thus also add to the monetary value of a business in the long run.
173 Where this last point also should open the eyes of some nearsighted managers who
174 seldom see beyond the next milestone.
176 \subsection{The etymology of refactoring}
180 \section{Classification of refactorings}
181 % only interesting refactorings
182 % with 2 detailed examples? One for structured and one for intra-method?
183 % Is replacing Bubblesort with Quick Sort considered a refactoring?
185 \subsection{Structural refactorings}
187 \subsubsection{Basic refactorings}
190 \explanation{Extract Method}{You have a code fragment that can be grouped
191 together.}{Turn the fragment into a method whose name explains the purpose of
194 \explanation{Inline Method}{A method's body is just as clear as its name.}{Put
195 the method's body into the body of its callers and remove the method.}
197 \explanation{Inline Temp}{You have a temp that is assigned to once with a simple
198 expression, and the temp is getting in the way of other refactorings.}{Replace
199 all references to that temp with the expression}
201 % Moving Features Between Objects
202 \explanation{Move Method}{A method is, or will be, using or used by more
203 features of another class than the class on which it is defined.}{Create a new
204 method with a similar body in the class it uses most. Either turn the old method
205 into a simple delegation, or remove it altogether.}
207 \explanation{Move Field}{A field is, or will be, used by another class more than
208 the class on which it is defined}{Create a new field in the target class, and
209 change all its users.}
212 \explanation{Replace Magic Number with Symbolic Constant}{You have a literal
213 number with a particular meaning.}{Create a constant, name it after the meaning,
214 and replace the number with it.}
216 \explanation{Encapsulate Field}{There is a public field.}{Make it private and
219 \explanation{Replace Type Code with Class}{A class has a numeric type code that
220 does not affect its behavior.}{Replace the number with a new class.}
222 \explanation{Replace Type Code with Subclasses}{You have an immutable type code
223 that affects the behavior of a class.}{Replace the type code with subclasses.}
225 \explanation{Replace Type Code with State/Strategy}{You have a type code that
226 affects the behavior of a class, but you cannot use subclassing.}{Replace the
227 type code with a state object.}
229 % Simplifying Conditional Expressions
230 \explanation{Consolidate Duplicate Conditional Fragments}{The same fragment of
231 code is in all branches of a conditional expression.}{Move it outside of the
234 \explanation{Remove Control Flag}{You have a variable that is acting as a
235 control flag fro a series of boolean expressions.}{Use a break or return
238 \explanation{Replace Nested Conditional with Guard Clauses}{A method has
239 conditional behavior that does not make clear the normal path of
240 execution.}{Use guard clauses for all special cases.}
242 \explanation{Introduce Null Object}{You have repeated checks for a null
243 value.}{Replace the null value with a null object.}
245 \explanation{Introduce Assertion}{A section of code assumes something about the
246 state of the program.}{Make the assumption explicit with an assertion.}
248 % Making Method Calls Simpler
249 \explanation{Rename Method}{The name of a method does not reveal its
250 purpose.}{Change the name of the method}
252 \explanation{Add Parameter}{A method needs more information from its
253 caller.}{Add a parameter for an object that can pass on this information.}
255 \explanation{Remove Parameter}{A parameter is no longer used by the method
258 %\explanation{Parameterize Method}{Several methods do similar things but with
259 %different values contained in the method.}{Create one method that uses a
260 %parameter for the different values.}
262 \explanation{Preserve Whole Object}{You are getting several values from an
263 object and passing these values as parameters in a method call.}{Send the whole
266 \explanation{Remove Setting Method}{A field should be set at creation time and
267 never altered.}{Remove any setting method for that field.}
269 \explanation{Hide Method}{A method is not used by any other class.}{Make the
272 \explanation{Replace Constructor with Factory Method}{You want to do more than
273 simple construction when you create an object}{Replace the constructor with a
276 % Dealing with Generalization
277 \explanation{Pull Up Field}{Two subclasses have the same field.}{Move the field
280 \explanation{Pull Up Method}{You have methods with identical results on
281 subclasses.}{Move them to the superclass.}
283 \explanation{Push Down Method}{Behavior on a superclass is relevant only for
284 some of its subclasses.}{Move it to those subclasses.}
286 \explanation{Push Down Field}{A field is used only by some subclasses.}{Move the
287 field to those subclasses}
289 \explanation{Extract Interface}{Several clients use the same subset of a class's
290 interface, or two classes have part of their interfaces in common.}{Extract the
291 subset into an interface.}
293 \explanation{Replace Inheritance with Delegation}{A subclass uses only part of a
294 superclasses interface or does not want to inherit data.}{Create a field for the
295 superclass, adjust methods to delegate to the superclass, and remove the
298 \explanation{Replace Delegation with Inheritance}{You're using delegation and
299 are often writing many simple delegations for the entire interface}{Make the
300 delegating class a subclass of the delegate.}
302 \subsubsection{Composite refactorings}
305 % \explanation{Replace Method with Method Object}{}{}
307 % Moving Features Between Objects
308 \explanation{Extract Class}{You have one class doing work that should be done by
309 two}{Create a new class and move the relevant fields and methods from the old
310 class into the new class.}
312 \explanation{Inline Class}{A class isn't doing very much.}{Move all its features
313 into another class and delete it.}
315 \explanation{Hide Delegate}{A client is calling a delegate class of an
316 object.}{Create Methods on the server to hide the delegate.}
318 \explanation{Remove Middle Man}{A class is doing to much simple delegation.}{Get
319 the client to call the delegate directly.}
322 \explanation{Replace Data Value with Object}{You have a data item that needs
323 additional data or behavior.}{Turn the data item into an object.}
325 \explanation{Change Value to Reference}{You have a class with many equal
326 instances that you want to replace with a single object.}{Turn the object into a
329 \explanation{Encapsulate Collection}{A method returns a collection}{Make it
330 return a read-only view and provide add/remove methods.}
332 % \explanation{Replace Array with Object}{}{}
334 \explanation{Replace Subclass with Fields}{You have subclasses that vary only in
335 methods that return constant data.}{Change the methods to superclass fields and
336 eliminate the subclasses.}
338 % Simplifying Conditional Expressions
339 \explanation{Decompose Conditional}{You have a complicated conditional
340 (if-then-else) statement.}{Extract methods from the condition, then part, an
343 \explanation{Consolidate Conditional Expression}{You have a sequence of
344 conditional tests with the same result.}{Combine them into a single conditional
345 expression and extract it.}
347 \explanation{Replace Conditional with Polymorphism}{You have a conditional that
348 chooses different behavior depending on the type of an object.}{Move each leg
349 of the conditional to an overriding method in a subclass. Make the original
352 % Making Method Calls Simpler
353 \explanation{Replace Parameter with Method}{An object invokes a method, then
354 passes the result as a parameter for a method. The receiver can also invoke this
355 method.}{Remove the parameter and let the receiver invoke the method.}
357 \explanation{Introduce Parameter Object}{You have a group of parameters that
358 naturally go together.}{Replace them with an object.}
360 % Dealing with Generalization
361 \explanation{Extract Subclass}{A class has features that are used only in some
362 instances.}{Create a subclass for that subset of features.}
364 \explanation{Extract Superclass}{You have two classes with similar
365 features.}{Create a superclass and move the common features to the
368 \explanation{Collapse Hierarchy}{A superclass and subclass are not very
369 different.}{Merge them together.}
371 \explanation{Form Template Method}{You have two methods in subclasses that
372 perform similar steps in the same order, yet the steps are different.}{Get the
373 steps into methods with the same signature, so that the original methods become
374 the same. Then you can pull them up.}
377 \subsection{Functional refactorings}
379 \explanation{Substitute Algorithm}{You want to replace an algorithm with one
380 that is clearer.}{Replace the body of the method with the new algorithm.}
384 \section{The impact on software quality}
386 \subsection{What is meant by quality?}
387 The term \emph{software quality} has many meanings. It all depends on the
388 context we put it in. If we look at it with the eyes of a software developer, it
389 usually mean that the software is easily maintainable and testable, or in other
390 words, that it is \emph{well designed}. This often correlates with the
391 management scale, where \emph{keeping the schedule} and \emph{customer
392 satisfaction} is at the center. From the customers point of view, in addition to
393 good usability, \emph{performance} and \emph{lack of bugs} is always
394 appreciated, measurements that are also shared by the software developer. (In
395 addition, such things as good documentation could be measured, but this is out
396 of the scope of this document.)
398 \subsection{The impact on performance}
400 Refactoring certainly will make software go more slowly, but it also makes the
401 software more amenable to performance tuning.~\cite{refactoring} % page 69
403 There is a common belief that refactoring compromises performance, due to
404 increased degree of indirection and that polymorphism is slower than
407 In a survey, Demeyer~\cite{demeyer2002} disproves this view in the case of
408 polymorphism. He is doing an experiment on, what he calls, ``Transform Self Type
409 Checks'' where you introduce a new polymorphic method and a new class hierarchy
410 to get rid of a class' type checking of a ``type attribute``. He uses this kind
411 of transformation to represent other ways of replacing conditionals with
412 polymorphism as well. The experiment is performed on the C++ programming
413 language and with three different compilers and platforms. \todo{But is the
414 result better?} Demeyer concludes that, with compiler optimization turned on,
415 polymorphism beats middle to large sized if-statements and does as well as
416 case-statements. (In accordance with his hypothesis, due to similarities
417 between the way C++ handles polymorphism and case-statements.)
419 The interesting thing about performance is that if you analyze most programs,
420 you find that they waste most of their time in a small fraction of the code.
423 So, although an increased amount of method calls could potentially slow down
424 programs, one should avoid premature optimization and sacrificing good design,
425 leaving the performance tuning until after profiling the software and having
426 isolated the actual problem areas.
430 \section{Correctness of refactorings}
433 \section{Composite refactorings} \label{intro_composite}
434 % motivation, examples
435 % manual vs automated?
436 % what about refactoring in a very large code base?
438 \section{Software metrics}
442 %\chapter{Planning the project}
447 \chapter{Refactorings in Eclipse JDT: Design, Shortcomings and Wishful
448 Thinking}\label{ch:jdt_refactorings}
450 This chapter will deal with some of the design behind refactoring support in
451 Eclipse, and the JDT in specific. After which it will follow a section about
452 shortcomings of the refactoring API in terms of composition of refactorings. The
453 chapter will be concluded with a section telling some of the ways the
454 implementation of refactorings in the JDT could have worked to facilitate
455 composition of refactorings.
458 The refactoring world of Eclipse can in general be separated into two parts: The
459 language independent part and the part written for a specific programming
460 language -- the language that is the target of the supported refactorings.
461 \todo{What about the language specific part?}
463 \subsection{The Language Toolkit}
464 The Language Toolkit, or LTK for short, is the framework that is used to
465 implement refactorings in Eclipse. It is language independent and provides the
466 abstractions of a refactoring and the change it generates, in the form of the
467 classes \typewithref{org.eclipse.ltk.core.refactoring}{Refactoring} and
468 \typewithref{org.eclipse.ltk.core.refactoring}{Change}. (There is also parts of
469 the LTK that is concerned with user interaction, but they will not be discussed
470 here, since they are of little value to us and our use of the framework.)
472 \subsubsection{The Refactoring Class}
473 The abstract class \type{Refactoring} is the core of the LTK framework. Every
474 refactoring that is going to be supported by the LTK have to end up creating an
475 instance of one of its subclasses. The main responsibilities of subclasses of
476 \type{Refactoring} is to implement template methods for condition checking
477 (\methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkInitialConditions}
479 \methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkFinalConditions}),
481 \methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{createChange}
482 method that creates and returns an instance of the \type{Change} class.
484 If the refactoring shall support that others participate in it when it is
485 executed, the refactoring has to be a processor-based
486 refactoring\typeref{org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring}.
487 It then delegates to its given
488 \typewithref{org.eclipse.ltk.core.refactoring.participants}{RefactoringProcessor}
489 for condition checking and change creation.
491 \subsubsection{The Change Class}
492 This class is the base class for objects that is responsible for performing the
493 actual workspace transformations in a refactoring. The main responsibilities for
494 its subclasses is to implement the
495 \methodwithref{org.eclipse.ltk.core.refactoring.Change}{perform} and
496 \methodwithref{org.eclipse.ltk.core.refactoring.Change}{isValid} methods. The
497 \method{isValid} method verifies that the change object is valid and thus can be
498 executed by calling its \method{perform} method. The \method{perform} method
499 performs the desired change and returns an undo change that can be executed to
500 reverse the effect of the transformation done by its originating change object.
502 \subsubsection{Executing a Refactoring}\label{executing_refactoring}
503 The life cycle of a refactoring generally follows two steps after creation:
504 condition checking and change creation. By letting the refactoring object be
506 \typewithref{org.eclipse.ltk.core.refactoring}{CheckConditionsOperation} that
507 in turn is handled by a
508 \typewithref{org.eclipse.ltk.core.refactoring}{CreateChangeOperation}, it is
509 assured that the change creation process is managed in a proper manner.
511 The actual execution of a change object has to follow a detailed life cycle.
512 This life cycle is honored if the \type{CreateChangeOperation} is handled by a
513 \typewithref{org.eclipse.ltk.core.refactoring}{PerformChangeOperation}. If also
514 an undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} is set
515 for the \type{PerformChangeOperation}, the undo change is added into the undo
518 \section{Shortcomings}
519 This section is introduced naturally with a conclusion: The JDT refactoring
520 implementation does not facilitate composition of refactorings.
521 \todo{refine}This section will try to explain why, and also identify other
522 shortcomings of both the usability and the readability of the JDT refactoring
525 I will begin at the end and work my way toward the composition part of this
528 \subsection{Absence of Generics in Eclipse Source Code}
529 This section is not only concerning the JDT refactoring API, but also large
530 quantities of the Eclipse source code. The code shows a striking absence of the
531 Java language feature of generics. It is hard to read a class' interface when
532 methods return objects or takes parameters of raw types such as \type{List} or
533 \type{Map}. This sometimes results in having to read a lot of source code to
534 understand what is going on, instead of relying on the available interfaces. In
535 addition, it results in a lot of ugly code, making the use of typecasting more
536 of a rule than an exception.
538 \subsection{Composite Refactorings Will Not Appear as Atomic Actions}
540 \subsubsection{Missing Flexibility from JDT Refactorings}
541 The JDT refactorings are not made with composition of refactorings in mind. When
542 a JDT refactoring is executed, it assumes that all conditions for it to be
543 applied successfully can be found by reading source files that has been
544 persisted to disk. They can only operate on the actual source material, and not
545 (in-memory) copies thereof. This constitutes a major disadvantage when trying to
546 compose refactorings, since if an exception occur in the middle of a sequence of
547 refactorings, it can leave the project in a state where the composite
548 refactoring was executed only partly. It makes it hard to discard the changes
549 done without monitoring and consulting the undo manager, an approach that is not
552 \subsubsection{Broken Undo History}
553 When designing a composed refactoring that is to be performed as a sequence of
554 refactorings, you would like it to appear as a single change to the workspace.
555 This implies that you would also like to be able to undo all the changes done by
556 the refactoring in a single step. This is not the way it appears when a sequence
557 of JDT refactorings is executed. It leaves the undo history filled up with
558 individual undo actions corresponding to every single JDT refactoring in the
559 sequence. This problem is not trivial to handle in Eclipse. (See section
560 \ref{hacking_undo_history}.)
562 \section{Wishful Thinking}
566 \chapter{Composite Refactorings in Eclipse}
568 \section{A Simple Ad Hoc Model}
569 As pointed out in chapter \ref{ch:jdt_refactorings}, the Eclipse JDT refactoring
570 model is not very well suited for making composite refactorings. Therefore a
571 simple model using changer objects (of type \type{RefaktorChanger}) is used as
572 an abstraction layer on top of the existing Eclipse refactorings.
574 \section{The Extract and Move Method Refactoring}
575 %The Extract and Move Method Refactoring is implemented mainly using these
578 % \item \type{ExtractAndMoveMethodChanger}
579 % \item \type{ExtractAndMoveMethodPrefixesExtractor}
580 % \item \type{Prefix}
581 % \item \type{PrefixSet}
584 \subsection{The Building Blocks}
585 This is a composite refactoring, and hence is built up using several primitive
586 refactorings. These basic building blocks are, as its name implies, the Extract
587 Method Refactoring \cite{refactoring} and the Move Method Refactoring
588 \cite{refactoring}. In Eclipse, the implementations of these refactorings are
590 \typewithref{org.eclipse.jdt.internal.corext.refactoring.code}{ExtractMethodRefactoring}
592 \typewithref{org.eclipse.jdt.internal.corext.refactoring.structure}{MoveInstanceMethodProcessor},
593 where the last class is designed to be used together with the processor-based
594 \typewithref{org.eclipse.ltk.core.refactoring.participants}{MoveRefactoring}.
596 \subsubsection{The ExtractMethodRefactoring Class}
597 This class is quite simple in its use. The only parameters it requires for
598 construction is a compilation
599 unit\typeref{org.eclipse.jdt.core.ICompilationUnit}, the offset into the source
600 code where the extraction shall start, and the length of the source to be
601 extracted. Then you have to set the method name for the new method together with
602 which access modifier that shall be used and some not so interesting parameters.
604 \subsubsection{The MoveInstanceMethodProcessor Class}
605 For the Move Method the processor requires a little more advanced input than
606 the class for the Extract Method. For construction it requires a method
607 handle\typeref{org.eclipse.jdt.core.IMethod} from the Java Model for the method
608 that is to be moved. Then the target for the move have to be supplied as the
609 variable binding from a chosen variable declaration. In addition to this, one
610 have to set some parameters regarding setters/getters and delegation.
612 To make a whole refactoring from the processor, one have to construct a
613 \type{MoveRefactoring} from it.
615 \subsection{The ExtractAndMoveMethodChanger Class}
616 The \typewithref{no.uio.ifi.refaktor.changers}{ExtractAndMoveMethodChanger}
617 class, that is a subclass of the class
618 \typewithref{no.uio.ifi.refaktor.changers}{RefaktorChanger}, is the class
619 responsible for composing the \type{ExtractMethodRefactoring} and the
620 \type{MoveRefactoring}. Its constructor takes a project
621 handle\typeref{org.eclipse.core.resources.IProject}, the method name for the new
622 method and a \typewithref{no.uio.ifi.refaktor.utils}{SmartTextSelection}.
624 A \type{SmartTextSelection} is basically a text
625 selection\typeref{org.eclipse.jface.text.ITextSelection} object that enforces
626 the providing of the underlying document during creation. I.e. its
627 \methodwithref{no.uio.ifi.refaktor.utils.SmartTextSelection}{getDocument} method
628 will never return \type{null}.
630 Before extracting the new method, the possible targets for the move operation is
631 found with the help of an
632 \typewithref{no.uio.ifi.refaktor.extractors}{ExtractAndMoveMethodPrefixesExtractor}.
633 The possible targets is computed from the prefixes that the extractor returns
635 \methodwithref{no.uio.ifi.refaktor.extractors.ExtractAndMoveMethodPrefixesExtractor}{getSafePrefixes}
636 method. The changer then choose the most suitable target by finding the most
637 frequent occurring prefix among the safe ones. The target is the type of the
638 first part of the prefix.
640 After finding a suitable target, the \type{ExtractAndMoveMethodChanger} first
641 creates an \type{ExtractMethodRefactoring} and performs it as explained in
642 section \ref{executing_refactoring} about the execution of refactorings. Then it
643 creates and performs the \type{MoveRefactoring} in the same way, based on the
644 changes done by the Extract Method refactoring.
646 \subsection{The ExtractAndMoveMethodPrefixesExtractor Class}
647 This extractor extracts properties needed for building the Extract and Move
648 Method refactoring. It searches through the given selection to find safe
649 prefixes, and those prefixes form a base that can be used to compute possible
650 targets for the move part of the refactoring. It finds both the candidates, in
651 the form of prefixes, and the non-candidates, called unfixes. All prefixes (and
652 unfixes) are represented by a
653 \typewithref{no.uio.ifi.refaktor.extractors}{Prefix}, and they are collected
654 into prefix sets.\typeref{no.uio.ifi.refaktor.extractors.PrefixSet}.
656 The prefixes and unfixes are found by property
657 collectors\typeref{no.uio.ifi.refaktor.extractors.collectors.PropertyCollector}.
658 A property collector follows the visitor pattern \cite{dp} and is of the
659 \typewithref{org.eclipse.jdt.core.dom}{ASTVisitor} type. An \type{ASTVisitor}
660 visits nodes in an abstract syntax tree that forms the Java document object
661 model. The tree consists of nodes of type
662 \typewithref{org.eclipse.jdt.core.do}{ASTNode}.
664 \subsubsection{The PrefixesCollector}
665 The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{PrefixesCollector}
666 is of type \type{PropertyCollector}. It visits expression
667 statements\typeref{org.eclipse.jdt.core.dom.ExpressionStatement} and creates
668 prefixes from its expressions in the case of method invocations. The prefixes
669 found is registered with a prefix set, together with all its sub-prefixes.
670 \todo{Rewrite in the case of changes to the way prefixes are found}
672 \subsubsection{The UnfixesCollector}
673 The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{UnfixesCollector}
674 finds unfixes within the selection. An unfix is a name that is assigned to
675 within the selection. The reason that this cannot be allowed, is that the result
676 would be an assignment to the \type{this} keyword, which is not valid in Java.
678 \subsubsection{Computing Safe Prefixes}
679 A safe prefix is a prefix that does not enclose an unfix. A prefix is enclosing
680 an unfix if the unfix is in the set of its sub-prefixes. As an example,
681 \texttt{``a.b''} is enclosing \texttt{``a''}, as is \texttt{``a''}. The safe
682 prefixes is unified in a \type{PrefixSet} and can be fetched calling the
683 \method{getSafePrefixes} method of the
684 \type{ExtractAndMoveMethodPrefixesExtractor}.
686 \subsection{The Prefix Class}
688 \subsection{The PrefixSet Class}
690 \subsection{Hacking the Refactoring Undo
691 History}\label{hacking_undo_history}
692 \todo{Where to put this section?}
694 As an attempt to make multiple subsequent changes to the workspace appear as a
695 single action (i.e. make the undo changes appear as such), I tried to alter
696 the undo changes\typeref{org.eclipse.ltk.core.refactoring.Change} in the history
699 My first impulse was to remove the, in this case, last two undo changes from the
700 undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} for the
701 Eclipse refactorings, and then add them to a composite
702 change\typeref{org.eclipse.ltk.core.refactoring.CompositeChange} that could be
703 added back to the manager. The interface of the undo manager does not offer a
704 way to remove/pop the last added undo change, so a possible solution could be to
705 decorate \cite{dp} the undo manager, to intercept and collect the undo changes
706 before delegating to the \method{addUndo}
707 method\methodref{org.eclipse.ltk.core.refactoring.IUndoManager}{addUndo} of the
708 manager. Instead of giving it the intended undo change, a null change could be
709 given to prevent it from making any changes if run. Then one could let the
710 collected undo changes form a composite change to be added to the manager.
712 There is a technical challenge with this approach, and it relates to the undo
713 manager, and the concrete implementation
714 UndoManager2\typeref{org.eclipse.ltk.internal.core.refactoring.UndoManager2}.
715 This implementation is designed in a way that it is not possible to just add an
716 undo change, you have to do it in the context of an active
717 operation\typeref{org.eclipse.core.commands.operations.TriggeredOperations}.
718 One could imagine that it might be possible to trick the undo manager into
719 believing that you are doing a real change, by executing a refactoring that is
720 returning a kind of null change that is returning our composite change of undo
721 refactorings when it is performed.
723 Apart from the technical problems with this solution, there is a functional
724 problem: If it all had worked out as planned, this would leave the undo history
725 in a dirty state, with multiple empty undo operations corresponding to each of
726 the sequentially executed refactoring operations, followed by a composite undo
727 change corresponding to an empty change of the workspace for rounding of our
728 composite refactoring. The solution to this particular problem could be to
729 intercept the registration of the intermediate changes in the undo manager, and
730 only register the last empty change.
732 Unfortunately, not everything works as desired with this solution. The grouping
733 of the undo changes into the composite change does not make the undo operation
734 appear as an atomic operation. The undo operation is still split up into
735 separate undo actions, corresponding to the change done by its originating
736 refactoring. And in addition, the undo actions has to be performed separate in
737 all the editors involved. This makes it no solution at all, but a step toward
740 There might be a solution to this problem, but it remains to be found. The
741 design of the refactoring undo management is partly to be blamed for this, as it
742 it is to complex to be easily manipulated.