Week 3 - 4 Refactoring
Week 3 - 4 Refactoring
Week 3 - 4 Refactoring
Two questions:
1.How do we fix our software?
2.How do we know our software is “bad”… when it works fine!
Coming up: Refactoring
Refactoring
• Definition: Refactoring modifies software to improve
its readability, maintainability, and extensibility
without changing what it actually does.
• External behavior does NOT change
• Internal structure is improved
Customer c = findCustomer(...);
...
if (customer == null) {
name = “occupant”
} else {
name = customer.getName()
}
if (customer == null) {
…
------------------------------------------------------------
Customer c = findCustomer()
name = c.getName()
Motivation: You have a conditional that chooses different behavior depending on the type of
an object.
Technique: Move each leg of the conditional to an overriding method in a subclass. Make
the original method abstract.
double getSpeed() {
switch (_type) {
case EUROPEAN:
return getBaseSpeed();
case AFRICAN:
return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
case NORWEGIAN_BLUE:
return (_isNailed) ? 0 : getBaseSpeed(_voltage);
} throw new RuntimeException ("Should be unreachable");
}
• Code smells are bad things done in code, somewhat like bad patterns
in code
• Many people have tied code smells to the specific refactorings to fix
the smell
• Should they be used all the time? You should always think about
them, but only apply them when they make sense… sometimes you
need a long method… but think about it to make sure!
• Also:
• Rename Method
• Change Method Parameters
3. Extract Class
• Break one class into two, e.g. Having the phone details as part of the Customer class is not a
realistic OO model, and also breaks the Single Responsibility design principle. We can refactor this
into two separate classes, each with the appropriate responsibility.
double getPayAmount() {
double result;
if (isDead) result = deadAmount();
else {
if (isSeparated) result = separatedAmount();
else {
if (isRetired) result = retiredAmount();
else result = normalPayAmount();
}
}
return result;
}
double getPayAmount() {
if (isDead) return deadAmount();
if (isSeparated) return separatedAmount();
if (isRetired) return retiredAmount();
return normalPayAmount();
};
14. Replace Parameter with Explicit Method
• You have a method that runs different code depending on the values of an enumerated
parameter. Create a separate method for each value of the parameter.
public TriviaData()
{
data = new ArrayList<TriviaQuestion>();
}
public TriviaQuestion()
{
question = "";
answer = "";
value = 0;
type = FREEFORM;
}
public TriviaGame()
{
// Load questions
questions = new TriviaData();
questions.addQuestion("The possession of more than two sets of chromosomes is termed?",
"polyploidy", 3, TriviaQuestion.FREEFORM);
questions.addQuestion("Erling Kagge skiied into the north pole alone on January 7, 1993.",
"F", 1, TriviaQuestion.TRUEFALSE);
questions.addQuestion("1997 British band that produced 'Tub Thumper'",
"Chumbawumba", 2, TriviaQuestion.FREEFORM);
questions.addQuestion("I am the geometric figure most like a lost parrot",
"polygon", 2, TriviaQuestion.FREEFORM);
questions.addQuestion("Generics were introducted to Java starting at version 5.0.",
"T", 1, TriviaQuestion.TRUEFALSE);
}
TriviaGame.java
// Main game loop
public static void main(String[] args)
{
int score = 0; // Overall score
int questionNum = 0; // Which question we're asking
TriviaGame game = new TriviaGame();
Scanner keyboard = new Scanner(System.in);
// Ask a question as long as we haven't asked them all
while (questionNum < game.questions.numQuestions())
{
// Show question
game.questions.showQuestion(questionNum);
// Get answer
String answer = keyboard.nextLine();
// Validate answer
TriviaQuestion q = game.questions.getQuestion(questionNum);
if (q.type == TriviaQuestion.TRUEFALSE)
{
if (answer.charAt(0) == q.answer.charAt(0))
{
System.out.println("That is correct! You get " + q.value + " points.");
score += q.value;
}
else
{
System.out.println("Wrong, the correct answer is " + q.answer);
}
}
TriviaGame.java
else if (q.type == TriviaQuestion.FREEFORM)
{
if (answer.toLowerCase().equals(q.answer.toLowerCase()))
{
System.out.println("That is correct! You get " + q.value + " points.");
score += q.value;
}
else
{
System.out.println("Wrong, the correct answer is " + q.answer);
}
}
System.out.println("Your score is " + score);
questionNum++;
}
System.out.println("Game over! Thanks for playing!");
}
}