Fare il Refactoring del codice

Refactoring is making changes to a body of code in order to improve its internal structure, without changing its external behaviour

Così M. Fowler definisce l’operazione di refactoring nel suo libro e nei suoi interventi in quest’ambito.

Refactoring è il processo per modificare un sistema software in modo tale da migliorare la struttura interna del codice senza alterarne il comportamento esterno” .

Ma la domanda che ci si pone spesso è: “ma vale davvero la pena di perder tempo a fare refactoring, dal momento che non si modificano le performance dell’applicazione?”.

Domanda forse legittima…per chi scrive codice col solo intento di vederlo “girare” una o due volte e basta più. Diversamente la risposta non può che essere ASSOLUTAMENTE SI!

E molto spesso non è neppure vero che il comportamento resta totalmente invariato; spesso, infatti, una buona operazione di refactoring comporta un miglioramento del programma dovuto ad una revisione di codice scritto (e capita spesso) in maniera poco ottimizzata o con sporcizie varie rimaste nello specifico metodo inutilmente.

Fare refactoring quindi è utile ed è buona norma nello sviluppo di una qualsiasi tipologia di applicativo software (ancor più se si lavora in team): rende più comprensibile e manutenibile il software migliorandone, e allungandone, in tal maniera, il proprio ciclo di vita.

Altro elemento, inoltre, che gioca ancora a favore del refactoring è il supporto che oramai un po’ tutti gli IDE danno a questo processo.

Vediamone un esempio in Visual Studio prendendo, come esempio, la classe Program.cs della solution HelloNHibernate discussa nell’articolo precedente Il primo progetto con Hibernate.

Ricordo che la classe contiene un metodo statico Main() che si occupa di leggere da un database l’elenco dei fornitori e dei prodotti archiviati; successivamente inserisce un nuovo fornitore ed un nuovo prodotto, quindi effettua nuovamente la lettura dei dati dal db per verificare il corretto inserimento degli stessi.

Il codice della classe è:

 

class Program

