Introduzione
Se è vero che scrivere codice che funzioni non
è la cosa più semplice del mondo (soprattutto
se deve fare esattamente quanto richiesto dall'utente
..),
scrivere codice che oltre a ciò sia anche di
qualità è decisamente più complesso.
Forse anche per questo, in seguito alla enorme popolarità
di Java, si è ben presto diffusa anche una serie
di regole su "come scrivere Java a regola d'arte".
Già, ma come districarsi tra queste "regole
d'arte", che sono numerose e di non sempre immediata
applicazione? Per non parlare poi della necessità
di poter disporre di strumenti che ci aiutino ad applicarle
e che ci forniscano un reale valore, facendoci risparmiare
davvero tempo e denaro durante le fasi dello sviluppo
e della manutenzione. In questo articolo analizzeremo
un pò più da vicino la questione della
qualità del codice, esaminando il come e perchè
esistono le regole di codifica, con uno sguardo anche
a come sia possibile applicarle traendone beneficio.
Col minimo sforzo, possibilmente!
Perchè
validare il codice?
Come nelle migliori storie di Java, tutto comincia a
casa Sun Microsystems, e stavolta sul suo sito web,
che tanto per toglierci ogni dubbio sulla utilità
delle "regole di codifica", dedica loro una
sezione apposita ([1]), dicendo testualmente che rispettarle
è di fondamentale importanza per qualsiasi sviluppatore,
e ciò in quanto:
-
la manutenzione costa mediamente quattro volte più
dello sviluppo (la ben nota regola del 20-80%)
- è
molto complesso manutenere il software anche da chi
lo ha scritto
- le
regole di codifica migliorano la leggibilità,
permettendo a chi sviluppa di comprendere meglio e
più rapidamente dove e come inserire codice
ulteriore
Persuasi
del fatto che validare il codice secondo regole è
utile e necessario, ci si chiede: e adesso, da dove
incominciamo?
Quali
riferimenti?
Una trattazione completa ed esaustiva delle regole di
scrittura del codice Java si può trovare, sempre
a cura di Sun Microsystems, nel testo [2], scaricabile
in formato pdf. Non mancano nella letteratura numerosi
altri importanti riferimenti, quali il testo fondamentale
[3], di importanza vitale per comprendere cosa significa
scrivere codice Java in modo efficace, ma anche [4],
in cui il focus viene spostato in particolare sulla
prevenzione dei problemi di memoria. Nei suddetti riferimenti,
vengono illustrate e discusse numerose regole per evitare
alcuni errori che tipicamente si commettono nello scrivere
codice Java, legati all'uso improprio di determinati
costrutti, all'abuso più che all'uso di certi
elementi sintattici, alla corretta a appropriata scelta
di alcuni statement piuttosto che altri.
Tali regole vengono suddivise in gruppi, distinti a
seconda del problema che provocano se vengono violate,
e precisamente:
-
Correttezza. violare le regole di tale categoria causa
con ogni probabilità dei bug, e il codice non
farà ciò che ci si aspetta
-
Progettazione. regole conformi ai principi dell'object
oriented programming (OOP). Si tratta di regole molto
più eficaci se applicate al codice da scrivere
ex-novo piuttosto che pre-esistente. Violazioni ad
esse possono portare con ogni probabilità a
bug quando il codice esistente venga modificato e/o
esteso
-
Performance. regole che se violate possono portare
a problemi in termini di velocità, memoria,
utilizzo risorse
Successivamente,
le violazioni registrate a tali regole vengono raggruppate
secondo coefficienti di "severità",
e precisamente:
-
Elevato. La violazione può portare a errori
a tempo di esecuzione, problemi di performance o evidenziare
gravi difetti a livello progettuale
-
Medio. La violazione può causare problemi,
ma ci sono diverse circostanze valide in cui l'applicazione
della regola in questione può essere ignorat
- Basso.
La violazione può impattare sulla manutenibilità
del codice ovvero essere sintomo della mancata applicazione
di una "best practice", ossia di una metodologia
che migliorerebbe di molto la qualità complessiva
di quanto prodotto
Chiarito
il fatto che la documentazione inerente le regole di
codifica esiste ed è abbondante, guardiamoci
intorno per vedere se esistono strumenti che le supportano
e come possono eventualmente aiutarci nel nostro lavoro.
Open
Source!
Una prima risposta viene, come spesso accade, dalle
community di Open Source. Esse ci mettono a disposizione
diversi interessanti strumenti, adatti proprio allo
scopo che stiamo trattando, come ad esempio CHECKSTYLE,
presentato e descritto in [5]. Nel presente articolo,
daremo un'occhiata da vicino a PMD ([6]), che ci offre
la possibilità di "attraversare" letteralmente
un insieme di codice Java identificando i potenziali
problemi rilevati. Quali problemi? Ad esempio la presenza
di blocchi di codice try/catch/finally/switch vuoti,
variabili locali o metodi dichiarati come private che
risultino inutilizzati, ovvero ancora espressioni ecccessivamente
complesse, ad esempo a causa di numerose statement if
annidate. Sempre sul medesimo riferimento [6] è
possibile consultare la lista delle regole che PMD supporta,
un elenco davvero completo ed esaustivo, che comprende
anche regole di complessità ciclomatica (McCabe).
L'interfaccia di PMD è abbastanza semplice ed
intuitiva, e permette anche di comprendere come PMD
agisca in pratica quando deve analizzare un blocco di
codice.
Alla maniera dei compilatori infatti, PMD costruisce
un "albero sintattico" degli elementi di codice
che processa. Tale albero, denominato AST (Abstract
Syntax Tree), contiene la struttura del codice in esame,
suddivisa in parti aventi ciascuna un ben determinato
significato. E' proprio su questa struttura e sugli
elementi che contiene che PMD effettua poi la sua analisi.
A titolo di esempio, può essere curioso vedere
come PMD costruisca il proprio AST proponendogli il
frammento di codice Java forse più famoso del
mondo, il celeberrimo "Hello World".
Figura 1 - PMD costruisce il suo AST
Come procedere adesso?
Leggendo con attenzione la documentazione di PMD, magari
incuriositi da quella finestra denominata "XPath"
che compare nella figura 1 vista più sopra, si
scopre che XPath non è altri che un linguaggio
formale che permette di definire le proprie "custom
rules" (qualora quelle già supportate da
PMD non dovessero bastare
..) e salvarle in un
formato XML completamente compatibile con la sintassi
presente nelle regole già esistenti nel repository
di PMD.
A
questo punto, tutto quello che andrà fatto sarà
di invocare PMD "passandogli" come parametri
la dislocazione del nostro codice da processare, nonchè
la dislocazione del "ruleset", ovvero del
repository contenente le diverse regole secondo cui
analizzare il codice stesso, eventualmente "puntando"
a un differente "ruleset", contenente le nostre
regole personalizzate. Il tutto espresso nella semplice
chiamata (da linea di comando):
pmd.bat
c:\path\to\my\src xml c:\path\to\mycustomrules.xml
Non
è questa la sede per discutere in modo approfondito
della sintassi del linguaggio formale XPath, per la
quale si rimanda ai riferimenti citati in bibliografia
([7] e [8]). Qui intendiamo comunque osservare che si
tratta di un mezzo potente ed espressivo per poter "implementare"
in modo efficace e relativamente veloce le proprie regole
di codifica, salvo averle a disposizione in modo immediato
per verificarle nel codice Java da analizzare. E se
oltre alle regole di PMD potessimo avere anche la possibilità
di verificare sul codice quelle definite da Sun e presentate
più sopra (le "effective Java", tanto
per intenderci)? Vediamo un esempio concreto leggermente
più significativo di "Hello World"
.
Un
esempio pratico
Scegliamo una applicazione tipica e anche ben nota nel
mondo Java, e cioè JMeter ([9]), e poniamoci
il problema di verificare quante e quali violazioni
sono presenti all'interno del suo codice, e di quale
categoria tra quelle disponibili e selezionate a priori.
Utilizziamo lo strumento Compuware OptimalAdvisor ([10])
e costruiamo come prima cosa il "design model"
di JMeter in notazione UML (fig. 2).
Figura 2 - Design Model di JMeter in OptimalAdvisor
Visitando
la "tab page" corrispondente alle regole di
codifica, notiamo che abbiamo la possibilità
di impiegare tanto le regole prescritte da Sun (presentate
nei primi paragrafi e relative alla efficacia del codice
Java), quanto tutte quelle supportate da PMD.
Per ciascuna di esse, in particolare, abbiamo a disposizione
una "finestra" che ne illustra il significato
e l'utilizzo (v. fig. 4). Si noti, nella figura citata,
anche la possibilità di definire le proprie regole
di validazione invocando un apposito wizard che le memorizza
poi in formato XML secondo quanto previsto dalla sintassi
XPath (bottone "New" in basso nella fig. 3)
Figura 3 - Esplorazione regole PMD in OptimalAdvisor
A
questo punto è sufficiente ricorrere al cosiddetto
"Rule Filter" per selezionare, tra tutte le
regole di validazione disponibili - e cioè sia
le PMD, sia le "effective Java" - quelle secondo
cui si intende analizzare il nostro codice..
Figura 4 - Selezione regole da applicare
Con
un click sul bottone "OK", il codice applicativo
in esame viene analizzato, e le violazioni individuate
vengono immediatamente evidenziate in un apposito report,
suddivise secondo "severity", come più
sopra specificato. Nella figura 5 si immagina di aver
voluto verificare quante violazioni alle regole di correttezza
erano state rilevate in JMeter. Si noti, sempre in figura
5, la possibilità di esportare in diversi formati
il report così ottenuto
Figura 5 - Violazioni alle regole di correttezza
in JMeter
Desideriamo
ottenere informazioni più approfondite sulle
diverse violazioni riscontrate sul codice? Nella figura
6 sono state visualizzate le violazioni più gravi
(severity = high) e si può notare come vengano
evidenziate direttamente sulla riga "colpevole"
nel codice sorgente, fornendo anche una traccia documentale
del tipo di violazione riscontrata e di alcuni dei possibili
workaround per eliminare il problema.
Figura 6 - High Violations in JMeter
Conclusioni
Perchè validare il codice? Perchè un codice
scritto "a regola d'arte" è più
facile e meno costoso da manutenere, sia per noi che
lo abbiamo sviluppato, sia per coloro che un giorno
lo prenderanno in carico....Esiste una quantità
di regole, norme, prescrizioni, metodologie e best practice,
basta cercare - magari iniziando a casa Sun - e si trova
ampia documentazione. Ma nessun ricettario potrà
mai farci diventare grandi cuochi, perchè occorre
una naturale (e notevole) predisposizione e tanta esperienza.
Chi può aiutarci allora? Per nostra fortuna,
le community di Open Source - ma non soltanto - offrono
diversi strumenti che permettono di analizzare il nostro
codice, anche secondo insiemi preselezionati ovvero
personalizzati di regole, e di produrre le relative
reportistiche, in vari formati e spesso di qualità.
Non dobbiamo cadere nella tentazione di scrivere codice
e basta, uno sguardo attento alla qualità di
ciò che produciamo o analizziamo oggi costituisce
un investimento sulla efficienza e sul valore di domani.
Bibliografia
[1]
SUN Microsystems, "Code Conventions for the Java
Programming Language", http://java.sun.com/docs/codeconv/
[2]
Achut Reddy, "Java Coding Style Guide", http://java.sun.com/docs/codeconv/
SUN Microsystems
[3] Joshua Block, "Effective Java Programming Language
Guide", http://java.sun.com/docs/books/effective/
SUN Microsystems
[4]
William Pugh, "The Java Memory Model is Fatally
Flawed", http://www.cs.umd.edu/~pugh/java/broken.pdf,
University of Maryland
[5]
Mokabyte -"Qualità del software", http://www.mokabyte.it/2004/11/auditing.htm
[6]
PMD official website, http://pmd.sourceforge.net/
[7]
XPath Tutorial http://pmd.sourceforge.net/xpathruletutorial.html
[8]
Tom Copeland "Custom PMD Rules", http://www.onjava.com/pub/a/onjava/2003/04/09/pmd_rules.html
[9]
JMeter, http://jakarta.apache.org/jmeter/, Apache Community
[10]
Compuware OptimalAdvisor, http://javacentral.compuware.com/products/optimaladvisor/documentation/v3.1/1820-20-15-0-32.html,
http://www.compuware.com/products/optimalj/2911_ENG_HTML.htm
Doriano Gallozzi è
nato a Roma nel 1964 e si è laureato in Ingegneria
Elettronica (indirizzo Informatica) nel 1989. Da sempre
interessato a problematiche di analisi, progettazione
e sviluppo di Sistemi Informativi, ha lavorato per diversi
anni in aziende del settore informatico italiano (gruppo
ENI, gruppo Telecom Italia), dove ha acquisito diverse
esperienze tanto nel campo della progettazione e sviluppo
del software (in ambiente M/F come in ambiente distribuito)
quanto nel campo dei RDBMS (DBA su diversi progetti
per clienti finali quali Telecom Italia). Da gennaio
2000 lavora nella Divisione Prevendita di Compuware
Italia. La sua attività verte principalmente
sulla piattaforma J2EE e tecnologie correlate, ma anche
su ambiti tecnologici quali l'Enterprise Application
Integration, i Portali Web, gli strumenti di Business
Process Management.
|