Refactoring - University of Arizona

Download Report

Transcript Refactoring - University of Arizona

Small changes to code to improve it
1
Refactoring Defined
 A change made to the internal structure of software to
make it easier to understand and cheaper to modify
without changing its observable behavior —
Refactoring, Martin Fowler. et. al. , page 53
 Martin wrote the book:
Refactoring
Improving the Design of Existing Code
 Refactoring owes a lot to a Refactoring: William
Opdyke's PhD thesis
2
Write Drafts and Revise
 All good writing is based upon revision.
— Jacques Barzun, Simple & Direct, 4th Edition
 Revision means "to look at again"
 Example: Before 4-July, 1776, Thomas Jefferson's draft of
the Declaration of Independence had this
"We hold these truths to be sacred and undeniable, ..."
 He let his friend Benjamin Franklin look over this draft to
make changes including this:
"We hold these truths to be self-evident, ..."
 Total of 47 revisions, then Congress made 39 more
http://www.weeklyreader.com/googledocs/pdfs/revisionfiles.pdf
3
Refactoring Happens
 In larger systems (frameworks), code will be read and
modified more frequently than it will be written
 Refactoring typically involves
 Removing duplicated or dead code
 Simplifying complex code
 Clarifying unclear code
 It turns out that removing code can actually be a good
thing: your system has fewer lines of code
 Easier to develop, maintain, and change
 Refactoring can be risky, unless you do it in small steps and
have automated tests that can be run anytime
4
A few examples
 A few refactorings we've seen (they have names)
 Encapsulate Field (do this virtually always)
 add getters and/or setters to access a field
 Rename Method (often)
 Extract SuperClass (recall Shape and Fruit)
 You have two classes with similar features
 Create a superclass and move common features to the superclass
 Compose Method
 A variety of refactorings can happen at the method level
5
Composed Method
 Some refactoring attempts to "compose" methods
 A composed method is relatively short by using calls to
a small number of coherent elements
 Easier to understand what the method does
 Some refactorings for composing methods
 Extract Method: replace complex code with a nice name
 Inline Method: use code that's as easy to read as method
 Code demo: Compose insertElement in
ArrayPriorityList
6
Before
public void insertElementAt(int index, E el) {
// If need to grow array, grow it
if (size() == data.length) {
Object[] temp = new Object[data.length + 20];
for (int i = 0; i < size; i++)
temp[i] = data[i];
data = temp;
}
// Shift array elements right to make room
for (int j = size; j > index; j--) {
data[j] = data[j - 1];
}
// Add new element at the provided index
data[index] = el;
size++;
}
7
After
public void insertElementAt(int index, E el) {
if (shouldGrowArray())
gowArray();
makeRoomAt(index);
addAt(index, el);
}
 Is the new insertElementAt more readable?
 Vote: Yes: ____
Nay: _____
 Are the extra private methods in the way?
 Vote: Yes: ____ Nay: _____
8
private void addAt(int index, E el) {
data[index] = el;
size++;
}
private void makeRoomAt(int index) {
for (int j = size; j > index; j--) {
data[j] = data[j - 1];
}
}
private void gowArray() {
Object[] temp = new Object[data.length + 20];
for (int i = 0; i < size; i++)
temp[i] = data[i];
data = temp;
}
9
Replace Nested Conditional
with Guard Clauses see link
private int boggleScoreOf(String word) {
int sum = 0;
if (next.length() == 3 || next.length() == 4)
sum = 1;
else if (next.length() == 5)
sum = 2;
else if (next.length() == 6)
sum = 3;
else if (next.length() == 7)
sum = 5;
else if (next.length() >= 8)
sum = 11;
else
sum = 0;
return sum;
}
10
Refactoring Catalog
 Buy the book or check out Martin's Refactoring
Catalog from the refactoring page
http://www.refactoring.com/
 Find catalog link and then find and read Inline
Method
 Before test 2 read all 27 Refactorings on the next slide
to prepare for the test 2 on Thursday 18-Nov
11
Some of these will be on test
1. Add Parameter
15. Remove Double Negative
2. Collapse
Hierarchy
16. Replace Assignment with Initialization

3. Consolidate Conditional
17. Replace Conditional with
 Read the following refactorings
from
Expression
Polymorphism
4. Consolidate
Duplicate
18. Replace Inheritance with Delegation
http://www.refactoring.com/catalog/index.html
(liste
Conditional Fragments
19. Replace Iteration with Recursion
d here in alphabetic order)
5. Decompose Conditional
20.Remove Control Flag
6. Encapsulate Collection
21. Replace Error Code with Exception
7. Encapsulate Field
22. Replace Exception with Test

8. Extract
Class
23. Replace Magic Number with Symbolic
9. Extract Method
Constant
Modifier
10. Extract Superclass
24. Replace Nested Conditional with
11. Hide Method
Guard Clauses
12. Inline Method
25. Replace Recursion with Iteration
13. Parameterize Method
26. Reverse Conditional
Pull up Field
27. Separate Query from Modifier
14. Pull Up Method
12
A dozen questions like this
g) Which design is better, I or II? Why?
I
void printOwing() {
printBanner();
// print details
System.out.println("name:
System.out.println("amount
}
" + _name);
" + getOutstanding());
II
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails (double outstanding) {
System.out.println ("name:
" + _name);
System.out.println ("amount
" + outstanding);
}
13
Answer
g) II
Why?
If you have a code fragment that can be grouped
together, use Extract Method to turn the fragment into
a method whose name explains the purpose of the
method
14