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}
49 To make it clear already from the beginning: The discussions in this report must
50 be seen in the context of object oriented programming languages, and Java in
51 particular, since that is the language in which most of the examples will be
52 given. All though the techniques discussed may be applicable to languages from
53 other paradigms, they will not be the subject of this report.
57 \chapter{What is Refactoring?}
59 This question is best answered by first defining the concept of a
60 \emph{refactoring}, what it is to \emph{refactor}, and then discuss what aspects
61 of programming that make people want to refactor their code.
63 \section{Defining refactoring}
64 Martin Fowler, in his masterpiece on refactoring \cite{refactoring}, defines a
65 refactoring like this:
67 \emph{Refactoring} (noun): a change made to the \todo{what does he mean by
68 internal?} internal structure of software to make it easier to understand and
69 cheaper to modify without changing its observable
70 behavior.~\cite{refactoring} % page 53
72 This definition assign additional meaning to the word \emph{refactoring}, beyond
73 the composition of the prefix \emph{re-}, usually meaning something like
74 ``again'' or ``anew'', and the word \emph{factoring}, that can mean to determine
75 the \emph{factors} of something. Where a \emph{factor} would be close to the
76 mathematical definition of something that divides a quantity, without leaving a
77 remainder. Fowler is mixing the \emph{motivation} behind refactoring into his
78 definition. Instead it could be made clean, only considering the mechanical and
79 behavioral aspects of refactoring. That is to factor the program again, putting
80 it together in a different way than before, while preserving the behavior of the
81 program. An alternative definition could then be:
83 \definition{A refactoring is a transformation
84 done to a program without altering its external behavior.}
86 From this we can conclude that a refactoring primarily changes how the
87 \emph{code} of a program is perceived by the \emph{programmer}, and not the
88 \emph{behavior} experienced by any user of the program. Although the logical
89 meaning is preserved, such changes could potentially alter the program's
90 behavior when it comes to performance gain or -penalties. So any logic depending
91 on the performance of a program could make the program behave differently after
94 In the extreme case one could argue that such a thing as \emph{software
95 obfuscation} is to refactor. If we where to define it as a refactoring, it could
96 be defined as a composite refactoring \see{intro_composite}, consisting of, for
97 instance, a series of rename refactorings. (But it could of course be much more
98 complex, and the mechanics of it would not exactly be carved in stone.) To
99 perform some serious obfuscation one would also take advantage of techniques not
100 found among established refactorings, such as removing whitespace. This might
101 not even generate a different syntax tree for languages not sensitive to
102 whitespace, placing it in the gray area of what kind of transformations is to be
103 considered refactorings.
105 Finally, to \emph{refactor} is (quoting Martin Fowler)
107 \ldots to restructure software by applying a series of refactorings without
108 changing its observable behavior.~\cite{refactoring} % page 54, definition
111 \section{The etymology of 'refactoring'}
112 It is a little difficult to pinpoint the exact origin of the word
113 ``refactoring'', as it seems to have evolved as part of a colloquial
114 terminology, more than a scientific term. There is no authoritative source for a
115 formal definition of it.
117 According to Martin Fowler~\cite{etymology-refactoring}, there may also be more
118 than one origin of the word. The most well-known source, when it comes to the
119 origin of \emph{refactoring}, is the Smalltalk\footnote{\emph{Smalltalk},
120 object-oriented, dynamically typed, reflective programming language.}\todo{find
121 reference to Smalltalk website or similar?} community and their infamous
123 Browser}\footnote{\url{http://st-www.cs.illinois.edu/users/brant/Refactory/RefactoringBrowser.html}}
124 described in the article \emph{A Refactoring Tool for
125 Smalltalk}~\cite{refactoringBrowser1997}, published in 1997.
126 Allegedly~\cite{etymology-refactoring}, the metaphor of factoring programs was
127 also present in the Forth\footnote{\emph{Forth} -- stack-based, extensible
128 programming language, without type-checking. See \url{http://www.forth.org}}
129 community, and the word ``refactoring'' is mentioned in a book by Leo Brodie,
130 called \emph{Thinking Forth}~\cite{brodie1984}, first published in
131 1984\footnote{\emph{Thinking Forth} was first published in 1984 by the
132 \emph{Forth Interest Group}. Then it was reprinted in 1994 with minor
133 typographical corrections, before it was transcribed into an electronic edition
134 typeset in \LaTeX\ and published under a Creative Commons licence in 2004. The
135 edition cited here is the 2004 edition, but the content should essentially be as
136 in 1984.}. The exact word is only printed one place\footnote{p. 232}, but the
137 term \emph{factoring} is prominent in the book, that also contains a whole
138 chapter dedicated to (re)factoring, and how to keep the (Forth) code clean and
141 \ldots good factoring technique is perhaps the most important skill for a
142 Forth programmer.~\cite{brodie1984}
144 Brodie also express what \emph{factoring} means to him:
146 Factoring means organizing code into useful fragments. To make a fragment
147 useful, you often must separate reusable parts from non-reusable parts. The
148 reusable parts become new definitions. The non-reusable parts become arguments
149 or parameters to the definitions.~\cite{brodie1984}
152 Fowler claims that the usage of the word \emph{refactoring} did not pass between
153 the \emph{Forth} and \emph{Smalltalk} communities, but that it emerged
154 independently in each of the communities.
158 \section{Motivation -- Why people refactor}
159 To get a grasp of what refactoring is all about, we can try to answer this
160 question: \emph{Why do people refactor?} Possible answers could include: ``To
161 remove duplication'' or ``to break up long methods''. Practitioners of the art
162 of Design Patterns~\cite{dp} could say that they do it to introduce a
163 long-needed pattern into their program's design. So it's safe to say that
164 peoples' intentions are to make their programs \emph{better} in some sense. But
165 what aspects of the programs are becoming improved?
167 As already mentioned, people often refactor to get rid of duplication. Moving
168 identical or similar code into methods, and maybe pushing those up or down in
169 their class hierarchies. Making template methods for overlapping
170 algorithms/functionality and so on. It's all about gathering what belongs
171 together and putting it all in one place. And the result? The code is easier to
172 maintain. When removing the implicit coupling between the code snippets, the
173 location of a bug is limited to only one place, and new functionality need only
174 to be added this one place, instead of a number of places people might not even
177 The same people find out that their program contains a lot of long and
178 hard-to-grasp methods. Then what do they do? They begin dividing their methods
179 into smaller ones, using the \emph{Extract Method}
180 refactoring~\cite{refactoring}. Then they may discover something about their
181 program that they weren't aware of before; revealing bugs they didn't know about
182 or couldn't find due to the complex structure of their program. \todo{Proof?}
183 Making the methods smaller and giving good names to the new ones clarifies the
184 algorithms and enhances the \emph{understandability} of the program. This makes
185 simple refactoring an excellent method for exploring unknown program code, or
186 code that you had forgotten that you wrote!
188 The word \emph{simple} came up in the last section. In fact, most basic
189 refactorings are simple. The true power of them are revealed first when they are
190 combined into larger --- higher level --- refactorings, called \emph{composite
191 refactorings} \see{intro_composite}. Often the goal of such a series of
192 refactorings is a design pattern. Thus the \emph{design} can be evolved
193 throughout the lifetime of a program, opposed to designing up-front. It's all
194 about being structured and taking small steps to improve the design.
196 Many refactorings are aimed at lowering the coupling between different classes
197 and different layers of logic. Say for instance that the coupling between the
198 user interface and the business logic of a program is lowered. Then the business
199 logic of the program could much easier be the target of automated tests,
200 increasing the productivity in the software development process. It is also
201 easier to distribute (e.g. between computers) the different components of a
202 program if they are sufficiently decoupled.
204 Another effect of refactoring is that with the increased separation of concerns
205 coming out of many refactorings, the \emph{performance} is improved. When
206 profiling programs, the problem parts are narrowed down to smaller parts of the
207 code, which are easier to tune, and optimization can be performed only where
208 needed and in a more effective way.
210 Refactoring program code --- with a goal in mind --- can give the code itself
211 more value. That is in the form of robustness to bugs, understandability and
212 maintainability. With the first as an obvious advantage, but with the following
213 two being also very important for software development. By incorporating
214 refactoring in the development process, bugs are found faster, new functionality
215 is added more easily and code is easier to understand by the next person exposed
216 to it, which might as well be the person who wrote it. The consequence of this,
217 is that refactoring can increase the average productivity of the development
218 process, and thus also add to the monetary value of a business in the long run.
219 Where this last point also should open the eyes of some nearsighted managers who
220 seldom see beyond the next milestone.
222 \todo{motivation: support new functionality?}
224 \section{The magical number seven}
225 \emph{The magical number seven, plus or minus two: some limits on our capacity
226 for processing information}~\cite{miller1956} is an article by George A. Miller
227 that was published in the journal \emph{Psychological Review} in 1956. It
228 presents evidence that support that the capacity of the number of objects a
229 human being can hold in its working memory is roughly seven, plus or minus two
230 objects. This number varies a bit depending on the nature and complexity of the
231 objects, but is according to Miller ``\ldots never changing so much as to be
234 Miller's article culminates in the section called \emph{Recoding}, a term he
235 borrows from communication theory. The central result in this section is that by
236 recoding information, the capacity of the amount of information that a human can
237 process at a time is increased. By \emph{recoding}, Miller means to group
238 objects together in chunks and give each chunk a new name that it can be
239 remembered by. By organizing objects into patterns of ever growing depth, one
240 can memorize and process a much larger amount of data than if it were to be
241 represented as its basic pieces. This grouping and renaming is analogous to how
242 many refactorings work, by grouping pieces of code and give them a new name.
243 Examples are the central \emph{Extract Method} and \emph{Extract Class}
244 refactorings~\cite{refactoring}.
247 \ldots recoding is an extremely powerful weapon for increasing the amount of
248 information that we can deal with.~\cite{miller1956}
250 An example from the article address the problem of memorizing a sequence of
251 binary digits. Let us say we have the following sequence\footnote{The example
252 presented here is slightly modified (and shortened) from what is presented in
253 the original article~\cite{miller1956}, but it is essentially the same.} of
254 16 binary digits: ``1010001001110011''. Most of us will have a hard time
255 memorizing this sequence by only reading it once or twice. Imagine if we instead
256 translate it to this sequence: ``A273''. If you have a background from computer
257 science, it will be obvious that the latest sequence is the first sequence
258 recoded to be represented by digits with base 16. Most people should be able to
259 memorize this last sequence by only looking at it once.
261 Another result from the Miller article is that when the amount of information a
262 human must interpret increases, it is crucial that the translation from one code
263 to another must be almost automatic for the subject to be able to remember the
264 translation, before he or she is presented with new information to recode. Thus
265 learning and understanding how to best organize certain kinds of data is
266 essential to efficiently handle that kind of data in the future. This is much
267 like when children learn to read. First they must learn how to recognize
268 letters. Then they can learn distinct words, and later read sequences of words
269 that form whole sentences. Eventually, most of them will be able to read whole
270 books and briefly retell the important parts of its content. This suggest that
271 the use of design patterns~\cite{dp} is a good idea when reasoning about
272 computer programs. With extensive use of design patterns when creating complex
273 program structures, one does not always have to read whole classes of code to
274 comprehend how they function, it may be sufficient to only see the name of a
275 class to almost fully understand its responsibilities.
278 Our language is tremendously useful for repackaging material into a few chunks
279 rich in information.~\cite{miller1956}
281 Without further evidence, these results at least indicates that refactoring
282 source code into smaller units with higher cohesion and, when needed,
283 introducing appropriate design patterns, should aid in the cause of creating
284 computer programs that are easier to maintain and has code that is easier (and
287 \section{Notable contributions to the refactoring literature}
288 \todo{Update with more contributions}
290 \item[1992] William F. Opdyke submits his doctoral dissertation called
291 \emph{Refactoring Object-Oriented Frameworks}~\cite{opdyke1992}. This
292 work defines a set of refactorings, that are behavior preserving given that
293 their preconditions are met. The dissertation is focused on the automation
295 \item[1999] Martin Fowler et al.: \emph{Refactoring: Improving the Design of
296 Existing Code}~\cite{refactoring}. This is maybe the most influential text
297 on refactoring. It bares similarities with Opdykes thesis~\cite{opdyke1992}
298 in the way that it provides a catalog of refactorings. But Fowler's book is
299 more about the craft of refactoring, as he focuses on establishing a
300 vocabulary for refactoring, together with the mechanics of different
301 refactorings and when to perform them. His methodology is also founded on
302 the principles of test-driven development.
303 \item[todo] \emph{Refactoring to Patterns}\todo{include}
306 \section{Tool support}
307 \todo{write, section vs. subsection}
309 \section{Relation to design patterns}
310 \todo{write, section vs. subsection, refactoring to patterns?}
313 \section{Classification of refactorings}
314 % only interesting refactorings
315 % with 2 detailed examples? One for structured and one for intra-method?
316 % Is replacing Bubblesort with Quick Sort considered a refactoring?
318 \subsection{Structural refactorings}
320 \subsubsection{Basic refactorings}
323 \explanation{Extract Method}{You have a code fragment that can be grouped
324 together.}{Turn the fragment into a method whose name explains the purpose of
327 \explanation{Inline Method}{A method's body is just as clear as its name.}{Put
328 the method's body into the body of its callers and remove the method.}
330 \explanation{Inline Temp}{You have a temp that is assigned to once with a simple
331 expression, and the temp is getting in the way of other refactorings.}{Replace
332 all references to that temp with the expression}
334 % Moving Features Between Objects
335 \explanation{Move Method}{A method is, or will be, using or used by more
336 features of another class than the class on which it is defined.}{Create a new
337 method with a similar body in the class it uses most. Either turn the old method
338 into a simple delegation, or remove it altogether.}
340 \explanation{Move Field}{A field is, or will be, used by another class more than
341 the class on which it is defined}{Create a new field in the target class, and
342 change all its users.}
345 \explanation{Replace Magic Number with Symbolic Constant}{You have a literal
346 number with a particular meaning.}{Create a constant, name it after the meaning,
347 and replace the number with it.}
349 \explanation{Encapsulate Field}{There is a public field.}{Make it private and
352 \explanation{Replace Type Code with Class}{A class has a numeric type code that
353 does not affect its behavior.}{Replace the number with a new class.}
355 \explanation{Replace Type Code with Subclasses}{You have an immutable type code
356 that affects the behavior of a class.}{Replace the type code with subclasses.}
358 \explanation{Replace Type Code with State/Strategy}{You have a type code that
359 affects the behavior of a class, but you cannot use subclassing.}{Replace the
360 type code with a state object.}
362 % Simplifying Conditional Expressions
363 \explanation{Consolidate Duplicate Conditional Fragments}{The same fragment of
364 code is in all branches of a conditional expression.}{Move it outside of the
367 \explanation{Remove Control Flag}{You have a variable that is acting as a
368 control flag fro a series of boolean expressions.}{Use a break or return
371 \explanation{Replace Nested Conditional with Guard Clauses}{A method has
372 conditional behavior that does not make clear the normal path of
373 execution.}{Use guard clauses for all special cases.}
375 \explanation{Introduce Null Object}{You have repeated checks for a null
376 value.}{Replace the null value with a null object.}
378 \explanation{Introduce Assertion}{A section of code assumes something about the
379 state of the program.}{Make the assumption explicit with an assertion.}
381 % Making Method Calls Simpler
382 \explanation{Rename Method}{The name of a method does not reveal its
383 purpose.}{Change the name of the method}
385 \explanation{Add Parameter}{A method needs more information from its
386 caller.}{Add a parameter for an object that can pass on this information.}
388 \explanation{Remove Parameter}{A parameter is no longer used by the method
391 %\explanation{Parameterize Method}{Several methods do similar things but with
392 %different values contained in the method.}{Create one method that uses a
393 %parameter for the different values.}
395 \explanation{Preserve Whole Object}{You are getting several values from an
396 object and passing these values as parameters in a method call.}{Send the whole
399 \explanation{Remove Setting Method}{A field should be set at creation time and
400 never altered.}{Remove any setting method for that field.}
402 \explanation{Hide Method}{A method is not used by any other class.}{Make the
405 \explanation{Replace Constructor with Factory Method}{You want to do more than
406 simple construction when you create an object}{Replace the constructor with a
409 % Dealing with Generalization
410 \explanation{Pull Up Field}{Two subclasses have the same field.}{Move the field
413 \explanation{Pull Up Method}{You have methods with identical results on
414 subclasses.}{Move them to the superclass.}
416 \explanation{Push Down Method}{Behavior on a superclass is relevant only for
417 some of its subclasses.}{Move it to those subclasses.}
419 \explanation{Push Down Field}{A field is used only by some subclasses.}{Move the
420 field to those subclasses}
422 \explanation{Extract Interface}{Several clients use the same subset of a class's
423 interface, or two classes have part of their interfaces in common.}{Extract the
424 subset into an interface.}
426 \explanation{Replace Inheritance with Delegation}{A subclass uses only part of a
427 superclasses interface or does not want to inherit data.}{Create a field for the
428 superclass, adjust methods to delegate to the superclass, and remove the
431 \explanation{Replace Delegation with Inheritance}{You're using delegation and
432 are often writing many simple delegations for the entire interface}{Make the
433 delegating class a subclass of the delegate.}
435 \subsubsection{Composite refactorings}
438 % \explanation{Replace Method with Method Object}{}{}
440 % Moving Features Between Objects
441 \explanation{Extract Class}{You have one class doing work that should be done by
442 two}{Create a new class and move the relevant fields and methods from the old
443 class into the new class.}
445 \explanation{Inline Class}{A class isn't doing very much.}{Move all its features
446 into another class and delete it.}
448 \explanation{Hide Delegate}{A client is calling a delegate class of an
449 object.}{Create Methods on the server to hide the delegate.}
451 \explanation{Remove Middle Man}{A class is doing to much simple delegation.}{Get
452 the client to call the delegate directly.}
455 \explanation{Replace Data Value with Object}{You have a data item that needs
456 additional data or behavior.}{Turn the data item into an object.}
458 \explanation{Change Value to Reference}{You have a class with many equal
459 instances that you want to replace with a single object.}{Turn the object into a
462 \explanation{Encapsulate Collection}{A method returns a collection}{Make it
463 return a read-only view and provide add/remove methods.}
465 % \explanation{Replace Array with Object}{}{}
467 \explanation{Replace Subclass with Fields}{You have subclasses that vary only in
468 methods that return constant data.}{Change the methods to superclass fields and
469 eliminate the subclasses.}
471 % Simplifying Conditional Expressions
472 \explanation{Decompose Conditional}{You have a complicated conditional
473 (if-then-else) statement.}{Extract methods from the condition, then part, an
476 \explanation{Consolidate Conditional Expression}{You have a sequence of
477 conditional tests with the same result.}{Combine them into a single conditional
478 expression and extract it.}
480 \explanation{Replace Conditional with Polymorphism}{You have a conditional that
481 chooses different behavior depending on the type of an object.}{Move each leg
482 of the conditional to an overriding method in a subclass. Make the original
485 % Making Method Calls Simpler
486 \explanation{Replace Parameter with Method}{An object invokes a method, then
487 passes the result as a parameter for a method. The receiver can also invoke this
488 method.}{Remove the parameter and let the receiver invoke the method.}
490 \explanation{Introduce Parameter Object}{You have a group of parameters that
491 naturally go together.}{Replace them with an object.}
493 % Dealing with Generalization
494 \explanation{Extract Subclass}{A class has features that are used only in some
495 instances.}{Create a subclass for that subset of features.}
497 \explanation{Extract Superclass}{You have two classes with similar
498 features.}{Create a superclass and move the common features to the
501 \explanation{Collapse Hierarchy}{A superclass and subclass are not very
502 different.}{Merge them together.}
504 \explanation{Form Template Method}{You have two methods in subclasses that
505 perform similar steps in the same order, yet the steps are different.}{Get the
506 steps into methods with the same signature, so that the original methods become
507 the same. Then you can pull them up.}
510 \subsection{Functional refactorings}
512 \explanation{Substitute Algorithm}{You want to replace an algorithm with one
513 that is clearer.}{Replace the body of the method with the new algorithm.}
517 \section{The impact on software quality}
519 \subsection{What is meant by quality?}
520 The term \emph{software quality} has many meanings. It all depends on the
521 context we put it in. If we look at it with the eyes of a software developer, it
522 usually mean that the software is easily maintainable and testable, or in other
523 words, that it is \emph{well designed}. This often correlates with the
524 management scale, where \emph{keeping the schedule} and \emph{customer
525 satisfaction} is at the center. From the customers point of view, in addition to
526 good usability, \emph{performance} and \emph{lack of bugs} is always
527 appreciated, measurements that are also shared by the software developer. (In
528 addition, such things as good documentation could be measured, but this is out
529 of the scope of this document.)
531 \subsection{The impact on performance}
533 Refactoring certainly will make software go more slowly, but it also makes the
534 software more amenable to performance tuning.~\cite{refactoring} % page 69
536 There is a common belief that refactoring compromises performance, due to
537 increased degree of indirection and that polymorphism is slower than
540 In a survey, Demeyer~\cite{demeyer2002} disproves this view in the case of
541 polymorphism. He is doing an experiment on, what he calls, ``Transform Self Type
542 Checks'' where you introduce a new polymorphic method and a new class hierarchy
543 to get rid of a class' type checking of a ``type attribute``. He uses this kind
544 of transformation to represent other ways of replacing conditionals with
545 polymorphism as well. The experiment is performed on the C++ programming
546 language and with three different compilers and platforms. \todo{But is the
547 result better?} Demeyer concludes that, with compiler optimization turned on,
548 polymorphism beats middle to large sized if-statements and does as well as
549 case-statements. (In accordance with his hypothesis, due to similarities
550 between the way C++ handles polymorphism and case-statements.)
552 The interesting thing about performance is that if you analyze most programs,
553 you find that they waste most of their time in a small fraction of the code.
556 So, although an increased amount of method calls could potentially slow down
557 programs, one should avoid premature optimization and sacrificing good design,
558 leaving the performance tuning until after profiling\footnote{For and example of
559 a Java profiler, check out VisualVM: \url{http://visualvm.java.net/}} the
560 software and having isolated the actual problem areas.
564 \section{Correctness of refactorings}
565 \todo{Volker's example?}
567 \section{Composite refactorings} \label{intro_composite}
568 \todo{motivation, examples, manual vs automated?, what about refactoring in a
569 very large code base?}
571 \section{Software metrics}
575 %\chapter{Planning the project}
583 \section{The problem statement}
584 \section{Choosing the language}
585 \section{Choosing the tool}
587 \chapter{Refactorings in Eclipse JDT: Design, Shortcomings and Wishful
588 Thinking}\label{ch:jdt_refactorings}
590 This chapter will deal with some of the design behind refactoring support in
591 Eclipse, and the JDT in specific. After which it will follow a section about
592 shortcomings of the refactoring API in terms of composition of refactorings. The
593 chapter will be concluded with a section telling some of the ways the
594 implementation of refactorings in the JDT could have worked to facilitate
595 composition of refactorings.
598 The refactoring world of Eclipse can in general be separated into two parts: The
599 language independent part and the part written for a specific programming
600 language -- the language that is the target of the supported refactorings.
601 \todo{What about the language specific part?}
603 \subsection{The Language Toolkit}
604 The Language Toolkit, or LTK for short, is the framework that is used to
605 implement refactorings in Eclipse. It is language independent and provides the
606 abstractions of a refactoring and the change it generates, in the form of the
607 classes \typewithref{org.eclipse.ltk.core.refactoring}{Refactoring} and
608 \typewithref{org.eclipse.ltk.core.refactoring}{Change}. (There is also parts of
609 the LTK that is concerned with user interaction, but they will not be discussed
610 here, since they are of little value to us and our use of the framework.)
612 \subsubsection{The Refactoring Class}
613 The abstract class \type{Refactoring} is the core of the LTK framework. Every
614 refactoring that is going to be supported by the LTK have to end up creating an
615 instance of one of its subclasses. The main responsibilities of subclasses of
616 \type{Refactoring} is to implement template methods for condition checking
617 (\methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkInitialConditions}
619 \methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkFinalConditions}),
621 \methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{createChange}
622 method that creates and returns an instance of the \type{Change} class.
624 If the refactoring shall support that others participate in it when it is
625 executed, the refactoring has to be a processor-based
626 refactoring\typeref{org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring}.
627 It then delegates to its given
628 \typewithref{org.eclipse.ltk.core.refactoring.participants}{RefactoringProcessor}
629 for condition checking and change creation.
631 \subsubsection{The Change Class}
632 This class is the base class for objects that is responsible for performing the
633 actual workspace transformations in a refactoring. The main responsibilities for
634 its subclasses is to implement the
635 \methodwithref{org.eclipse.ltk.core.refactoring.Change}{perform} and
636 \methodwithref{org.eclipse.ltk.core.refactoring.Change}{isValid} methods. The
637 \method{isValid} method verifies that the change object is valid and thus can be
638 executed by calling its \method{perform} method. The \method{perform} method
639 performs the desired change and returns an undo change that can be executed to
640 reverse the effect of the transformation done by its originating change object.
642 \subsubsection{Executing a Refactoring}\label{executing_refactoring}
643 The life cycle of a refactoring generally follows two steps after creation:
644 condition checking and change creation. By letting the refactoring object be
646 \typewithref{org.eclipse.ltk.core.refactoring}{CheckConditionsOperation} that
647 in turn is handled by a
648 \typewithref{org.eclipse.ltk.core.refactoring}{CreateChangeOperation}, it is
649 assured that the change creation process is managed in a proper manner.
651 The actual execution of a change object has to follow a detailed life cycle.
652 This life cycle is honored if the \type{CreateChangeOperation} is handled by a
653 \typewithref{org.eclipse.ltk.core.refactoring}{PerformChangeOperation}. If also
654 an undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} is set
655 for the \type{PerformChangeOperation}, the undo change is added into the undo
658 \section{Shortcomings}
659 This section is introduced naturally with a conclusion: The JDT refactoring
660 implementation does not facilitate composition of refactorings.
661 \todo{refine}This section will try to explain why, and also identify other
662 shortcomings of both the usability and the readability of the JDT refactoring
665 I will begin at the end and work my way toward the composition part of this
668 \subsection{Absence of Generics in Eclipse Source Code}
669 This section is not only concerning the JDT refactoring API, but also large
670 quantities of the Eclipse source code. The code shows a striking absence of the
671 Java language feature of generics. It is hard to read a class' interface when
672 methods return objects or takes parameters of raw types such as \type{List} or
673 \type{Map}. This sometimes results in having to read a lot of source code to
674 understand what is going on, instead of relying on the available interfaces. In
675 addition, it results in a lot of ugly code, making the use of typecasting more
676 of a rule than an exception.
678 \subsection{Composite Refactorings Will Not Appear as Atomic Actions}
680 \subsubsection{Missing Flexibility from JDT Refactorings}
681 The JDT refactorings are not made with composition of refactorings in mind. When
682 a JDT refactoring is executed, it assumes that all conditions for it to be
683 applied successfully can be found by reading source files that has been
684 persisted to disk. They can only operate on the actual source material, and not
685 (in-memory) copies thereof. This constitutes a major disadvantage when trying to
686 compose refactorings, since if an exception occur in the middle of a sequence of
687 refactorings, it can leave the project in a state where the composite
688 refactoring was executed only partly. It makes it hard to discard the changes
689 done without monitoring and consulting the undo manager, an approach that is not
692 \subsubsection{Broken Undo History}
693 When designing a composed refactoring that is to be performed as a sequence of
694 refactorings, you would like it to appear as a single change to the workspace.
695 This implies that you would also like to be able to undo all the changes done by
696 the refactoring in a single step. This is not the way it appears when a sequence
697 of JDT refactorings is executed. It leaves the undo history filled up with
698 individual undo actions corresponding to every single JDT refactoring in the
699 sequence. This problem is not trivial to handle in Eclipse. (See section
700 \ref{hacking_undo_history}.)
702 \section{Wishful Thinking}
706 \chapter{Composite Refactorings in Eclipse}
708 \section{A Simple Ad Hoc Model}
709 As pointed out in chapter \ref{ch:jdt_refactorings}, the Eclipse JDT refactoring
710 model is not very well suited for making composite refactorings. Therefore a
711 simple model using changer objects (of type \type{RefaktorChanger}) is used as
712 an abstraction layer on top of the existing Eclipse refactorings.
714 \section{The Extract and Move Method Refactoring}
715 %The Extract and Move Method Refactoring is implemented mainly using these
718 % \item \type{ExtractAndMoveMethodChanger}
719 % \item \type{ExtractAndMoveMethodPrefixesExtractor}
720 % \item \type{Prefix}
721 % \item \type{PrefixSet}
724 \subsection{The Building Blocks}
725 This is a composite refactoring, and hence is built up using several primitive
726 refactorings. These basic building blocks are, as its name implies, the Extract
727 Method Refactoring \cite{refactoring} and the Move Method Refactoring
728 \cite{refactoring}. In Eclipse, the implementations of these refactorings are
730 \typewithref{org.eclipse.jdt.internal.corext.refactoring.code}{ExtractMethodRefactoring}
732 \typewithref{org.eclipse.jdt.internal.corext.refactoring.structure}{MoveInstanceMethodProcessor},
733 where the last class is designed to be used together with the processor-based
734 \typewithref{org.eclipse.ltk.core.refactoring.participants}{MoveRefactoring}.
736 \subsubsection{The ExtractMethodRefactoring Class}
737 This class is quite simple in its use. The only parameters it requires for
738 construction is a compilation
739 unit\typeref{org.eclipse.jdt.core.ICompilationUnit}, the offset into the source
740 code where the extraction shall start, and the length of the source to be
741 extracted. Then you have to set the method name for the new method together with
742 which access modifier that shall be used and some not so interesting parameters.
744 \subsubsection{The MoveInstanceMethodProcessor Class}
745 For the Move Method the processor requires a little more advanced input than
746 the class for the Extract Method. For construction it requires a method
747 handle\typeref{org.eclipse.jdt.core.IMethod} from the Java Model for the method
748 that is to be moved. Then the target for the move have to be supplied as the
749 variable binding from a chosen variable declaration. In addition to this, one
750 have to set some parameters regarding setters/getters and delegation.
752 To make a whole refactoring from the processor, one have to construct a
753 \type{MoveRefactoring} from it.
755 \subsection{The ExtractAndMoveMethodChanger Class}
756 The \typewithref{no.uio.ifi.refaktor.changers}{ExtractAndMoveMethodChanger}
757 class, that is a subclass of the class
758 \typewithref{no.uio.ifi.refaktor.changers}{RefaktorChanger}, is the class
759 responsible for composing the \type{ExtractMethodRefactoring} and the
760 \type{MoveRefactoring}. Its constructor takes a project
761 handle\typeref{org.eclipse.core.resources.IProject}, the method name for the new
762 method and a \typewithref{no.uio.ifi.refaktor.utils}{SmartTextSelection}.
764 A \type{SmartTextSelection} is basically a text
765 selection\typeref{org.eclipse.jface.text.ITextSelection} object that enforces
766 the providing of the underlying document during creation. I.e. its
767 \methodwithref{no.uio.ifi.refaktor.utils.SmartTextSelection}{getDocument} method
768 will never return \type{null}.
770 Before extracting the new method, the possible targets for the move operation is
771 found with the help of an
772 \typewithref{no.uio.ifi.refaktor.extractors}{ExtractAndMoveMethodPrefixesExtractor}.
773 The possible targets is computed from the prefixes that the extractor returns
775 \methodwithref{no.uio.ifi.refaktor.extractors.ExtractAndMoveMethodPrefixesExtractor}{getSafePrefixes}
776 method. The changer then choose the most suitable target by finding the most
777 frequent occurring prefix among the safe ones. The target is the type of the
778 first part of the prefix.
780 After finding a suitable target, the \type{ExtractAndMoveMethodChanger} first
781 creates an \type{ExtractMethodRefactoring} and performs it as explained in
782 section \ref{executing_refactoring} about the execution of refactorings. Then it
783 creates and performs the \type{MoveRefactoring} in the same way, based on the
784 changes done by the Extract Method refactoring.
786 \subsection{The ExtractAndMoveMethodPrefixesExtractor Class}
787 This extractor extracts properties needed for building the Extract and Move
788 Method refactoring. It searches through the given selection to find safe
789 prefixes, and those prefixes form a base that can be used to compute possible
790 targets for the move part of the refactoring. It finds both the candidates, in
791 the form of prefixes, and the non-candidates, called unfixes. All prefixes (and
792 unfixes) are represented by a
793 \typewithref{no.uio.ifi.refaktor.extractors}{Prefix}, and they are collected
794 into prefix sets.\typeref{no.uio.ifi.refaktor.extractors.PrefixSet}.
796 The prefixes and unfixes are found by property
797 collectors\typeref{no.uio.ifi.refaktor.extractors.collectors.PropertyCollector}.
798 A property collector follows the visitor pattern \cite{dp} and is of the
799 \typewithref{org.eclipse.jdt.core.dom}{ASTVisitor} type. An \type{ASTVisitor}
800 visits nodes in an abstract syntax tree that forms the Java document object
801 model. The tree consists of nodes of type
802 \typewithref{org.eclipse.jdt.core.do}{ASTNode}.
804 \subsubsection{The PrefixesCollector}
805 The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{PrefixesCollector}
806 is of type \type{PropertyCollector}. It visits expression
807 statements\typeref{org.eclipse.jdt.core.dom.ExpressionStatement} and creates
808 prefixes from its expressions in the case of method invocations. The prefixes
809 found is registered with a prefix set, together with all its sub-prefixes.
810 \todo{Rewrite in the case of changes to the way prefixes are found}
812 \subsubsection{The UnfixesCollector}
813 The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{UnfixesCollector}
814 finds unfixes within the selection. An unfix is a name that is assigned to
815 within the selection. The reason that this cannot be allowed, is that the result
816 would be an assignment to the \type{this} keyword, which is not valid in Java.
818 \subsubsection{Computing Safe Prefixes}
819 A safe prefix is a prefix that does not enclose an unfix. A prefix is enclosing
820 an unfix if the unfix is in the set of its sub-prefixes. As an example,
821 \texttt{``a.b''} is enclosing \texttt{``a''}, as is \texttt{``a''}. The safe
822 prefixes is unified in a \type{PrefixSet} and can be fetched calling the
823 \method{getSafePrefixes} method of the
824 \type{ExtractAndMoveMethodPrefixesExtractor}.
826 \subsection{The Prefix Class}
828 \subsection{The PrefixSet Class}
830 \subsection{Hacking the Refactoring Undo
831 History}\label{hacking_undo_history}
832 \todo{Where to put this section?}
834 As an attempt to make multiple subsequent changes to the workspace appear as a
835 single action (i.e. make the undo changes appear as such), I tried to alter
836 the undo changes\typeref{org.eclipse.ltk.core.refactoring.Change} in the history
839 My first impulse was to remove the, in this case, last two undo changes from the
840 undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} for the
841 Eclipse refactorings, and then add them to a composite
842 change\typeref{org.eclipse.ltk.core.refactoring.CompositeChange} that could be
843 added back to the manager. The interface of the undo manager does not offer a
844 way to remove/pop the last added undo change, so a possible solution could be to
845 decorate \cite{dp} the undo manager, to intercept and collect the undo changes
846 before delegating to the \method{addUndo}
847 method\methodref{org.eclipse.ltk.core.refactoring.IUndoManager}{addUndo} of the
848 manager. Instead of giving it the intended undo change, a null change could be
849 given to prevent it from making any changes if run. Then one could let the
850 collected undo changes form a composite change to be added to the manager.
852 There is a technical challenge with this approach, and it relates to the undo
853 manager, and the concrete implementation
854 UndoManager2\typeref{org.eclipse.ltk.internal.core.refactoring.UndoManager2}.
855 This implementation is designed in a way that it is not possible to just add an
856 undo change, you have to do it in the context of an active
857 operation\typeref{org.eclipse.core.commands.operations.TriggeredOperations}.
858 One could imagine that it might be possible to trick the undo manager into
859 believing that you are doing a real change, by executing a refactoring that is
860 returning a kind of null change that is returning our composite change of undo
861 refactorings when it is performed.
863 Apart from the technical problems with this solution, there is a functional
864 problem: If it all had worked out as planned, this would leave the undo history
865 in a dirty state, with multiple empty undo operations corresponding to each of
866 the sequentially executed refactoring operations, followed by a composite undo
867 change corresponding to an empty change of the workspace for rounding of our
868 composite refactoring. The solution to this particular problem could be to
869 intercept the registration of the intermediate changes in the undo manager, and
870 only register the last empty change.
872 Unfortunately, not everything works as desired with this solution. The grouping
873 of the undo changes into the composite change does not make the undo operation
874 appear as an atomic operation. The undo operation is still split up into
875 separate undo actions, corresponding to the change done by its originating
876 refactoring. And in addition, the undo actions has to be performed separate in
877 all the editors involved. This makes it no solution at all, but a step toward
880 There might be a solution to this problem, but it remains to be found. The
881 design of the refactoring undo management is partly to be blamed for this, as it
882 it is to complex to be easily manipulated.