2. Refactoring: definizione
“Refactoring is the process of changing a software
system in such a way that it does not alter the external
behavior of the code yet improves its internal
structure.”
Martin Fowler
3. I principi del refactoring:
• Migliorare il design del codice
• Eliminare le duplicazioni (ridurre la quantità di
codice)
• Rendere il codice più leggibile e facile da modificare
4. package com.sourcesense.refactoring.workshop;
import java.util.Iterator;
import java.util.List;
public class CaloriesCalculator {
private List<Food> foods;
private final Person person;
public CaloriesCalculator(Person person, List<Food> foods) {
this.person = person;
this.foods = foods;
}
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */ *
person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
5. Le regole:
• Tempo a disposizione: 20 minuti
• I test devono restare verdi
• I test non possono essere modificati.
(Ad esempio non puoi modificare i parametri di
input e output, mentre puoi creare nuovi oggetti
usati “internamente”
6. Magic numbers
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */
* person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
7. Uso delle costanti parziale
public Person(String name, int kg) {
this.name = name;
this.kg = kg;
}
public String getName() {
return name;
}
public int getKg() {
return kg;
}
}
public int size() {
if (kg > 130)
return 3;
if (kg < 50)
return 1;
return MEDIUM_SIZE;
}
8. Nomi di variabili metodi e classi
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer
*/ * person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
9. Cicli for
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */ *
person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
10. Responsabilità
1. Costruzione del report
...
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one
kilometer */ * person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
11. Responsabilità
2. Calcolo delle calorie
...
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */ *
person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
12. Responsabilità
3.Validazione
...
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */ * person.size() /
cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
13. Validazione: posizione e ripetizione
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one kilometer */ *
person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}
14. Accesso ai field privati
public String result() throws Exception {
String string = quot;Diet Report for quot; + person.getName() +quot;:nquot;;
double cal = 0.0;
for (int i = 0; i < foods.size(); i++) {
Food food = foods.get(i);
string += food.name + quot; - quot; + food.kg + quot;nquot;;
if (quot;quot;.equalsIgnoreCase(food.name)) throw new
FirstException();
if (quot;applequot;.equals(food.name)) cal += food.kg * 15 * 10;
if (quot;magicPillquot;.equals(food.name)) cal -= 10;
if (quot;candyquot;.equals(food.name)) cal += food.kg;
}
string += quot;Total: quot; + cal + quot; kcalnquot;;
string += quot;kilometers to be run: quot; + 90 /* calories in one
kilometer */ * person.size() / cal;
for (Iterator iterator = foods.iterator(); iterator.hasNext();) {
Food type = (Food) iterator.next();
if (quot;quot;.equalsIgnoreCase(type.name)) throw new FirstException();
if (person.getKg() > 1000) throw new SecondException();
}
return string;
}
}