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