Miglioramento della qualità del software con attività di refactoring
Transcript
Miglioramento della qualità del software con attività di refactoring
Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in Ingegneria del Softwer Miglioramento della qualità del software con attività di refactoring Anno Accademico 2015/2016 Candidato: Giovanni Montanile matr. N46/0001061 “Ai mie gentori , a tutte le per sone che hanno credutto in me” Indice Introduzione, Capitolo 1: Refactoring, 1.1Bad code smells, 1.2Il Modello di qualità, Capitolo 2: Refactoring e Analisi codice sorgente, 5 7 8 10 14 2.1 Strumenti di Refactory e Analisi, 2.2 AppPerfect java code, 2.3 Esempio Calendario, 2.3.1 Test, 2.3.2 Qualità del proramma prima, 2.3.3 Attività di refactoring, 2.3.4 Test regressivo, 2.3.5 Qualità del programma dopo, Conclusioni, 14 14 15 18 19 22 34 34 37 Bibliografia, 38 Miglioramento della qualità del software con attività di refactoring Introduzione Se ci ritrovassimo coinvolti nella realizzazione di un progetto software, la qualità del codice sorgente non sarebbe certamente il primo problema al quale rivolgeremo i nostri pensieri. Al contrario, cercheremo di rendere il progetto funzionante, di rispettare tutte le richieste espresse dal cliente. Testando il nostro prodotto, sarà possbile notare i numerosi errori che sono stati compiuti a discapito della qualità del nostro codice sorgente. La pulizia del codice dovrebbe essere, invece, un processo da utilizzare durante la stesura del software,la fase di testing e anche dopo il completamento del prodotto. Qualsiasi momento è buono per controllare se ciò che abbiamo scritto rispetta le leggi della “buona progettazione” migliorando cosi la qualità del codice sorgente. Per fare ciò viene usata l’attivita di recfatoring che permette di riscrivere il codice in modo manuale o semiautomatico cercando di individuare e eliminare i cosidetti “bad small” del codice. Tale processo migliora i parametri di legibilità, di manutenibilità, della riusabilità, della estendibilità del codice e la riduzione della sua complessità. La refactoring, molte volte, è paragonata alla pulizia della cucina , in cui si preparano diversi pasti al giorno per più di una manciata di persone, in 4 Miglioramento della qualità del software con attività di refactoring genere la pulizia e la riorganizzazione si verificano continuamente, esiste un responsabile dei piatti, delle pentole, della cucina stessa, del cibo, del frigorifero che deve tenere tutto pulito e organizzato , senza questo si avrebbe una cucina sporca e caotica inadeguta alla continua preparazione dei piatti. Per esempio si pensi alla nostra casa, dove possibile vedere gli effetti non banali di refactoring: come il non lavare le pentole subito dopo aver cucinato il cioccolato che porta da due secondi di risciacquo a 10 minuti di raschiamento e strofinamento aggressivo. 5 Miglioramento della qualità del software con attività di refactoring Capitolo 1: Refactoring Il refactoring é una tecnica di ristruturazione del codice sorgente di un sistema software che ha l’obiettivo di migliorarne la struttura interna, senza alterarne il comportamento esterno. Essa è una tecnica sistematica per ripulire il codice dai bad small code, riducendo al minimo le possibilità di introdurre bug . Esempi di refactoring sono: sostituire un identificatore poco chiaro con uno semanticamente più valido. spezzare un metodo lungo in più metodi compatti. trasformare un attributo pubblico in privato, fornendo gli opportuni metodi di accesso. L’attività di refactoring procede in modo sistematico applicando al codice una sequenza di “semplici” tecniche di refactoring di base, ognuna delle quali apporta una modifica al sistema portandolo da uno stato di partenza ad uno stato di arrivo, preservandone il suo comportamento o perlomeno non modificandone la conformità ai requisiti funzionali. 6 Miglioramento della qualità del software con attività di refactoring Il problema principale legato al refactoring è il suo impatto globale sul codice, ad esempio, se si sceglie di cambiare l’identificatore di un attributo, dovranno essere modificate tutte le parti del codice che fanno riferimento ad esso, dunque, se le modifiche non vengono effettuate correttamente, si rischia di portare il codice alla regressione. In altri termini, applicando il refactoring, si possono introdurre nel codice errori logici o sintattici che erano originariamente assenti. Per questo motivo, dopo ogni azione di refactoring, risulta importante effettuare un opportuno test di regressione, in modo da individuare ed eliminare immediatamente errori eventualmente introdotti. Inolte si può vericare che un prodotto software può migliorare o peggiorare la qualità del prodotto asseconda della metrica considerata. Ad esempio, se si considera un unico metodo che con una singola scansione effettua due operazioni su una collezione di oggetti può essere spezzato in due metodi più chiari che effettuano le stesse operazioni ma con due scansioni differenti , per tali ragioni si ha un miglioramento rispetto la metrica Cyclomatic Complexity ma un peggioramento rispetto la metrica Weighted methods per class. 1.1 Bad code smells Il termine code smells introdotto da Kent Beck nel libro “Refactoring” ha due significati: 7 Miglioramento della qualità del software con attività di refactoring Che gli smells sono subito individuabili in quanto solo guardando il codice è possibile individuere i problemi, come trovare un metodo che ha un numero di line di codice molto elevato. Che gli smells non sempre sono il problema ma indicatori di problema. Nome del gruppo Gli smell in gruppo Descrizione i Bloaters Bloaters sono codici, metodi e le classi che hanno aumentato di -Long Method proporzioni -Large Class gigantesche, che sono -Primitive Obsession difficili da lavorare. Di -Long Parameter List solito questi smells non affiorano subito, -DataClumps piuttosto si accumulano nel tempo, come si evolve programma Gli abusanti orientamento agli oggetti -Switch Statements -Temporary Field -Refused Bequest -Alternative Classes with Different Interfaces Sono quelle procedure che non rispettano i principi di orientameto a oggetti The Change Preventers -Divergent Change -Shotgun Surgery -Parallel Inheritance Hierarchies Questi odori significa che se avete bisogno di cambiare qualcosa in un posto nel codice, è necessario fare molti cambiamenti in altri posti. i Dispensables -Lazy class -Data class -Duplicate Code Codice che è superfluo cioè qualcosa inutile e non necessaria la cui 8 Miglioramento della qualità del software con attività di refactoring gli accoppiatori -Dead Code, -Speculative Generality assenza avrebbe reso il codice più pulito, più efficiente e più facile da capire -Feature Envy -Inappropriate Intimacy -Message Chains -Middle Man Codici che contribuiscono ad accoppiamento eccessiva tra le classi o mostrano cosa succede se l'accoppiamento è sostituita dalla delega. Tabella 1:Small code1 1.2 Il Modello di qualità Lo standard più utilizzato per la descrizione di un modello di qualità del software è lo standard ISO/IEC 9126. Esso è composto di 4 parti: 1. Quality Model: un insieme di caratteristiche di qualità che descrivono i fattori di qualità di un prodotto. 2. External Metrics: un insieme di metriche indirette attraverso le quali si può valutare la conformità di un prodotto in relazione all’ambiente operativo in cui si trova. 3. Internal Metrics: un insieme di metriche applicabili al software non eseguibile (come il codice sorgente), legate alle specifiche richieste dall’utente, che permettono di individuare eventuali problemi nelle metriche esterne, prima che il software sia eseguibile. 1 Mäntylä, M. V. and Lassenius, C. "Subjective Evaluation of Software Evolvability Using Code Smells: An Empirical Study". Journal of Empirical Software Engineering, vol. 11, no. 3, 2006, pp. 395-431 9 Miglioramento della qualità del software con attività di refactoring 4. Quality In Use Metrics: un insieme di metriche, dipendenti dalle metriche esterne ed interne, legate alle caratteristiche positive che un utente riscontra nell’utilizzo del software. Per determinare la qualità di un prodotto software si possono quindi osservare tre punti di vista: La qualità esterna è quella rappresentata dalle prestazioni del prodotto e dalle funzionalità che offre (il prodotto è visto come una black box da testare). – In sostanza, riguarda il comportamento “dinamico” del software in un dato ambiente operativo. – Va ricordato che il software non “funziona” mai da solo, ma è sempre parte di un ambiente , che può contenere hardware, persone, processi etc… – Le caratteristiche di qualità esterne del software lo qualificano in relazione a questo ambiente e permettono di osservarne il comportamento mentre è utilizzato operativamente. La qualità interna rappresenta le proprietà intrinseche del prodotto (quelle misurabili direttamente sul codice sorgente, sul suo flusso di controllo). Si realizza a partire da: – I requisiti di qualità dell'utente (External Quality Requirements), che rappresentano le specifiche di qualità così come le dà l’utente, fornendo il primo input alla progettazione. 10 Miglioramento della qualità del software con attività di refactoring – Le specifiche tecniche (Internal Quality Requirements), che rappresentano la qualità richiesta dall’utente tradotta dallo sviluppatore nell’architettura del software, nella struttura del programma, nelle interfacce del software verso l’utente. La qualità in uso riguarda il livello con cui il prodotto si dimostra utile all’utente nel suo effettivo contesto d’utilizzo, in particolare la capacità del prodotto di dare efficacia ed efficienza al lavoro dell’utente, a fronte di una sicurezza di utilizzo e di una soddisfazione nel far uso del prodotto. – In sostanza, è una misura dell’ interazione tra utente e prodotto, in un determinato contesto d’uso. I tre punti di vista si influenzano a vicenda, ma è ovvio che un prodotto software percepito positivamente dall’utente è sintomo di una buona qualità di base del codice sorgente. Per la misurazione della qualità nei vari punti di vista, vegono usate diverse metriche che sono in relazione al codice sorgente e si distinguono in: Nome metrica Physical lines Descrizione Numero di ritorni a capo. Deve essere un valore basso.. Numero di linee di commento. Deve essere un valore alto. Numero di linee di codice. Il progetto che possiede meno righe di codice ha un design superiore e richiede una manutenzione minore Numero di pacchetti. Comment lines Lines of code Packages 11 Miglioramento della qualità del software con attività di refactoring Classes Numero di classi. Confrontando progetti con le stesse funzionalità, il progetto che possiede più classi è quello che realizza l’astrazione migliore. Numero di files analizzati. Numero di directories analizzate Numero di metodi Numero di test. Tempo impiegato per effettuare un test. Numero di test falliti. Linee coperte dal test. Rami di un’espressione booleana coperti (true e false). Numero di linee duplicate Numero di regole violate Somma delle violazioni calcolate in base ad un coefficiente di priorità E’ calcolato come [100-(weighted_violations / nloc * 100)] E’ la posizione della classe all’interno dell’albero di eredità. Si consiglia di mantenere il numero dei livelli da attraversare per giungere la radice, al di sotto del 5. E’ il numero di tutti i metodi implementati da una classe più il numero di metodi accessibili tramite un oggetto della classe. Si consiglia di mantenere questo numero basso. Maggiore è la RFC, maggiore è lo sforzo dato per apportare modifiche. E’ il numero delle classi che utilizzano una classe. E’ il numero delle classi che una classe utilizza Essa misura il numero di componenti collegati ad una classe. Un valore basso indica che il codice è semplice da comprendere e riutilizzare. Un valore alto suggerisce di dividere la classe in classi più piccole. Si consiglia di effettuare un refactoring, Files Directories Methods Unit tests Unit tests duration Unit test error. Line coverage Branch coverage Duplicated lines Violations Weighted violations Rules compliance index Depth of inheritance tree Response for class Afferent couplings Efferent couplings Lack of cohesion of methods 12 Miglioramento della qualità del software con attività di refactoring se questo valore diventa maggiore di 2. E’ il numero medio di metodi contenuti in una classe. Si consiglia di mantenere tale numero al di sotto del valore 14. Essa misura il numero di cammini linearmente indipendenti all’interno di una parte di codice. Più il numero è alto, più lo sforzo per effettuare un testing del codice sarà alto. Si consiglia di mantenere questo numero al di sotto del valore 10. Rappresenta la distanza dalla linea ideale A+I=1. Identifica quanto una categoria è lontana dal caso ideale. Minore è la distanza del software dalla linea, maggiore è la sua qualità. Weighted methods per class Cyclomatic Complexity (CC) Distance Tabella 2 : Metriche 13 Miglioramento della qualità del software con attività di refactoring Capitolo 2: Refactoring e Analisi codice sorgente Il processo di refactoring è molto difficile e lungo se si esegue con un’ analisi solo visiva quindi é possibile trovare software che esaminano automaticamente il codice , riuscendo ad individuare i vari “ bad smell” e dare delle soluzioni; allo stesso modo è possibile verificare la qualità del prodotto sia prima che dopo l’eseguzione dell’ attivita di refactoring. Attraverso quest’ultima operazione emergeranno i vari miglioramenti o i peggioramenti della qualità del prodotto. 2.1 Strumenti di Refactory e Analisi Lo strumento che usereremo per la refactoring: AppPerfect java code é un software con licenza trial, un prodotto che può essere ridistribuito con validità di 15 giorni allo scadere di tali tempistiche per poter usufruire del prodotto bisognerà pagare. Per l’ analisi di qualità del codice sorgente useremo il programma: Stan4j che é open sorce, software il cui codice sorgente è messo a disposizione di tutti permettendone lo studio e la modifica. Entrambi possono essere intregati ad un ulteriore programma: eclipse. 14 Miglioramento della qualità del software con attività di refactoring 2.2 AppPerfect java code AppPerfect java code è un software di analisi statica del codice Java progettato per eseguire i seguenti compiti fondamentali: revisione automatica del codice java e implementazione di una corretta scrittura del codice; Le carateristiche fondamentali sono: o 750 regole di buona codifica che il codice deve rispettare , suddivisi in diverse aree funzionali come la sicurezza, l'ottimizzazione, la portabilità, i18n, possibili errori, standard di codifica, etc. o Oltre 180 Correzioni automatiche per le eventuali violazioni: Una volta che vengono rilevati errori, AppPerfect é in grado di correggere automaticamente più di 180 tipi di violazioni. È sufficiente rivedere e approvare le modifiche. o Metriche : forniscono informazioni dettagliate sui vari parametri per il codice sorgente come il numero di linee di codice, commenti linee, complessità di metodi, numero di metodi, ecc. Questa informazione è di vitale importanza per la conformità codice Java. o Esportazione rapporti : AppPerfect Java Code Analyzer fornisce un report che consente di individuare i problemi del codice e i suoi parametri. 15 Miglioramento della qualità del software con attività di refactoring 2.3 Esempio Calendario Consideriamo un semplice programma che fornendo una data in formato giorno,in mese in caratteri settimana se e anno ci restituisce il nome del giorno della è giusta la data, altrimenti il programma restituirà un messaggio di errore. Il codice è il seguente public class Calendario { public static String calend(int d, String ms, int a) { int m=0; if (ms=="gennaio") m=1; else if (ms=="febbraio") m=2; else if (ms=="marzo") m=3; else if (ms=="aprile") m=4; else if (ms=="maggio") m=5; else if (ms=="giugno") m=6; else if (ms=="luglio") m=7; else if (ms=="agosto") 16 Miglioramento della qualità del software con attività di refactoring m=8; else if (ms=="settembre") m=9; else if (ms=="ottobre") m=10; else if (ms=="novembre") m=11; else if (ms=="dicembre") m=12; if (d<1 || d>31 || m==0 || a<=1582) return "Errore"; boolean bisestile= (a%4==0); if (bisestile && a%100==0 && a%400!=0) bisestile=false; if ((m==2 && d>29)||(m==2 && d==29 && (!bisestile))) return "Errore"; if ((m==4 || m==6 || m==9 || m==11) && d>30) return "Errore"; if (m<=2) { m = m + 12; a--; }; int f1 = a / 4; int f2 = a / 100; int f3 = a / 400; int f4 = (int) (2 * m + (.6 * (m + 1))); int f5 = a + d + 1; 17 Miglioramento della qualità del software con attività di refactoring int x = f1 - f2 + f3 + f4 + f5; int k = x / 7; int n = x - k * 7; if (n==1) return "Lunedi"; else if (n==2) return "Martedi"; else if (n==3) return "Mercoledi"; else if (n==4) return "Giovedi"; else if (n==5) return "Venerdi"; else if (n==6) return "Sabato"; else if (n==0) return "Domenica"; else return "Errore"; } 2.3.1 Test Per testare le funzionalità del codice useremo tool di eclipse junit, che ci permette di testare il codice in maniera automatica inserendo i vari ingressi sia corretti che sbagliati, confrontandoli con i risultati che ci aspetteremo di ricevere rispetto all’ ingresso inserito. Questo stesso test lo utilizeremo come rigressione del programma dopo l’attivita di refactoring; 18 Miglioramento della qualità del software con attività di refactoring così andremo a verificare se le funzionalità del proramma sono ancora valide. Eseguimo il test: Figura 1: Test prima Da cio si può vedere che i vari test sono andati tutti a buon fine. 2.3.2 Qualità del proramma prima Analiziamo il programma prima dell’ attivita di refactoring tramite il plugin open sorce stan4j che ci permette di verificare tutte le connessioni tra metodi, le varie metriche fondamentali e le varie violazioni del programma . 19 Miglioramento della qualità del software con attività di refactoring Composition View La Composition View di questo progetto mostra che esso è composto semplicemente da un pacchetto, in cui ci sono due classi quella TestBlackBox composta da 22 metodi che Figura 2 : Composition View invocano l‘unica funzione della classe Calendario: la funzione calend(…). Metriche Stan4j copre un elevato numero di metriche. Le più interessanti per la nostra analisi sono quelle che ci consentono di individuare eventuali violazioni. Violazioni Metric calendario.Calendario.calend(...) calendario.Calendario.calend(...) Nel Value CC 39 ELOC 98 nostro caso abbiamo 39 violazioni nella metrica Cyclomatic Complexity e 98 violazioni nel Estimated Lines of Code. Visualiziamo il rapporto delle metriche 20 Miglioramento della qualità del software con attività di refactoring Metric Value Number of Libraries 2 Number of Packages 1 Number of Top Level Classes 2 Average Number of Top Level Classes per Package 2 Average Number of Member Classes per Class 0 Average Number of Methods per Class Average Number of Fields per Class Estimated Lines of Code 12.50 0 189 Estimated Lines of Code per Top Level Class Average Cyclomatic Complexity 94.50 2.52 Fat for Library Dependencies 0 Fat for Flat Package Dependencies 0 Fat for Top Level Class Dependencies 1 Tangled for Library Dependencies 0% Average Component Dependency between Libraries 0% Average Component Dependency between Packages 0% Average Component Dependency between Units 21 50% Miglioramento della qualità del software con attività di refactoring Average Distance 0 Average Absolute Distance 0 Average Weighted Methods per Class 31.50 Average Depth of Inheritance Tree 1 Average Number of Children 0 Average Coupling between Objects 1 Average Response for a Class Average Lack of Cohesion in Methods 22 13 126.50 Miglioramento della qualità del software con attività di refactoring 2.3.3 Attivita di refactoring Analiziamo ora il codice del sorgente tramite il programma AppPerfect Java code test , é un plugin di eclipse che viene visualizzato in questo modo: Figura 3: AppPerfect Java code Violazioni Il programma elenca le violazioni, che non rispettano le regole imposte per relizzare l’analisi, le quali sono state trovate nel file Java . Viene inoltre visualizzato il numero di riga in cui sono state osservate queste violazioni. Se un numero di riga viene cliccato, apre il file in editor di Eclipse con dato numero di riga evidenziata. Il menu pop-up contiene le opzioni di correzione automatica o ignora le violazioni. Auto-fix è la caratteristica in cui AppPerfect CodeTEST altera il codice sorgente per risolvere le violazioni. Ignora o una singola o tutte le violazioni di quel tipo, diventando sospesa. Le Violazioni che sono sospese 23 possono essere riattivate Miglioramento della qualità del software con attività di refactoring successivamente, in modo da riportarle indietro nella vista violazioni. Violazioni sospese Questo punto di vista elenca le violazioni che sono state sospese. Menu pop-up della vista contiene le opzioni per riattivare le violazioni sospese. Una volta riattivate le violazioni ritornano di nuovo nelle finestra delle violazioni. Violazioni Auto risolvibili Questo punto di vista è un sotto-insieme della vista violazioni. La finestra violazioni auto risolvibili elenca solo quelle violazioni che possono essere risolte automaticamente dal AppPerfect CodeTEST. Menu pop-up della vista. Contiene le opzioni per auto-fix che permette di visionare la soluzine per risolvere quel tipo di violazione. Metrica Essa mostra le Metriche statiche raccolte durante l'analisi: Classes Metrics numero di classi nel progetto,nei singoli packages. Class wise Blank Lines numero di righe vuote in singole classi. Class wise Commented Lines Commentate mostra il numero di righe di codice commentato nei singole classi. 24 Miglioramento della qualità del software con attività di refactoring Method Complexity conta complessità del metodo , come il numero totale di - if, for, while, do and switch che compaiono nel corpo del metodo. Questo aiuta a identificare i metodi che sono troppo complessi. Si può prendere in considerazione la rottura di un metodo troppo complesso in più metodi con minore complessità. Method Parameters numero di parametri dei singoli metodi Method numero di metodo per classe. Nested Block Depth numero massimo nidificazione che si trovano in un metodo. Non-static attributes numero di attributi non statici per classe. Static attributes numero di attributi statici per classe. Total Lines numero totale di linee. Sintesi del progetto Questo punto di vista ha due schede: - Violazioni di Gravità. - Violazioni Categoria. 25 Miglioramento della qualità del software con attività di refactoring Tramite grafico a torta che fornisce rapidamente un quadro chiaro di distribuzione di violazioni tra le categorie e gravità. I problemi Vista Problemi fornisce informazioni su gli errori di sintassi nel codice. Esportazione Risultati Una volta che l'analisi del codice è eseguito su progetto e diversi punti di vista sono visibili come spiegato sopra, è possibile esportare questo punto di vista in formati multipli. Regole Le regole che deve rispettare il codice sono organizzate dal AppPerfect Role Manager per gravità : Critical, High, Low, Medium a loro volta sono sudivise in categorie : 1. Optimization 2. OOPs 3. Garbage Collection 4. Code Convention 5. EJB 6. Security 7. Unused Code 8. Internationalization 9. Metrics 10. JSP Metrics 26 Miglioramento della qualità del software con attività di refactoring 11. Portability 12. 64 bits 13. Possible Errors 14. Java Docs 15. JSP 16. JUnit 17. Naming Convention 18. Servlet Rules 19. J2ME 20. Struts 21. Hibernate Tramite la guida é possibile visionare queste regole esempi e soluzioni. 27 con gli appositi Miglioramento della qualità del software con attività di refactoring Selezioniamo le regole che deve sodisfare il programma: Figura 4: AppPerfect Rule Manager 28 Miglioramento della qualità del software con attività di refactoring Analiziamo il programma rispetto a queste regole che abbiamo imposto, come quelle appartenenti alla categoria delle metrics e otteniamo questo: Figura 5: Report violazione codice AppPerfect Su questo rapporto é possibile vedere che il programma ha 111 linee di codice che violano le regole che abbiamo stabilito in precedenza . Per ciasuna regola vediamo come fare la refactoring, dove alcune sono risolte automaticamente dal programma come: Use_Equals_Instead_Equality_Operator Ci viene l’operatore sugerito di sostituire == con la funzione il metodo equals(“ ” ) della classe String Figura 6: Auto-fix user_Equals_Instead_Equality_Operator 29 Miglioramento della qualità del software con attività di refactoring Avoid_string_literals_except_in_constant_declarations Viene suggerito di convertire la stringa di carattere in una variabile costante in tutte le sue occorenze Figura7: Auto-Fix Avoid_string_literals_except_in_constant_dec larations Avoid_duplicate_string_literals Perchè viene usata una stringa di carattere più volte, viene suggerito di convertire la stringa in una variabile costante le occorenze Figura 8: Auto-Fix Avoid_duplicate_string_literals 30 e con essa tutte Miglioramento della qualità del software con attività di refactoring Altre hanno soluzioni tramite la guida con i rispettivi esempi e sugerimenti Maximum_number_of_return_statements Segnala la presenza di un grande numero di istruzioni return che aumentano la complessità del codice . public class MyClass { public boolean isNull ( Object s ) // VIOLATION { if ( s == null ) { return true; } return false; } } Soluzione public class MyClass { public boolean isNull ( Object s) // CORRECTION { return s == null ? true : false;}} sostituendo i vari return con un unico return. Maximum_complexity Indica che la complessità del programma, viene suggerita la divisione in più metodi quindi si va a estrarre pezzi di codice ricavando nuovi metodi tramite la funzionalità Extract Method notiva di eclipse. Maximum_number_of_nested_control_statements 31 Miglioramento della qualità del software con attività di refactoring Indica la presenza di if nidificati che aumenta la complessità del codice.La soluzione di questo problema é la creazione di un metodo nidificazioni vengono implementate come un ruten unico; prendiamo il codice del genere presente nel metodo: int m=0; if (ms=="gennaio") m=1; else if (ms=="febbraio") m=2; else if (ms=="marzo") m=3; else if (ms=="aprile") m=4; else if (ms=="maggio") m=5; else if (ms=="giugno") m=6; else if (ms=="luglio") m=7; else if (ms=="agosto") m=8; else if (ms=="settembre") m=9; else if (ms=="ottobre") m=10; else if (ms=="novembre") m=11; else if (ms=="dicembre") 32 dove le Miglioramento della qualità del software con attività di refactoring m=12; si costruisce una funzione di questo genere : private static int mesestring2num(String ms) { return ms.equals(GENNAIO)? 1: ms.equals(FEBBRAIO)? 2: ms.equals(MARZO)? 3: ms.equals(APRILE)? 4: ms.equals(MAGGIO)? 5: ms.equals(GIUGNO)? 6: ms.equals(LUGLIO)? 7: ms.equals(AGOSTO)? 8: ms.equals(SETTEMBRE)? 9: ms.equals(OTTOBRE) ? 10: ms.equals(NOVEMBRE)? 11: ms.equals(DICEMBRE)? 12:0 ; } 33 Miglioramento della qualità del software con attività di refactoring Dopo l’attivita di refactoring il codice si sarà trasformato in questo: public static String calend(int d, String ms, int a) { int m = mesestring2num(ms); return verifica(d, a, m)? giorno(d, a, m):ERRORE; } private static boolean verifica(int d, int a, int m) { boolean bisestile= (a%4==0); if (bisestile && a%100==0 && a%400!=0) bisestile=false; return !( d<1 || d>31 || m==0 || a<=1582 ||(m==2 && d>29) ||(m==2 && d==29 && !bisestile) ||(m==4 || m==6 || m==9 || m==11) && d>30); } 34 Miglioramento della qualità del software con attività di refactoring private static String giorno(int d, int a, int m) { int n = numgiorno(d, a, m); return n==1 ? LUNEDI: n==2 ? MARTEDI: n==3 ? MERCOLEDI: n==4 ? GIOVEDI: n==5 ? VENERDI: n==6 ? SABATO: n==0? DOMENICA: ERRORE; } private static int numgiorno(int d, int a, int m) { if (m<=2) { m = m + 12; a--; } int f1 = a / 4; int f2 = a / 100; int f3 = a / 400; int f4 = (int) (2 * m + (.6 * (m + 1))); int f5 = a + d + 1; int x = f1 - f2 + f3 + f4 + f5; int k = x / 7; int n = x - k * 7; 35 Miglioramento della qualità del software con attività di refactoring return n; } private static int mesestring2num(String ms) { return ms.equals(GENNAIO)? 1: ms.equals(FEBBRAIO)? 2: ms.equals(MARZO)? 3: ms.equals(APRILE)? 4: ms.equals(MAGGIO)? 5: ms.equals(GIUGNO)? 6: ms.equals(LUGLIO)? 7: ms.equals(AGOSTO)? 8: ms.equals(SETTEMBRE)? 9: ms.equals(OTTOBRE) ? 10: ms.equals(NOVEMBRE)? 11: ms.equals(DICEMBRE)? 36 Miglioramento della qualità del software con attività di refactoring 12:0 ; } } 2.3.4 Test regressivo Ritestiamo il codice con gli stessi ingressi provati in precedenza sempre tramite junit, per verificare se l’attivita di refactoring ha portato cambiamenti di funzionalità al programma eseguiamo il test e otteniamo : Figura 9: Test di rigressione Con questa verifica ci permette di affermare che pur apportando modifiche al codice tramite attività di refactoring le funzionalità del programma non hanno subito alcuna modifica. 37 Miglioramento della qualità del software con attività di refactoring 2.3.5 Qualità del programma dopo Riseguendo il programma con il pluing stan4j andiamo a visionare se ci sono stati cambiamenti di qualità rispetto a violazioni e alle metriche visionate in precedenza: Violazioni Artifact Metric CC Calendario.Calendario.verifica(...) Value 19 Da ciò é possibile notare, come le violazioni sono diminuite per la metrica Cyclomatic Complexity e scomparse per quelle Estimated Lines of Code pure se il valore 19 sarebbe un pò alto in quanto esso dovrebbe essere minore di 10. Rapportandolo all’ analisi precedente abbiamo un netto miglioramento,in quanto ora si trova in una zona intermedia indicata con il giallo tra 10 e 20. Precedentemente la metricaCyclomatic Complexity si trovava in una zona rossa indicando una complessità peggiore. visioniamo le altre metriche: Metric Value Number of Libraries 1 Number of Packages 1 Number of Top Level Classes 2 Average Number of Top Level Classes per Package 2 Average Number of Member Classes per Class 0 Average Number of Methods per Class 14.50 Average Number of Fields per Class 10 38 Miglioramento della qualità del software con attività di refactoring Estimated Lines of Code 223 Estimated Lines of Code per Top Level Class 111.50 Average Cyclomatic Complexity 2.34 Fat for Library Dependencies 0 Fat for Flat Package Dependencies 0 Fat for Top Level Class Dependencies 1 Tangled for Library Dependencies 0% Average Component Dependency between Libraries 0% Average Component Dependency between Packages 0% Average Component Dependency between Units 50% Average Distance 0 Average Absolute Distance 0 Average Weighted Methods per Class 34 Average Depth of Inheritance Tree 1 Average Number of Children 0 Average Coupling between Objects 1 Average Response for a Class 15 Average Lack of Cohesion in Methods 126.50 Mettendo a confronto le due tabelle si evince un miglioramento nel Cynclomatinc complexity, ma un pò di peggioramento secondo la mertrica di weighted methods per class in quanto sono aumentati i metodi nella classe. 39 Miglioramento della qualità del software con attività di refactoring Conclusioni Come visto dall’ esempio l’attivita di refatoring e quindi la pulizia del codice oltre a un miglioramento della Cynclomatinc complexity cioè una diminuzione della complessità del codice; ci ha permesso di dividere un codice monolitico in più metodi rendendo cosi più leggibile, più facile da interpetrare, più semplice da modificare per eventuali interventi di manutenzione che rappresentano la parte più costosa dell’intero progetto. Una buona pulizia del codice permette non solo a chi scrive il programma di lavorare più aggevolmente, ma soprattutto a chi lavora in un team di comprendere ciò che l’autore del codice vuole fare. Ciò riduce il tempo di interpetazione del codice e aumenta quello di sviluppo. Una buona pulizia del codice permette di avere un programma molto più performante, riusabile, manutenibile. L’attivita di refatoring però, presenta anche degli effetti negativi. Se si cerca di migliorare il programma rispetto a una qualità può verificarsi la diminuzione di un’ altra come ad esempio la creazione di più metodi partendo da uno. Attraverso questa operazione aumenta la leggibilità del codice, contemporaneamente aumentano le interconnesioni tra metodi. 40 Miglioramento della qualità del software con attività di refactoring D’altrocanto non si deve esagerare con la refatoring in quanto, un uso estremo di questa attività, può causare degrado delle funzionalità del codice e quinidi si é obligati dopo l’intervento di refactoring di fare un test di regressione . In fine é bene fare l’attivita di pulizia con estrema attenzione , poichè un‘eccessiva pulizia del codice puo’ danneggiare le funzionalità del programma. 41 Miglioramento della qualità del software con attività di refactoring Bibliografia Mäntylä, M. V. and Lassenius, C. "Subjective Evaluation of Software Evolvability Using Code Smells: An Empirical Study". Journal of Empirical Software Engineering, vol. 11, no. 3, 2006, pp. 395-431. Stan4j, “http://stan4j.com/” AppPerfect java code, “http://www.appperfect.com/products/javacode-test.html” Martin Fowler “www.refactoring.com.” C.Ghezzi, M. Jazayeri, D. Mandrioli; Ingegneria del Software. Fondamenti e principi, seconda edizione. Pearson 42