]> git.uio.no Git - ifi-stolz-refaktor.git/blame - thesis/master-thesis-erlenkr.tex
Thesis: exchanging some verbatims with custom commands
[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 4\usepackage[T1]{fontenc,url}
3510e539 5\usepackage{lmodern} % using Latin Modern to be able to use bold typewriter font
9ff90080 6\urlstyle{sf}
571ef294 7\usepackage{babel,textcomp,csquotes,ifimasterforside,varioref,graphicx}
84fe308b 8\usepackage[style=numeric-comp,backend=bibtex]{biblatex}
12c254af 9\usepackage{amsthm}
00aa0588 10\usepackage{todonotes}
b289552b 11\usepackage{verbatim}
ddcea0b5
EK
12\usepackage{minted}
13\usemintedstyle{bw}
8fae7b44
EK
14\usepackage{perpage} %the perpage package
15\MakePerPage{footnote} %the perpage package command
9ff90080 16
12c254af
EK
17\theoremstyle{plain}
18\newtheorem*{wordDef}{Definition}
19
ddcea0b5
EK
20\graphicspath{ {./figures/} }
21
12c254af 22\newcommand{\definition}[1]{\begin{wordDef}#1\end{wordDef}}
b01d328a 23\newcommand{\see}[1]{(see section \ref{#1})}
137e0e7b
EK
24\newcommand{\explanation}[3]{\noindent\textbf{\textit{#1}}\\*\emph{When:}
25#2\\*\emph{How:} #3\\*[-7px]}
3510e539 26\newcommand{\type}[1]{\texttt{\textbf{#1}}}
f041551b
EK
27\newcommand{\typeref}[1]{\footnote{\type{#1}}}
28\newcommand{\typewithref}[2]{\type{#2}\typeref{#1.#2}}
29\newcommand{\method}[1]{\type{#1}}
30\newcommand{\methodref}[2]{\footnote{\type{#1}\method{\##2()}}}
31\newcommand{\methodwithref}[2]{\method{#2}\footnote{\type{#1}\method{\##2()}}}
3510e539 32\newcommand{\var}[1]{\type{#1}}
9ff90080 33
7c28933b
EK
34
35\title{Refactoring}
84fe308b 36\subtitle{An unfinished essay}
7c28933b
EK
37\author{Erlend Kristiansen}
38
39\bibliography{bibliography/master-thesis-erlenkr-bibliography}
9ff90080
EK
40
41\begin{document}
531c4132 42\ififorside
9ff90080 43\frontmatter{}
9ff90080
EK
44
45
46\chapter*{Abstract}
47Empty document.
48
49\tableofcontents{}
50\listoffigures{}
51\listoftables{}
52
53\chapter*{Preface}
54
f3a108c3
EK
55To make it clear already from the beginning: The discussions in this report must
56be seen in the context of object oriented programming languages, and Java in
57particular, since that is the language in which most of the examples will be
58given. All though the techniques discussed may be applicable to languages from
59other paradigms, they will not be the subject of this report.
60
055dca93 61\mainmatter
00aa0588 62
740e1b6c 63\chapter{What is Refactoring?}
7c28933b 64
f3a108c3
EK
65This question is best answered by first defining the concept of a
66\emph{refactoring}, what it is to \emph{refactor}, and then discuss what aspects
67of programming that make people want to refactor their code.
00aa0588 68
740e1b6c 69\section{Defining refactoring}
8fae7b44 70Martin Fowler, in his masterpiece on refactoring \cite{refactoring}, defines a
00aa0588 71refactoring like this:
ee45c41f 72
00aa0588
EK
73\begin{quote}
74 \emph{Refactoring} (noun): a change made to the \todo{what does he mean by
75 internal?} internal structure of software to make it easier to understand and
76 cheaper to modify without changing its observable
8fae7b44 77 behavior.~\cite{refactoring} % page 53
00aa0588 78\end{quote}
ee45c41f
EK
79
80\noindent This definition assign additional meaning to the word
81\emph{refactoring}, beyond the composition of the prefix \emph{re-}, usually
82meaning something like ``again'' or ``anew'', and the word \emph{factoring},
83that can mean to determine the \emph{factors} of something. Where a
84\emph{factor} would be close to the mathematical definition of something that
85divides a quantity, without leaving a remainder. Fowler is mixing the
86\emph{motivation} behind refactoring into his definition. Instead it could be
87made clean, only considering the mechanical and behavioral aspects of
88refactoring. That is to factor the program again, putting it together in a
89different way than before, while preserving the behavior of the program. An
90alternative definition could then be:
51a854d4 91
51a854d4 92\definition{A refactoring is a transformation
8fae7b44 93done to a program without altering its external behavior.}
00aa0588 94
ee1d883a
EK
95From this we can conclude that a refactoring primarily changes how the
96\emph{code} of a program is perceived by the \emph{programmer}, and not the
740e1b6c
EK
97\emph{behavior} experienced by any user of the program. Although the logical
98meaning is preserved, such changes could potentially alter the program's
99behavior when it comes to performance gain or -penalties. So any logic depending
100on the performance of a program could make the program behave differently after
101a refactoring.
00aa0588 102
137e0e7b
EK
103In the extreme case one could argue that such a thing as \emph{software
104obfuscation} is to refactor. If we where to define it as a refactoring, it could
105be defined as a composite refactoring \see{intro_composite}, consisting of, for
106instance, a series of rename refactorings. (But it could of course be much more
107complex, and the mechanics of it would not exactly be carved in stone.) To
108perform some serious obfuscation one would also take advantage of techniques not
109found among established refactorings, such as removing whitespace. This might
110not even generate a different syntax tree for languages not sensitive to
ee1d883a 111whitespace, placing it in the gray area of what kind of transformations is to be
137e0e7b 112considered refactorings.
00aa0588
EK
113
114Finally, to \emph{refactor} is (quoting Martin Fowler)
7c28933b
EK
115\begin{quote}
116 \ldots to restructure software by applying a series of refactorings without
8fae7b44 117 changing its observable behavior.~\cite{refactoring} % page 54, definition
7c28933b
EK
118\end{quote}
119
740e1b6c 120\section{The etymology of 'refactoring'}
f3a108c3
EK
121It is a little difficult to pinpoint the exact origin of the word
122``refactoring'', as it seems to have evolved as part of a colloquial
123terminology, more than a scientific term. There is no authoritative source for a
124formal definition of it.
125
126According to Martin Fowler~\cite{etymology-refactoring}, there may also be more
127than one origin of the word. The most well-known source, when it comes to the
128origin of \emph{refactoring}, is the Smalltalk\footnote{\emph{Smalltalk},
129object-oriented, dynamically typed, reflective programming language.}\todo{find
130reference to Smalltalk website or similar?} community and their infamous
131\emph{Refactoring
132Browser}\footnote{\url{http://st-www.cs.illinois.edu/users/brant/Refactory/RefactoringBrowser.html}}
133described in the article \emph{A Refactoring Tool for
134Smalltalk}~\cite{refactoringBrowser1997}, published in 1997.
135Allegedly~\cite{etymology-refactoring}, the metaphor of factoring programs was
136also present in the Forth\footnote{\emph{Forth} -- stack-based, extensible
137programming language, without type-checking. See \url{http://www.forth.org}}
138community, and the word ``refactoring'' is mentioned in a book by Leo Brodie,
139called \emph{Thinking Forth}~\cite{brodie1984}, first published in
1401984\footnote{\emph{Thinking Forth} was first published in 1984 by the
141\emph{Forth Interest Group}. Then it was reprinted in 1994 with minor
142typographical corrections, before it was transcribed into an electronic edition
143typeset in \LaTeX\ and published under a Creative Commons licence in 2004. The
144edition cited here is the 2004 edition, but the content should essentially be as
145in 1984.}. The exact word is only printed one place\footnote{p. 232}, but the
146term \emph{factoring} is prominent in the book, that also contains a whole
147chapter dedicated to (re)factoring, and how to keep the (Forth) code clean and
148maintainable.
ee45c41f 149
f3a108c3
EK
150\begin{quote}
151 \ldots good factoring technique is perhaps the most important skill for a
152 Forth programmer.~\cite{brodie1984}
153\end{quote}
ee45c41f
EK
154
155\noindent Brodie also express what \emph{factoring} means to him:
156
f3a108c3
EK
157\begin{quote}
158 Factoring means organizing code into useful fragments. To make a fragment
159 useful, you often must separate reusable parts from non-reusable parts. The
160 reusable parts become new definitions. The non-reusable parts become arguments
161 or parameters to the definitions.~\cite{brodie1984}
162\end{quote}
163
164Fowler claims that the usage of the word \emph{refactoring} did not pass between
165the \emph{Forth} and \emph{Smalltalk} communities, but that it emerged
166independently in each of the communities.
167
740e1b6c
EK
168\todo{more history?}
169
170\section{Motivation -- Why people refactor}
171To get a grasp of what refactoring is all about, we can try to answer this
172question: \emph{Why do people refactor?} Possible answers could include: ``To
173remove duplication'' or ``to break up long methods''. Practitioners of the art
174of Design Patterns~\cite{dp} could say that they do it to introduce a
b01d328a 175long-needed pattern into their program's design. So it is safe to say that
740e1b6c
EK
176peoples' intentions are to make their programs \emph{better} in some sense. But
177what aspects of the programs are becoming improved?
51a854d4
EK
178
179As already mentioned, people often refactor to get rid of duplication. Moving
00aa0588 180identical or similar code into methods, and maybe pushing those up or down in
740e1b6c
EK
181their class hierarchies. Making template methods for overlapping
182algorithms/functionality and so on. It's all about gathering what belongs
00aa0588 183together and putting it all in one place. And the result? The code is easier to
137e0e7b
EK
184maintain. When removing the implicit coupling between the code snippets, the
185location of a bug is limited to only one place, and new functionality need only
186to be added this one place, instead of a number of places people might not even
187remember.
51a854d4
EK
188
189The same people find out that their program contains a lot of long and
190hard-to-grasp methods. Then what do they do? They begin dividing their methods
00aa0588
EK
191into smaller ones, using the \emph{Extract Method}
192refactoring~\cite{refactoring}. Then they may discover something about their
193program that they weren't aware of before; revealing bugs they didn't know about
194or couldn't find due to the complex structure of their program. \todo{Proof?}
195Making the methods smaller and giving good names to the new ones clarifies the
b01d328a
EK
196algorithms and enhances the \emph{understandability} of the program
197\see{magic_number_seven}. This makes simple refactoring an excellent method for
198exploring unknown program code, or code that you had forgotten that you wrote!
51a854d4 199
f65da046 200The word \emph{simple} came up in the last section. In fact, most primitive
51a854d4 201refactorings are simple. The true power of them are revealed first when they are
137e0e7b 202combined into larger --- higher level --- refactorings, called \emph{composite
8fae7b44 203refactorings} \see{intro_composite}. Often the goal of such a series of
137e0e7b
EK
204refactorings is a design pattern. Thus the \emph{design} can be evolved
205throughout the lifetime of a program, opposed to designing up-front. It's all
b01d328a 206about being structured and taking small steps to improve a program's design.
51a854d4
EK
207
208Many refactorings are aimed at lowering the coupling between different classes
b01d328a
EK
209and different layers of logic. \todo{which refactorings?} Say for instance that
210the coupling between the user interface and the business logic of a program is
211lowered. Then the business logic of the program could much easier be the target
212of automated tests, increasing the productivity in the software development
213process. It is also easier to distribute (e.g. between computers) the different
214components of a program if they are sufficiently decoupled.
0b0567f2
EK
215
216Another effect of refactoring is that with the increased separation of concerns
137e0e7b
EK
217coming out of many refactorings, the \emph{performance} is improved. When
218profiling programs, the problem parts are narrowed down to smaller parts of the
219code, which are easier to tune, and optimization can be performed only where
220needed and in a more effective way.
221
b01d328a
EK
222Last, but not least, and this should probably be the best reason to refactor, is
223to refactor to \emph{facilitate a program change}. If one has managed to keep
224one's code clean and tidy, and the code is not bloated with design patterns that
225is not ever going to be needed, then some refactoring might be needed to
226introduce a design pattern that is appropriate for the change that is going to
227happen.
228
137e0e7b
EK
229Refactoring program code --- with a goal in mind --- can give the code itself
230more value. That is in the form of robustness to bugs, understandability and
231maintainability. With the first as an obvious advantage, but with the following
ee1d883a 232two being also very important for software development. By incorporating
00aa0588
EK
233refactoring in the development process, bugs are found faster, new functionality
234is added more easily and code is easier to understand by the next person exposed
ee1d883a
EK
235to it, which might as well be the person who wrote it. The consequence of this,
236is that refactoring can increase the average productivity of the development
237process, and thus also add to the monetary value of a business in the long run.
238Where this last point also should open the eyes of some nearsighted managers who
239seldom see beyond the next milestone.
137e0e7b 240
b01d328a 241\section{The magical number seven}\label{magic_number_seven}
f4cea2d6
EK
242\emph{The magical number seven, plus or minus two: some limits on our capacity
243for processing information}~\cite{miller1956} is an article by George A. Miller
244that was published in the journal \emph{Psychological Review} in 1956. It
245presents evidence that support that the capacity of the number of objects a
246human being can hold in its working memory is roughly seven, plus or minus two
247objects. This number varies a bit depending on the nature and complexity of the
248objects, but is according to Miller ``\ldots never changing so much as to be
249unrecognizable.''
250
251Miller's article culminates in the section called \emph{Recoding}, a term he
252borrows from communication theory. The central result in this section is that by
253recoding information, the capacity of the amount of information that a human can
254process at a time is increased. By \emph{recoding}, Miller means to group
255objects together in chunks and give each chunk a new name that it can be
256remembered by. By organizing objects into patterns of ever growing depth, one
257can memorize and process a much larger amount of data than if it were to be
258represented as its basic pieces. This grouping and renaming is analogous to how
259many refactorings work, by grouping pieces of code and give them a new name.
260Examples are the central \emph{Extract Method} and \emph{Extract Class}
261refactorings~\cite{refactoring}.
262
263\begin{quote}
264 \ldots recoding is an extremely powerful weapon for increasing the amount of
265 information that we can deal with.~\cite{miller1956}
266\end{quote}
ee45c41f 267
f4cea2d6
EK
268An example from the article address the problem of memorizing a sequence of
269binary digits. Let us say we have the following sequence\footnote{The example
270 presented here is slightly modified (and shortened) from what is presented in
271 the original article~\cite{miller1956}, but it is essentially the same.} of
27216 binary digits: ``1010001001110011''. Most of us will have a hard time
273memorizing this sequence by only reading it once or twice. Imagine if we instead
274translate it to this sequence: ``A273''. If you have a background from computer
275science, it will be obvious that the latest sequence is the first sequence
276recoded to be represented by digits with base 16. Most people should be able to
277memorize this last sequence by only looking at it once.
278
279Another result from the Miller article is that when the amount of information a
280human must interpret increases, it is crucial that the translation from one code
281to another must be almost automatic for the subject to be able to remember the
282translation, before he or she is presented with new information to recode. Thus
283learning and understanding how to best organize certain kinds of data is
284essential to efficiently handle that kind of data in the future. This is much
285like when children learn to read. First they must learn how to recognize
286letters. Then they can learn distinct words, and later read sequences of words
287that form whole sentences. Eventually, most of them will be able to read whole
288books and briefly retell the important parts of its content. This suggest that
289the use of design patterns~\cite{dp} is a good idea when reasoning about
290computer programs. With extensive use of design patterns when creating complex
291program structures, one does not always have to read whole classes of code to
292comprehend how they function, it may be sufficient to only see the name of a
293class to almost fully understand its responsibilities.
294
295\begin{quote}
296 Our language is tremendously useful for repackaging material into a few chunks
297 rich in information.~\cite{miller1956}
298\end{quote}
ee45c41f 299
f4cea2d6
EK
300Without further evidence, these results at least indicates that refactoring
301source code into smaller units with higher cohesion and, when needed,
302introducing appropriate design patterns, should aid in the cause of creating
303computer programs that are easier to maintain and has code that is easier (and
304better) understood.
305
740e1b6c 306\section{Notable contributions to the refactoring literature}
d21ef41f
EK
307\todo{Update with more contributions}
308\begin{description}
309 \item[1992] William F. Opdyke submits his doctoral dissertation called
310 \emph{Refactoring Object-Oriented Frameworks}~\cite{opdyke1992}. This
311 work defines a set of refactorings, that are behavior preserving given that
312 their preconditions are met. The dissertation is focused on the automation
313 of refactorings.
314 \item[1999] Martin Fowler et al.: \emph{Refactoring: Improving the Design of
315 Existing Code}~\cite{refactoring}. This is maybe the most influential text
316 on refactoring. It bares similarities with Opdykes thesis~\cite{opdyke1992}
317 in the way that it provides a catalog of refactorings. But Fowler's book is
318 more about the craft of refactoring, as he focuses on establishing a
319 vocabulary for refactoring, together with the mechanics of different
320 refactorings and when to perform them. His methodology is also founded on
321 the principles of test-driven development.
f3a108c3 322 \item[todo] \emph{Refactoring to Patterns}\todo{include}
d21ef41f 323\end{description}
3b7c1d90
EK
324
325\section{Tool support}
326\todo{write, section vs. subsection}
327
328\section{Relation to design patterns}
f3a108c3 329\todo{write, section vs. subsection, refactoring to patterns?}
b289552b
EK
330\begin{comment}
331
137e0e7b
EK
332\section{Classification of refactorings}
333% only interesting refactorings
334% with 2 detailed examples? One for structured and one for intra-method?
335% Is replacing Bubblesort with Quick Sort considered a refactoring?
336
337\subsection{Structural refactorings}
338
f65da046 339\subsubsection{Primitive refactorings}
137e0e7b
EK
340
341% Composing Methods
342\explanation{Extract Method}{You have a code fragment that can be grouped
343together.}{Turn the fragment into a method whose name explains the purpose of
344the method.}
345
346\explanation{Inline Method}{A method's body is just as clear as its name.}{Put
347the method's body into the body of its callers and remove the method.}
348
349\explanation{Inline Temp}{You have a temp that is assigned to once with a simple
350expression, and the temp is getting in the way of other refactorings.}{Replace
351all references to that temp with the expression}
352
353% Moving Features Between Objects
354\explanation{Move Method}{A method is, or will be, using or used by more
355features of another class than the class on which it is defined.}{Create a new
356method with a similar body in the class it uses most. Either turn the old method
357into a simple delegation, or remove it altogether.}
358
359\explanation{Move Field}{A field is, or will be, used by another class more than
360the class on which it is defined}{Create a new field in the target class, and
361change all its users.}
362
363% Organizing Data
364\explanation{Replace Magic Number with Symbolic Constant}{You have a literal
365number with a particular meaning.}{Create a constant, name it after the meaning,
366and replace the number with it.}
367
368\explanation{Encapsulate Field}{There is a public field.}{Make it private and
369provide accessors.}
370
371\explanation{Replace Type Code with Class}{A class has a numeric type code that
8fae7b44 372does not affect its behavior.}{Replace the number with a new class.}
137e0e7b
EK
373
374\explanation{Replace Type Code with Subclasses}{You have an immutable type code
8fae7b44 375that affects the behavior of a class.}{Replace the type code with subclasses.}
137e0e7b
EK
376
377\explanation{Replace Type Code with State/Strategy}{You have a type code that
8fae7b44 378affects the behavior of a class, but you cannot use subclassing.}{Replace the
137e0e7b
EK
379type code with a state object.}
380
381% Simplifying Conditional Expressions
382\explanation{Consolidate Duplicate Conditional Fragments}{The same fragment of
8fae7b44 383code is in all branches of a conditional expression.}{Move it outside of the
137e0e7b
EK
384expression.}
385
386\explanation{Remove Control Flag}{You have a variable that is acting as a
387control flag fro a series of boolean expressions.}{Use a break or return
388instead.}
389
390\explanation{Replace Nested Conditional with Guard Clauses}{A method has
8fae7b44 391conditional behavior that does not make clear the normal path of
137e0e7b
EK
392execution.}{Use guard clauses for all special cases.}
393
8fae7b44 394\explanation{Introduce Null Object}{You have repeated checks for a null
137e0e7b
EK
395value.}{Replace the null value with a null object.}
396
397\explanation{Introduce Assertion}{A section of code assumes something about the
398state of the program.}{Make the assumption explicit with an assertion.}
399
400% Making Method Calls Simpler
401\explanation{Rename Method}{The name of a method does not reveal its
402purpose.}{Change the name of the method}
403
404\explanation{Add Parameter}{A method needs more information from its
405caller.}{Add a parameter for an object that can pass on this information.}
406
407\explanation{Remove Parameter}{A parameter is no longer used by the method
408body.}{Remove it.}
409
410%\explanation{Parameterize Method}{Several methods do similar things but with
411%different values contained in the method.}{Create one method that uses a
412%parameter for the different values.}
413
414\explanation{Preserve Whole Object}{You are getting several values from an
415object and passing these values as parameters in a method call.}{Send the whole
416object instead.}
417
418\explanation{Remove Setting Method}{A field should be set at creation time and
419never altered.}{Remove any setting method for that field.}
420
421\explanation{Hide Method}{A method is not used by any other class.}{Make the
422method private.}
423
8fae7b44
EK
424\explanation{Replace Constructor with Factory Method}{You want to do more than
425simple construction when you create an object}{Replace the constructor with a
137e0e7b
EK
426factory method.}
427
428% Dealing with Generalization
8fae7b44 429\explanation{Pull Up Field}{Two subclasses have the same field.}{Move the field
137e0e7b
EK
430to the superclass.}
431
432\explanation{Pull Up Method}{You have methods with identical results on
433subclasses.}{Move them to the superclass.}
434
8fae7b44 435\explanation{Push Down Method}{Behavior on a superclass is relevant only for
137e0e7b
EK
436some of its subclasses.}{Move it to those subclasses.}
437
438\explanation{Push Down Field}{A field is used only by some subclasses.}{Move the
439field to those subclasses}
440
441\explanation{Extract Interface}{Several clients use the same subset of a class's
8fae7b44 442interface, or two classes have part of their interfaces in common.}{Extract the
137e0e7b
EK
443subset into an interface.}
444
445\explanation{Replace Inheritance with Delegation}{A subclass uses only part of a
446superclasses interface or does not want to inherit data.}{Create a field for the
447superclass, adjust methods to delegate to the superclass, and remove the
448subclassing.}
449
450\explanation{Replace Delegation with Inheritance}{You're using delegation and
451are often writing many simple delegations for the entire interface}{Make the
452delegating class a subclass of the delegate.}
453
454\subsubsection{Composite refactorings}
455
456% Composing Methods
457% \explanation{Replace Method with Method Object}{}{}
458
459% Moving Features Between Objects
460\explanation{Extract Class}{You have one class doing work that should be done by
461two}{Create a new class and move the relevant fields and methods from the old
462class into the new class.}
463
464\explanation{Inline Class}{A class isn't doing very much.}{Move all its features
465into another class and delete it.}
466
467\explanation{Hide Delegate}{A client is calling a delegate class of an
468object.}{Create Methods on the server to hide the delegate.}
469
470\explanation{Remove Middle Man}{A class is doing to much simple delegation.}{Get
471the client to call the delegate directly.}
472
473% Organizing Data
474\explanation{Replace Data Value with Object}{You have a data item that needs
8fae7b44 475additional data or behavior.}{Turn the data item into an object.}
137e0e7b
EK
476
477\explanation{Change Value to Reference}{You have a class with many equal
478instances that you want to replace with a single object.}{Turn the object into a
479reference object.}
480
481\explanation{Encapsulate Collection}{A method returns a collection}{Make it
8fae7b44 482return a read-only view and provide add/remove methods.}
137e0e7b
EK
483
484% \explanation{Replace Array with Object}{}{}
485
486\explanation{Replace Subclass with Fields}{You have subclasses that vary only in
487methods that return constant data.}{Change the methods to superclass fields and
488eliminate the subclasses.}
489
490% Simplifying Conditional Expressions
491\explanation{Decompose Conditional}{You have a complicated conditional
492(if-then-else) statement.}{Extract methods from the condition, then part, an
493else part.}
494
495\explanation{Consolidate Conditional Expression}{You have a sequence of
496conditional tests with the same result.}{Combine them into a single conditional
497expression and extract it.}
498
499\explanation{Replace Conditional with Polymorphism}{You have a conditional that
8fae7b44 500chooses different behavior depending on the type of an object.}{Move each leg
137e0e7b
EK
501of the conditional to an overriding method in a subclass. Make the original
502method abstract.}
503
504% Making Method Calls Simpler
505\explanation{Replace Parameter with Method}{An object invokes a method, then
506passes the result as a parameter for a method. The receiver can also invoke this
507method.}{Remove the parameter and let the receiver invoke the method.}
508
509\explanation{Introduce Parameter Object}{You have a group of parameters that
510naturally go together.}{Replace them with an object.}
511
512% Dealing with Generalization
513\explanation{Extract Subclass}{A class has features that are used only in some
514instances.}{Create a subclass for that subset of features.}
515
516\explanation{Extract Superclass}{You have two classes with similar
517features.}{Create a superclass and move the common features to the
518superclass.}
519
520\explanation{Collapse Hierarchy}{A superclass and subclass are not very
521different.}{Merge them together.}
522
523\explanation{Form Template Method}{You have two methods in subclasses that
524perform similar steps in the same order, yet the steps are different.}{Get the
525steps into methods with the same signature, so that the original methods become
526the same. Then you can pull them up.}
527
528
529\subsection{Functional refactorings}
530
531\explanation{Substitute Algorithm}{You want to replace an algorithm with one
532that is clearer.}{Replace the body of the method with the new algorithm.}
00aa0588 533
b289552b 534\end{comment}
00aa0588
EK
535
536\section{The impact on software quality}
537
538\subsection{What is meant by quality?}
539The term \emph{software quality} has many meanings. It all depends on the
9a55a5bc
EK
540context we put it in. If we look at it with the eyes of a software developer, it
541usually mean that the software is easily maintainable and testable, or in other
542words, that it is \emph{well designed}. This often correlates with the
543management scale, where \emph{keeping the schedule} and \emph{customer
137e0e7b
EK
544satisfaction} is at the center. From the customers point of view, in addition to
545good usability, \emph{performance} and \emph{lack of bugs} is always
546appreciated, measurements that are also shared by the software developer. (In
547addition, such things as good documentation could be measured, but this is out
548of the scope of this document.)
9a55a5bc 549
00aa0588 550\subsection{The impact on performance}
9a55a5bc
EK
551\begin{quote}
552 Refactoring certainly will make software go more slowly, but it also makes the
00aa0588 553 software more amenable to performance tuning.~\cite{refactoring} % page 69
9a55a5bc 554\end{quote}
ee45c41f
EK
555
556\noindent There is a common belief that refactoring compromises performance, due
557to increased degree of indirection and that polymorphism is slower than
9a55a5bc
EK
558conditionals.
559
00aa0588 560In a survey, Demeyer~\cite{demeyer2002} disproves this view in the case of
9a55a5bc
EK
561polymorphism. He is doing an experiment on, what he calls, ``Transform Self Type
562Checks'' where you introduce a new polymorphic method and a new class hierarchy
563to get rid of a class' type checking of a ``type attribute``. He uses this kind
564of transformation to represent other ways of replacing conditionals with
565polymorphism as well. The experiment is performed on the C++ programming
00aa0588
EK
566language and with three different compilers and platforms. \todo{But is the
567result better?} Demeyer concludes that, with compiler optimization turned on,
568polymorphism beats middle to large sized if-statements and does as well as
569case-statements. (In accordance with his hypothesis, due to similarities
570between the way C++ handles polymorphism and case-statements.)
ee45c41f 571
9a55a5bc
EK
572\begin{quote}
573 The interesting thing about performance is that if you analyze most programs,
574 you find that they waste most of their time in a small fraction of the code.
00aa0588 575 ~\cite{refactoring}
9a55a5bc 576\end{quote}
9a55a5bc 577
ee45c41f
EK
578\noindent So, although an increased amount of method calls could potentially
579slow down programs, one should avoid premature optimization and sacrificing good
580design, leaving the performance tuning until after profiling\footnote{For and
581 example of a Java profiler, check out VisualVM:
582 \url{http://visualvm.java.net/}} the software and having isolated the actual
583 problem areas.
00aa0588 584
00aa0588 585\section{Composite refactorings} \label{intro_composite}
f3a108c3
EK
586\todo{motivation, examples, manual vs automated?, what about refactoring in a
587very large code base?}
6065c96c 588Generally, when thinking about refactoring, at the mechanical level, there are
f65da046
EK
589essentially two kinds of refactorings. There are the \emph{primitive}
590refactorings, and the \emph{composite} refactorings. A primitive refactoring can
6065c96c
EK
591be defined like this:
592
f65da046
EK
593\definition{A primitive refactoring is a refactoring that cannot be expressed in
594terms of other refactorings.}
595
ee45c41f 596\noindent Examples are the \emph{Pull Up Field} and \emph{Pull Up Method}
f65da046 597refactorings~\cite{refactoring}, that moves members up in their class
ee45c41f
EK
598hierarchies.
599
600A composite refactoring is more complex, and can be defined like this:
f65da046 601
6065c96c 602\definition{A composite refactoring is a refactoring that can be expressed in
f65da046
EK
603terms of two or more primitive refactorings.}
604
ee45c41f 605\noindent An example of a composite refactoring is the \emph{Extract Superclass}
6065c96c 606refactoring~\cite{refactoring}. In its simplest form, it is composed of the
f65da046 607previously described primitive refactorings, in addition to the \emph{Pull Up
6065c96c
EK
608Constructor Body} refactoring~\cite{refactoring}. It works by creating an
609abstract superclass that the target class(es) inherits from, then by applying
610\emph{Pull Up Field}, \emph{Pull Up Method} and \emph{Pull Up Constructor Body}
ddcea0b5
EK
611on the members that are to be members of the new superclass. For an overview of
612the \emph{Extract Superclass} refactoring, see figure
613\ref{fig:extractSuperclass}.
6065c96c 614
ddcea0b5
EK
615\begin{figure}[h]
616 \centering
faa9f4f3 617 \includegraphics[angle=270,width=\linewidth]{extractSuperclassItalic.pdf}
ddcea0b5
EK
618 \caption{The Extract Superclass refactoring}
619 \label{fig:extractSuperclass}
620\end{figure}
6065c96c
EK
621
622\section{Manual vs. automated refactorings}
623Refactoring is something every programmer does, even if he or she does not known
f65da046
EK
624the term \emph{refactoring}. Every refinement of source code that does not alter
625the program's behavior is a refactoring. For small refactorings, such as
626\emph{Extract Method}, executing it manually is a manageable task, but is still
627prone to errors. Getting it right the first time is not easy, considering the
628signature and all the other aspects of the refactoring that has to be in place.
629
630Take for instance the renaming of classes, methods and fields. For complex
631programs these refactorings are almost impossible to get right. Attacking them
632with textual search and replace, or even regular expressions, will fall short on
633these tasks. Then it is crucial to have proper tool support that can perform
634them automatically. Tools that can parse source code and thus has semantic
635knowledge about which occurrences of which names that belongs to what construct
636in the program. For even trying to perform one of these complex task manually,
637one would have to be very confident on the existing test suite \see{tdd}.
00aa0588 638
f65da046
EK
639\section{Correctness of refactorings}
640\todo{Volker's example?}
641For automated refactorings to be truly useful, they must show a high degree of
642behavior preservation. This might seem obvious, but there are examples of
ee45c41f
EK
643refactorings in existing tools that break programs. \todo{More than Eclipse?} I
644will now present an example of an \emph{Extract Method} refactoring followed by
645a \emph{Move Method} refactoring that breaks a program. The following piece of
646code shows the target for the composed refactoring:
00aa0588 647
ddcea0b5
EK
648\begin{minted}[linenos]{java}
649public class C {
650 public X x = new X();
ee45c41f 651
ddcea0b5
EK
652 public void f() {
653 x.m(this);
654 x.n();
655 }
656}
657\end{minted}
ee45c41f
EK
658
659\noindent The next piece of code shows the destination of the refactoring. Note
3510e539
EK
660that the method \method{m(C c)} of class \type{C} assigns to the field \var{x}
661of the argument \var{c} that has type \type{C}:
ee45c41f
EK
662
663\begin{minted}{java}
664public class X {
665 public void m(C c) {
666 c.x = new X();
667 }
668 public void n() {}
669}
670\end{minted}
671
672The refactoring sequence works by extracting line 5 and 6 from the original
3510e539
EK
673class \type{C} into a method \method{f} with the statements from those lines as
674its method body. The method is then moved to the class \type{X}. The result is
ee45c41f
EK
675shown in the following two pieces of code:
676
677\begin{minted}[linenos]{java}
678public class C {
679 public X x = new X();
680
681 public void f() {
682 x.f(this);
683 }
684}
685\end{minted}
686
687\begin{minted}[linenos]{java}
688public class X {
689 public void m(C c) {
690 c.x = new X();
691 }
692 public void n() {}
693 public void f(C c) {
694 m(c);
695 n();
696 }
697}
698\end{minted}
699
3510e539
EK
700Since, after the refactoring, the method \method{f} of class \type{C} calls the
701method \method{f} of class \type{X}, the program breaks. (See line 5 of the
702version of class \type{C} after the refactoring.) Before the refactoring, the
703methods \method{m} and \method{n} of class \type{X} are called on different
704object instances (see line 5 and 6 of the original class \type{C}). After, they
705are called on the same object, and the statement on line 3 in the class \type{X}
706after the refactoring no longer have any effect in our example.
ddcea0b5 707
f65da046
EK
708\section{Test Driven Development}\label{tdd}
709
710\section{Software metrics}
00aa0588
EK
711
712%\part{The project}
713%\chapter{Planning the project}
714%\part{Conclusion}
715%\chapter{Results}
716
b0e80574 717
3b7c1d90
EK
718
719\chapter{\ldots}
720\todo{write}
721\section{The problem statement}
3f929fcc
EK
722\section{Choosing the target language}
723Choosing which programming language to use as the target for manipulation is not
724a very difficult task. The language have to be an object-oriented programming
725language, and it must have existing tool support for refactoring. The
726\emph{Java} programming language\footnote{\url{https://www.java.com/}} is the
727dominating language when it comes to examples in the literature of refactoring,
728and is thus a natural choice. Java is perhaps, currently the most influential
729programming language in the world, with its \emph{Java Virtual Machine} that
730runs on all of the most popular architectures and also supports\footnote{They
731compile to java bytecode.} dozens of other programming languages, with
732\emph{Scala}, \emph{Clojure} and \emph{Groovy} as the most prominent ones. Java
733is currently the language that every other programming language is compared
734against. It is also the primary language of the author of this thesis.
735
736\section{Choosing the tools}
737When choosing a tool for manipulating Java, there are certain criterias that
738have to be met. First of all, the tool should have some existing refactoring
739support that this thesis can build upon. Secondly it should provide some kind of
740framework for parsing and analyzing Java source code. Third, it should itself be
741open source. This is both because of the need to be able to browse the code for
742the existing refactorings that is contained in the tool, and also because open
743source projects hold value in them selves. Another important aspect to consider
744is that open source projects of a certain size, usually has large communities of
745people connected to them, that are commited to answering questions regarding the
746use and misuse of the products, that to a large degree is made by the cummunity
747itself.
748
749There is a certain class of tools that meet these criterias, namely the class of
750\emph{IDEs}\footnote{\emph{Integrated Development Environment}}. These are
751proagrams that is ment to support the whole production cycle of a cumputer
752program, and the most popular IDEs that support Java, generally have quite good
753refactoring support.
754
755The main contenders for this thesis is the \emph{Eclipse
756IDE}\footnote{\url{http://www.eclipse.org/}}, with the \emph{Java development
757tools} (JDT), the \emph{IntelliJ IDEA Community
758Edition}\footnote{\url{http://www.jetbrains.com/idea/}} and the \emph{NetBeans
759IDE}\footnote{\url{https://netbeans.org/}}. Eclipse and NetBeans are both free,
760open source and community driven, while the IntelliJ IDEA has an open sourced
761community edition that is free of charge, but also offer an \emph{Ultimate
6018eec9 762Edition} with an extended set of features, at additional cost. All three IDEs
3f929fcc 763supports adding plugins to extend their functionality and tools that can be used
6018eec9 764to parse and analyze Java source code. \todo{investigate if this is true} But
3f929fcc 765one of the IDEs stand out as a favorite, and that is the \emph{Eclipse IDE}.
6018eec9
EK
766This is the most popular~\cite{javaReport2011} among them and seems to be de
767facto standard IDE for Java development regardless of platform.
3b7c1d90 768
5837a41f
EK
769\chapter{Refactorings in Eclipse JDT: Design, Shortcomings and Wishful
770Thinking}\label{ch:jdt_refactorings}
771
772This chapter will deal with some of the design behind refactoring support in
773Eclipse, and the JDT in specific. After which it will follow a section about
774shortcomings of the refactoring API in terms of composition of refactorings. The
775chapter will be concluded with a section telling some of the ways the
776implementation of refactorings in the JDT could have worked to facilitate
777composition of refactorings.
055dca93 778
b0e80574 779\section{Design}
f041551b 780The refactoring world of Eclipse can in general be separated into two parts: The
b289552b 781language independent part and the part written for a specific programming
07e173d4
EK
782language -- the language that is the target of the supported refactorings.
783\todo{What about the language specific part?}
f041551b
EK
784
785\subsection{The Language Toolkit}
786The Language Toolkit, or LTK for short, is the framework that is used to
787implement refactorings in Eclipse. It is language independent and provides the
788abstractions of a refactoring and the change it generates, in the form of the
789classes \typewithref{org.eclipse.ltk.core.refactoring}{Refactoring} and
790\typewithref{org.eclipse.ltk.core.refactoring}{Change}. (There is also parts of
791the LTK that is concerned with user interaction, but they will not be discussed
792here, since they are of little value to us and our use of the framework.)
793
794\subsubsection{The Refactoring Class}
795The abstract class \type{Refactoring} is the core of the LTK framework. Every
796refactoring that is going to be supported by the LTK have to end up creating an
797instance of one of its subclasses. The main responsibilities of subclasses of
798\type{Refactoring} is to implement template methods for condition checking
799(\methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkInitialConditions}
800and
801\methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{checkFinalConditions}),
802in addition to the
803\methodwithref{org.eclipse.ltk.core.refactoring.Refactoring}{createChange}
07e173d4
EK
804method that creates and returns an instance of the \type{Change} class.
805
806If the refactoring shall support that others participate in it when it is
807executed, the refactoring has to be a processor-based
808refactoring\typeref{org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring}.
809It then delegates to its given
810\typewithref{org.eclipse.ltk.core.refactoring.participants}{RefactoringProcessor}
811for condition checking and change creation.
f041551b
EK
812
813\subsubsection{The Change Class}
07e173d4
EK
814This class is the base class for objects that is responsible for performing the
815actual workspace transformations in a refactoring. The main responsibilities for
816its subclasses is to implement the
817\methodwithref{org.eclipse.ltk.core.refactoring.Change}{perform} and
818\methodwithref{org.eclipse.ltk.core.refactoring.Change}{isValid} methods. The
819\method{isValid} method verifies that the change object is valid and thus can be
820executed by calling its \method{perform} method. The \method{perform} method
821performs the desired change and returns an undo change that can be executed to
822reverse the effect of the transformation done by its originating change object.
823
61420ef7 824\subsubsection{Executing a Refactoring}\label{executing_refactoring}
07e173d4
EK
825The life cycle of a refactoring generally follows two steps after creation:
826condition checking and change creation. By letting the refactoring object be
827handled by a
828\typewithref{org.eclipse.ltk.core.refactoring}{CheckConditionsOperation} that
829in turn is handled by a
830\typewithref{org.eclipse.ltk.core.refactoring}{CreateChangeOperation}, it is
831assured that the change creation process is managed in a proper manner.
832
833The actual execution of a change object has to follow a detailed life cycle.
834This life cycle is honored if the \type{CreateChangeOperation} is handled by a
835\typewithref{org.eclipse.ltk.core.refactoring}{PerformChangeOperation}. If also
836an undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} is set
837for the \type{PerformChangeOperation}, the undo change is added into the undo
838history.
055dca93 839
b0e80574 840\section{Shortcomings}
80663734 841This section is introduced naturally with a conclusion: The JDT refactoring
5837a41f
EK
842implementation does not facilitate composition of refactorings.
843\todo{refine}This section will try to explain why, and also identify other
844shortcomings of both the usability and the readability of the JDT refactoring
845source code.
80663734
EK
846
847I will begin at the end and work my way toward the composition part of this
848section.
849
5837a41f 850\subsection{Absence of Generics in Eclipse Source Code}
80663734
EK
851This section is not only concerning the JDT refactoring API, but also large
852quantities of the Eclipse source code. The code shows a striking absence of the
853Java language feature of generics. It is hard to read a class' interface when
5837a41f
EK
854methods return objects or takes parameters of raw types such as \type{List} or
855\type{Map}. This sometimes results in having to read a lot of source code to
856understand what is going on, instead of relying on the available interfaces. In
857addition, it results in a lot of ugly code, making the use of typecasting more
858of a rule than an exception.
859
860\subsection{Composite Refactorings Will Not Appear as Atomic Actions}
861
862\subsubsection{Missing Flexibility from JDT Refactorings}
863The JDT refactorings are not made with composition of refactorings in mind. When
864a JDT refactoring is executed, it assumes that all conditions for it to be
865applied successfully can be found by reading source files that has been
866persisted to disk. They can only operate on the actual source material, and not
867(in-memory) copies thereof. This constitutes a major disadvantage when trying to
868compose refactorings, since if an exception occur in the middle of a sequence of
869refactorings, it can leave the project in a state where the composite
870refactoring was executed only partly. It makes it hard to discard the changes
871done without monitoring and consulting the undo manager, an approach that is not
872bullet proof.
873
874\subsubsection{Broken Undo History}
875When designing a composed refactoring that is to be performed as a sequence of
876refactorings, you would like it to appear as a single change to the workspace.
877This implies that you would also like to be able to undo all the changes done by
878the refactoring in a single step. This is not the way it appears when a sequence
879of JDT refactorings is executed. It leaves the undo history filled up with
880individual undo actions corresponding to every single JDT refactoring in the
881sequence. This problem is not trivial to handle in Eclipse. (See section
882\ref{hacking_undo_history}.)
883
884\section{Wishful Thinking}
80663734 885
80663734 886
b0e80574
EK
887
888\chapter{Composite Refactorings in Eclipse}
889
890\section{A Simple Ad Hoc Model}
891As pointed out in chapter \ref{ch:jdt_refactorings}, the Eclipse JDT refactoring
892model is not very well suited for making composite refactorings. Therefore a
893simple model using changer objects (of type \type{RefaktorChanger}) is used as
894an abstraction layer on top of the existing Eclipse refactorings.
895
896\section{The Extract and Move Method Refactoring}
61420ef7
EK
897%The Extract and Move Method Refactoring is implemented mainly using these
898%classes:
899%\begin{itemize}
900% \item \type{ExtractAndMoveMethodChanger}
901% \item \type{ExtractAndMoveMethodPrefixesExtractor}
902% \item \type{Prefix}
903% \item \type{PrefixSet}
904%\end{itemize}
905
906\subsection{The Building Blocks}
907This is a composite refactoring, and hence is built up using several primitive
908refactorings. These basic building blocks are, as its name implies, the Extract
909Method Refactoring \cite{refactoring} and the Move Method Refactoring
910\cite{refactoring}. In Eclipse, the implementations of these refactorings are
911found in the classes
912\typewithref{org.eclipse.jdt.internal.corext.refactoring.code}{ExtractMethodRefactoring}
913and
914\typewithref{org.eclipse.jdt.internal.corext.refactoring.structure}{MoveInstanceMethodProcessor},
915where the last class is designed to be used together with the processor-based
916\typewithref{org.eclipse.ltk.core.refactoring.participants}{MoveRefactoring}.
917
918\subsubsection{The ExtractMethodRefactoring Class}
919This class is quite simple in its use. The only parameters it requires for
920construction is a compilation
921unit\typeref{org.eclipse.jdt.core.ICompilationUnit}, the offset into the source
922code where the extraction shall start, and the length of the source to be
923extracted. Then you have to set the method name for the new method together with
924which access modifier that shall be used and some not so interesting parameters.
925
926\subsubsection{The MoveInstanceMethodProcessor Class}
927For the Move Method the processor requires a little more advanced input than
928the class for the Extract Method. For construction it requires a method
929handle\typeref{org.eclipse.jdt.core.IMethod} from the Java Model for the method
930that is to be moved. Then the target for the move have to be supplied as the
931variable binding from a chosen variable declaration. In addition to this, one
932have to set some parameters regarding setters/getters and delegation.
933
934To make a whole refactoring from the processor, one have to construct a
935\type{MoveRefactoring} from it.
b0e80574
EK
936
937\subsection{The ExtractAndMoveMethodChanger Class}
61420ef7
EK
938The \typewithref{no.uio.ifi.refaktor.changers}{ExtractAndMoveMethodChanger}
939class, that is a subclass of the class
940\typewithref{no.uio.ifi.refaktor.changers}{RefaktorChanger}, is the class
941responsible for composing the \type{ExtractMethodRefactoring} and the
942\type{MoveRefactoring}. Its constructor takes a project
943handle\typeref{org.eclipse.core.resources.IProject}, the method name for the new
944method and a \typewithref{no.uio.ifi.refaktor.utils}{SmartTextSelection}.
945
946A \type{SmartTextSelection} is basically a text
947selection\typeref{org.eclipse.jface.text.ITextSelection} object that enforces
948the providing of the underlying document during creation. I.e. its
949\methodwithref{no.uio.ifi.refaktor.utils.SmartTextSelection}{getDocument} method
950will never return \type{null}.
951
952Before extracting the new method, the possible targets for the move operation is
953found with the help of an
954\typewithref{no.uio.ifi.refaktor.extractors}{ExtractAndMoveMethodPrefixesExtractor}.
72b64328
EK
955The possible targets is computed from the prefixes that the extractor returns
956from its
61420ef7
EK
957\methodwithref{no.uio.ifi.refaktor.extractors.ExtractAndMoveMethodPrefixesExtractor}{getSafePrefixes}
958method. The changer then choose the most suitable target by finding the most
72b64328
EK
959frequent occurring prefix among the safe ones. The target is the type of the
960first part of the prefix.
61420ef7
EK
961
962After finding a suitable target, the \type{ExtractAndMoveMethodChanger} first
963creates an \type{ExtractMethodRefactoring} and performs it as explained in
964section \ref{executing_refactoring} about the execution of refactorings. Then it
965creates and performs the \type{MoveRefactoring} in the same way, based on the
966changes done by the Extract Method refactoring.
967
b0e80574 968\subsection{The ExtractAndMoveMethodPrefixesExtractor Class}
61420ef7 969This extractor extracts properties needed for building the Extract and Move
72b64328
EK
970Method refactoring. It searches through the given selection to find safe
971prefixes, and those prefixes form a base that can be used to compute possible
972targets for the move part of the refactoring. It finds both the candidates, in
973the form of prefixes, and the non-candidates, called unfixes. All prefixes (and
974unfixes) are represented by a
975\typewithref{no.uio.ifi.refaktor.extractors}{Prefix}, and they are collected
976into prefix sets.\typeref{no.uio.ifi.refaktor.extractors.PrefixSet}.
977
978The prefixes and unfixes are found by property
979collectors\typeref{no.uio.ifi.refaktor.extractors.collectors.PropertyCollector}.
980A property collector follows the visitor pattern \cite{dp} and is of the
981\typewithref{org.eclipse.jdt.core.dom}{ASTVisitor} type. An \type{ASTVisitor}
982visits nodes in an abstract syntax tree that forms the Java document object
983model. The tree consists of nodes of type
984\typewithref{org.eclipse.jdt.core.do}{ASTNode}.
985
986\subsubsection{The PrefixesCollector}
987The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{PrefixesCollector}
988is of type \type{PropertyCollector}. It visits expression
989statements\typeref{org.eclipse.jdt.core.dom.ExpressionStatement} and creates
990prefixes from its expressions in the case of method invocations. The prefixes
991found is registered with a prefix set, together with all its sub-prefixes.
992\todo{Rewrite in the case of changes to the way prefixes are found}
993
994\subsubsection{The UnfixesCollector}
995The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{UnfixesCollector}
996finds unfixes within the selection. An unfix is a name that is assigned to
997within the selection. The reason that this cannot be allowed, is that the result
998would be an assignment to the \type{this} keyword, which is not valid in Java.
999
1000\subsubsection{Computing Safe Prefixes}
1001A safe prefix is a prefix that does not enclose an unfix. A prefix is enclosing
1002an unfix if the unfix is in the set of its sub-prefixes. As an example,
1003\texttt{``a.b''} is enclosing \texttt{``a''}, as is \texttt{``a''}. The safe
1004prefixes is unified in a \type{PrefixSet} and can be fetched calling the
1005\method{getSafePrefixes} method of the
1006\type{ExtractAndMoveMethodPrefixesExtractor}.
61420ef7 1007
b0e80574 1008\subsection{The Prefix Class}
72b64328 1009\todo{?}
b0e80574
EK
1010\subsection{The PrefixSet Class}
1011
5837a41f
EK
1012\subsection{Hacking the Refactoring Undo
1013History}\label{hacking_undo_history}
8fae7b44
EK
1014\todo{Where to put this section?}
1015
1016As an attempt to make multiple subsequent changes to the workspace appear as a
1017single action (i.e. make the undo changes appear as such), I tried to alter
1018the undo changes\typeref{org.eclipse.ltk.core.refactoring.Change} in the history
1019of the refactorings.
1020
1021My first impulse was to remove the, in this case, last two undo changes from the
f041551b
EK
1022undo manager\typeref{org.eclipse.ltk.core.refactoring.IUndoManager} for the
1023Eclipse refactorings, and then add them to a composite
8fae7b44
EK
1024change\typeref{org.eclipse.ltk.core.refactoring.CompositeChange} that could be
1025added back to the manager. The interface of the undo manager does not offer a
1026way to remove/pop the last added undo change, so a possible solution could be to
1027decorate \cite{dp} the undo manager, to intercept and collect the undo changes
f041551b
EK
1028before delegating to the \method{addUndo}
1029method\methodref{org.eclipse.ltk.core.refactoring.IUndoManager}{addUndo} of the
8fae7b44
EK
1030manager. Instead of giving it the intended undo change, a null change could be
1031given to prevent it from making any changes if run. Then one could let the
1032collected undo changes form a composite change to be added to the manager.
1033
1034There is a technical challenge with this approach, and it relates to the undo
1035manager, and the concrete implementation
1036UndoManager2\typeref{org.eclipse.ltk.internal.core.refactoring.UndoManager2}.
1037This implementation is designed in a way that it is not possible to just add an
1038undo change, you have to do it in the context of an active
1039operation\typeref{org.eclipse.core.commands.operations.TriggeredOperations}.
1040One could imagine that it might be possible to trick the undo manager into
1041believing that you are doing a real change, by executing a refactoring that is
1042returning a kind of null change that is returning our composite change of undo
1043refactorings when it is performed.
1044
1045Apart from the technical problems with this solution, there is a functional
1046problem: If it all had worked out as planned, this would leave the undo history
1047in a dirty state, with multiple empty undo operations corresponding to each of
1048the sequentially executed refactoring operations, followed by a composite undo
1049change corresponding to an empty change of the workspace for rounding of our
1050composite refactoring. The solution to this particular problem could be to
1051intercept the registration of the intermediate changes in the undo manager, and
1052only register the last empty change.
1053
1054Unfortunately, not everything works as desired with this solution. The grouping
1055of the undo changes into the composite change does not make the undo operation
1056appear as an atomic operation. The undo operation is still split up into
1057separate undo actions, corresponding to the change done by its originating
1058refactoring. And in addition, the undo actions has to be performed separate in
1059all the editors involved. This makes it no solution at all, but a step toward
1060something worse.
1061
1062There might be a solution to this problem, but it remains to be found. The
1063design of the refactoring undo management is partly to be blamed for this, as it
1064it is to complex to be easily manipulated.
1065
b0e80574 1066
9ff90080
EK
1067\backmatter{}
1068\printbibliography
055dca93 1069\listoftodos
9ff90080 1070\end{document}