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