Refactoring
-
Upload
gianluca-demichelis -
Category
Documents
-
view
29 -
download
3
description
Transcript of Refactoring
Refactoring
Migliorare il design di codice già scritto
Una modifica alla struttura interna di un software al fine di renderlo più facile da capire e meno costoso da modificare, senza alterare il suo comportamento osservabile.
Il refactoring è la ristrutturazione del software attraverso l’applicazione di una serie di semplici metodologie, che vedremo nella presentazione (e che, per inciso, sono chiamate anche esse “refactoring”).
Cosa è il refactoring?
2refactoring
Perché il refactoring?
Perché dovrei fare refactoring?
In che modo il refactoring mi aiuta?
Migliora il design del software
Rende più comprensibile il software
Aiuta a trovare i bachi
Aiuta a programmare più in fretta
Programmi difficili da capire sono anche difficili da modificare
Programmi con logica duplicata sono difficili da modificare
Programmi con logica condizionale complessa sono difficili da modificare
3refactoring
Quando fare refactoring?
• quando si aggiunge una funzione• quando si deve risolvere un baco• quando si fa del code-review
Regole di massima• quando si incontra del codice duplicato• quando si trovano funzioni / procedure / metodi lunghi• quando una classe diventa troppo grande• quando si incontrano metodi con tanti parametri nella firma• quando ci si accorge che una classe dovrebbe subire evoluzioni divergenti• quando si incontrano problemi con i tipi primitivi (es. BAS di S.I.M.-G.)• quando ci sono istruzioni “switch”.• gerarchie di classi parallele (es. catasto urbano / catasto rurale)• gerarchie prolisse (troppe classi)• quando si trovano troppi commenti 4refactoring
Categorie di interventi
• Refactoring a livello di metodo• Spostamento di funzionalità tra oggetti• Organizzazione dei dati• Semplificazione delle espressioni condizionali• Semplificazione delle chiamate ai metodi• Generalizzazione• Grossi interventi (BIG REFACTORING)
5refactoring
Refactoring a livello di metodo Extract method Metodi troppo lunghi, codice duplicato: occorre
raccogliere una parte di codice in un metodo proprio.
void printOwing() {
printBanner();
//print details
System.out.println ("name: " + _name);
System.out.println ("amount " + getOutstanding());
}
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails (double outstanding) {
System.out.println ("name: " + _name);
System.out.println ("amount " + outstanding);
}
6refactoring
Refactoring a livello di metodo Introduce explaining variable Se si ha un’espressione complessa e ricorrente, inserire il
risultato dell’espressione (o di parti di essa) in una variabile temporanea che ne spieghi il significato.
if ((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0 ) {
// do something
}
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if (isMacOs && isIEBrowser && wasInitialized() && wasResized) {
// do something
}
7refactoring
Refactoring a livello di metodo Replace method with Method object Si ha un metodo lungo su cui non si può operare con extract
method perché fa uso di tante variabili locali: si trasforma il metodo in un oggetto, le variabili locali diventano attributi dell’oggetto. A questo punto si può operare una decomposizione internamente all’oggetto.
class Order...
double price() {
double primaryBasePrice;
double secondaryBasePrice;
double tertiaryBasePrice;
// long computation; ...
}
8refactoring
Spostamento di funzionalità tra oggetti Move method Un metodo usa (o userebbe volentieri) funzioni o attributi
di una classe che non è la sua: si crei un metodo nella seconda classe, si renda il metodo di partenza una chiamata al nuovo metodo o lo si elimini.
9refactoring
Spostamento di funzionalità tra oggetti Extract Class Si ha una classe che fa il lavoro che dovrebbero fare due
classi diverse: si crei una nuova classe e si spostino gli attributi e i metodi rilevanti.
10refactoring
Spostamento di funzionalità tra oggetti Hide delegate Un utilizzatore chiama una classe delegata di un oggetto: si
crei un metodo nell’oggetto in modo da nascondere la classe delegata.
11refactoring
Organizzazione dei dati
Replace data value with Object Si ha un dato che ha (o potrebbe avere) dati o
comportamenti addizionali: si trasformi il dato in un oggetto proprio.
12refactoring
Organizzazione dei dati Replace array with Object Si ha un array in cui elementi diversi possono avere
significati diversi: sostituite l’array con un oggetto che abbia un attributo per ogni elemento dell’array.
String[] row = new String[3];
row [0] = "Liverpool";
row [1] = "15";
Performance row = new Performance();
row.setName("Liverpool");
row.setWins("15"); 13refactoring
Organizzazione dei dati Replace type code with Subclasses Si ha un “type code” immutabile che influenza che
influenza il comportamento di una classe: si sostituisca il “type code” con delle sottoclassi.
14refactoring
Semplificazione delle espressioni condizionali
Decompose conditional Si hanno delle espressioni condizionali complicate: si
estraggano metodi dalla condizione e dalle parti “then” ed “else”.
if (date.before (SUMMER_START) || date.after(SUMMER_END))
charge = quantity * _winterRate + _winterServiceCharge;
else
charge = quantity * _summerRate;
if (notSummer(date))
charge = winterCharge(quantity);
else
charge = summerCharge (quantity);
15refactoring
Semplificazione delle espressioni condizionali Replace nested conditional with guard clauses Un metodo presenta un comportamento condizionale che non rende
chiaro la sequenza di esecuzione: si usino guard clauses.
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();
};
16refactoring
Semplificazione delle espressioni condizionali Replace conditional with polymorphism Si ha un’espressione condizionale che discrimina diversi comportamenti
sul tipo di un oggetto: si creino sottoclassi e si sposti il comportamento condizionale in ognuna delle classi derivate.
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");
}
17refactoring
Semplificazione delle chiamate ai metodi
Rename method
Cambiare il nome dei metodi in modo che il nome sia esplicativo della funzione del metodo.
18refactoring
Semplificazione delle chiamate ai metodi Add parameter / Remove parameter Un metodo ha bisogno di più informazioni dal chiamante: si
aggiunga un parametro alla firma.
Un parametro non è più usato all’interno di un metodo: lo si rimuova dalla firma.
19refactoring
Semplificazione delle chiamate ai metodi
Preserve whole object Si recuperano vari attributi da un oggetto e li si usa
come parametri per un metodo: si passi direttamente l’oggetto come unico parametro.
20refactoring
Generalizzazione
Pull up field / Pull up method Due sottoclassi hanno lo stesso attributo: lo si sposti
nella classe padre
Due sottoclassi hanno un metodo con lo stesso comportamento: si sposti il metodo nella classe padre.
21refactoring
Generalizzazione Push down field / Push down method Un attributo è usato solo da una delle sottoclassi: si
sposti l’attributo nella sottoclasse
Un metodo è significativo solo per una delle sottoclassi: si sposti il metodo nella sottoclasse.
22refactoring
Generalizzazione Extract subclass Una classe ha delle funzionalità che sono usato solo
per alcune istanze della classe: si crei una sottoclasse che incorpori queste funzionalità e le si rimuova dalla classe iniziale.
23refactoring
Grossi interventi Rimozione ereditarietà Si ha una gerarchia che esegue due compiti alla volta: si creino
due gerarchie e si usi la delega per i comportamenti voluti
24refactoring
Conversione da procedurale a oggetti Si ha del codice scritto con un approccio procedurale: si
trasformino i dati in oggetti, si scompongano le procedure e si spostino le parti nei metodi degli oggetti creati.
Grossi interventi
Separazione del modello dalla presentazione Si hanno delle classi GUI che contengono logica / algoritmi che
apparterrebbero al modello: si estragga la logica dall’interfaccia in classi di dominio separate.
25refactoring
Estrazione di una gerarchia Si ha una classe che sta eseguendo troppi compiti, almeno in
parte attraverso diverse istruzioni condizionali: si crei una gerarchia di classi in cui ogni sottoclasse rappresenta un caso specifico.
Concetti chiave
Piccoli passi (a meno dei “grossi interventi”)
Uso estensivo dello unit-testing
Separazione netta tra refactoring e sviluppo di funzionalità
Lavoro di gruppo (code review ufficioso e frequente / Pair programming)
Coraggio e fiducia + buone abitudini
26refactoring
27
Grazie per l’attenzione!
refactoring