noun: a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior
verb: to restructure software by applying a series of refactorings without changing its observable behavior
MARTIN FOWLER DEFINITION (AUTHOR OF REFACTORING.COM)
Refactoring isn't another word for cleaning up code - it specifically defines one technique for improving the health of a code-base. I use "restructuring" as a more general term for reorganizing code that may incorporate other techniques.
It’s like I want to go 100 miles east but instead of just traipsing through the woods, I’m going to drive 20 miles north to the highway and then I’m going to go 100 miles east at three times the speed I could have if I just went straight there. When people are pushing you to just go straight there, sometimes you need to say, “Wait, I need to check the map and find the quickest route.” The preparatory refactoring does that for me.
Refactoring involves changing things, hence it can (and so it will!) introduce problems.
Be ready for them, take the opportunity to automate tests, do it in small incremental steps, etc.
EXAMPLES????
Extract code to new/other method/classes
Move methods
Rename methods/objects/attributes
add attributes to classes/methods
Change Classes Structure
Move a method from class A to class B if uses/is being used by more features in class B
Introduce Null Object
Imagine in your software you are always checking if instances of an object are null:
Customer c = findCustomer(...);
...
if (customer == null) {
name = "occupant";
} else {
name = customer.getName();
}
...
if (customer == null) {
...
}
Duplicating code, makes it more difficult to be maintained, more complex, more difficult to be understood
Introduce Null Object
public class NullCustomer extends Customer {
public String getName() {
return “occupant”
}
------------------------------------------------------------
Customer c = findCustomer()
name = c.getName()
Switch Statements
Switch Statements
class Animal {
final int MAMMAL = 0, BIRD = 1, REPTILE = 2;
int myKind; // set in constructor
...
String getSkin() {
switch (myKind) {
case MAMMAL: return "hair";
case BIRD: return "feathers";
case REPTILE: return "scales";
default: return "integument";
}
}
}
Switch Statements
class Animal {
final int MAMMAL = 0, BIRD = 1, REPTILE = 2;
int myKind; // set in constructor
...
String getSkin() {
switch (myKind) {
case MAMMAL: return "hair";
case BIRD: return "feathers";
case REPTILE: return "scales";
default: return "integument";
}
}
}
class Animal {
String getSkin() { return "integument"; }
}
class Mammal extends Animal {
String getSkin() { return "hair"; }
}
class Bird extends Animal {
String getSkin() { return "feathers"; }
}
class Reptile extends Animal {
String getSkin() { return "scales"; }
}
- Adding a new animal type, such as Amphibian, does not require revising and recompiling existing code - Mammals, birds, and reptiles are likely to differ in other ways, and we’ve already separated them out (so we won’t need more switch statements) - We’ve gotten rid of the flags we needed to tell one kind of animal from another - Basically, we’re now using Objects the way they were meant to be used
Advantages:
Bad Smells: is a term coined by Martin Fowler
https://sourcemaking.com/refactoring/smells
https://sourcemaking.com/refactoring/smells
5.D.1 and 5.D.2
CODE REVIEWS
CODE ANALYSIS
DEFECT ANALYSIS
(EXAMPLE: LINTERS)