{

static void Main(string[] args)

{

//Istanzio due variabili locali per l’accesso al DAO

SupplierDAO suppDao = new SupplierDAO();

ProductDAO prodDao = new ProductDAO();

//Leggo i Suppliers memorizzati nel database

IList suppliers = suppDao.GetSupplier();

//Li stampo in console

Console.WriteLine(“***** Elenco Fornitori : ***** “);

foreach (Supplier supplier in suppliers)

{

Console.WriteLine(“LastName= “ + supplier.LastName + ” |
FirstName= “
+ supplier.FirstName + ” | BusinessName= “
+ supplier.BusinessName);

Console.WriteLine(“Address= “ + supplier.Address +
” | Phone= ”
+ supplier.Phone + ” | E-mail= “
+ supplier.Mail);

Console.WriteLine(“”);

}

//Leggo i Product memorizzati nel database

IList products = prodDao.GetProducts();

//Li stampo in console

Console.WriteLine***** Elenco Prodotti : *****

foreach (Product product in products)

{

Console.WriteLine(“Name= “+product.Name+” | Category= “
+ product.Category + ” | Pieces= “ + product.PiecesInStock
+ ” | Price= “ + product.Price);

Console.WriteLine(“Produttore= “+product.Supplier.BusinessName);

Console.WriteLine();

}

Console.ReadKey();

//Creo un nuovo Supplier

Supplier newsupplier = new Supplier();

newsupplier.FirstName = “Giovanni”;

newsupplier.LastName = “Girino”;

newsupplier.BusinessName = “Il miglior pollo”;

newsupplier.CreatedOn = DateTime.Now;

newsupplier.Address = “Via dell’Aia, 23″;

//E lo salvo nel database

suppDao.SaveSupplier(newsupplier);

//Creo un nuovo prodotto

Product newproduct = new Product();

newproduct.Category = “Food”;

newproduct.Name = “Pollo”;

newproduct.PiecesInStock = 8;

newproduct.Price = new decimal(2.35);

newproduct.Supplier = newsupplier;

//E lo salvo nel database

prodDao.SaveProduct(newproduct);

//Adesso rileggo i Suppliers memorizzati nel database

suppliers = suppDao.GetSupplier();

//Li stampo in console

Console.WriteLine***** Elenco Fornitori Aggiornato: *****

foreach (Supplier supplier in suppliers)

{

Console.WriteLine(“LastName= “ + supplier.LastName + ” |
FirstName= “
+supplier.FirstName+” | BusinessName= “ +
supplier.BusinessName );

Console.WriteLine(“Address= “ + supplier.Address+ ” | Phone= “
+ supplier.Phone + ” | E-mail= “ + supplier.Mail);

Console.WriteLine(“”);

}

//Leggo i Product memorizzati nel database

products = prodDao.GetProducts();

//Li stampo in console

Console.WriteLine***** Elenco Prodotti Aggiornato: *****

foreach (Product product in products)

{

Console.WriteLine(“Name= “+product.Name+” | Category= “
+ product.Category + ” | Pieces= “ +product.PiecesInStock
+ | Price= “ + product.Price + ” | Supplier = “ +
product.Supplier.BusinessName);

Console.WriteLine(“”);

}

Console.ReadKey();

}

Come si vede il metodo è molto lungo, il che lo rende molto poco leggibile, e vi è pure codice ripetuto.

Proviamo quindi a migliorare le cose: per prima cosa selezioniamo la parte relativa alla lettura dei forniti dal database ed alla stampa della lista in Console; ciccando col tasto destro del mouse scegliendo: “Extract Method si aprirà una finestra nella quale si deve inserire solamente il nome del metodo (i parametri vengono generati implicitamente), scegliendo, quindi, di chiamare il nuovo metodo readAndViewSupplier il risultato sarà:

private static readAndViewSuppliers(SupplierDAO suppDao)

{

//Leggo i Suppliers memorizzati nel database

IList suppliers = suppDao.GetSupplier();

//Li stampo in console

Console.WriteLine(“***** Elenco Fornitori : *****”);

foreach (Supplier supplier in suppliers)

{

Console.WriteLine(“LastName= “ + supplier.LastName +
” | FirstName= “
+supplier.FirstName+” | BusinessName= “
+ supplier.BusinessName);

Console.WriteLine(“Address= “+supplier.Address+” | Phone= “
+ supplier.Phone + ” | E-mail= “ + supplier.Mail);

Console.WriteLine(“”);

}

}

OSS: Per convenzione i nomi dei metodi privati, si scrivono in minuscolo, mentre quelli pubblici in maiuscolo.

 

Stesso procedimento operiamo per la lettura dei prodotti:

 

private static readAndViewProduct(ProductDAO prodDao)

{

//Leggo i Product memorizzati nel database

IList products = prodDao.GetProducts();

//Li stampo in console

Console.WriteLine(“***** Elenco Prodotti : *****”);

foreach (Product product in products)

{

Console.WriteLine(“Name= “+product.Name+” | Category= “ +
product.Category + ” | Pieces= “ + product.PiecesInStock +
” | Price= ”
+ product.Price);

Console.WriteLine(“Produttore = “ + product.Supplier.BusinessName);

Console.WriteLine();

}

}

 

Quindi estraiamo un metodo per l’inserimento del nuovo fornitore al quale, per comodità, passiamo i valori dei campi come parametri:

 

private static Supplier createNewSupplier(string name, string lastname, string businessname, string address)

{

//Creo un nuovo Supplier

Supplier newsupplier = new Supplier();

newsupplier.FirstName = name;

newsupplier.LastName = lastname;

newsupplier.BusinessName = businessname;

newsupplier.CreatedOn = DateTime.Now;

newsupplier.Address = address;

return newsupplier;

}

ed analogamente operiamo l’inserimento del nuovo prodotto:

 

private static Product createNewProduct(string category,
string
name,int pieces,decimal price,Supplier newsupplier)

{

Product newproduct = new Product();

newproduct.Category = category;

newproduct.Name = name;

newproduct.PiecesInStock = pieces;

newproduct.Price = price;

newproduct.Supplier = newsupplier;

return newproduct;

}

 

Con queste semplici e brevi operazioni effettuate sul metodo abbiamo ridotto il codice della classe a:

 

class Program

{

static void Main(string[] args)

{

//Istanzio due variabili locali per l’accesso al DAO

SupplierDAO suppDao = new SupplierDAO();

ProductDAO prodDao = new ProductDAO();

readAndViewSuppliers(suppDao);

readAndViewProduct(prodDao);

//Creo un nuovo Supplier

Supplier newsupplier = createNewSupplier(“Giovanni”,
“Girino”, “Il miglior pollo”, “Via dell’Aia, 23″);

//E lo salvo nel database

suppDao.SaveSupplier(newsupplier);

//Creo un nuovo prodotto

Product newproduct = createNewProduct(“Food”,“Pollo”,8,2.35,newsupplier);

//E lo salvo nel database

prodDao.SaveProduct(newproduct);

//Adesso rileggo i Suppliers memorizzati nel database

readAndViewSuppliers(suppDao);

//Leggo i Product memorizzati nel database

readAndViewProduct(prodDao);

Console.ReadKey();

}

 

che indubbiamente risulta più semplice da leggere e da manutenere in una revisione futura.

Refactoring it was easy doing …

Una Risposta

  1. Complimenti, ottimo articolo chiaro e ben scritto; ottima l’idea di evidenziare il passaggio dalla teoria alla pratica

Lascia un commento