Refactoring

27
Refactoring Migliorare il design di codice già scritto

description

A power-point presentation of the basic concept of refactoring

Transcript of Refactoring

Page 1: Refactoring

Refactoring

Migliorare il design di codice già scritto

Page 2: Refactoring

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

Page 3: Refactoring

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

Page 4: Refactoring

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

Page 5: Refactoring

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

Page 6: Refactoring

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

Page 7: Refactoring

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

Page 8: Refactoring

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

Page 9: Refactoring

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

Page 10: Refactoring

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

Page 11: Refactoring

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

Page 12: Refactoring

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

Page 13: Refactoring

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

Page 14: Refactoring

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

Page 15: Refactoring

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

Page 16: Refactoring

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

Page 17: Refactoring

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

Page 18: Refactoring

Semplificazione delle chiamate ai metodi

Rename method

Cambiare il nome dei metodi in modo che il nome sia esplicativo della funzione del metodo.

18refactoring

Page 19: Refactoring

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

Page 20: Refactoring

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

Page 21: Refactoring

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

Page 22: Refactoring

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

Page 23: Refactoring

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

Page 24: Refactoring

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.

Page 25: Refactoring

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.

Page 26: Refactoring

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

Page 27: Refactoring

27

Grazie per l’attenzione!

refactoring