MokaByte 90- 9mbre 2004 
Qualità del software
Auditing del codice
di
Stefano Rossini

Affrontare un tale argomento in modo completo ed esaustivo, esula dallo scopo di questo articolo che invece si concentrerà sugli aspetti relativi alla qualità del codice ed alle relative metriche di misura. Il concetto di qualità Ma che cos'è la qualità di un software? La qualità del software è determinata da una combinazione di diversi fattori (vedere [BM_OOSC]).

Introduzione
Tra i fattori che determinano la qualità di un software, ve ne sono alcuni che sono più appariscenti, rilevabili da qualunque utente privo di competenze specifiche di sviluppo software (fattori esterni), altre che riguardano direttamente solo chi produce il software (i fattori interni). I fattori interni possono diventare esterni se l'utente è in qualche modo coinvolto in attività di produzione/fornitura di software (ad esempio una libreria per programmatori ha come utenti altri programmatori e non semplici operatori).
Alcuni tra i principali fattori esterni rilevabili dall'utente finale generico sono: Correttezza di funzionamento e affidabilità, Robustezza, Estensibilità, Facilità e flessibilità d'uso, Portabilità e Scalabilità.
I fattori interni o rilevabili da un utente specialistico sono fondamentalmente due: Menutenibilità e Riusabilità.
Il raggiungimento di questi ultimi requisiti ha notevoli ripercussioni anche sui fattori esterni, o meglio sulla facilità con cui la qualità esterna può essere ottenuta.
I contributi forse più noti per ciò che concerne la qualità del SW sono gli standard ISO relativi ai processi produttivi e di servizio ed ai prodotti software (vedere [QPS]). In particolare, la serie di standard ISO 9000 non è specifico dei prodotti software e si occupa di definire le caratteristiche e i requisiti di un sistema di qualità aziendale (standard di processo), mentre lo standard ISO 9126 (vedere [ISO9126]) definisce alcune nozioni generali concernenti la qualità dei prodotti software (standard di prodotto).


Figura 1: Lo standard ISO 9126


Il contenuto dello standard ISO 9126 è costituito da un elenco di caratteristiche di qualità di un generico prodotto software:

  • Functionality (Suitability, Accuracy, Interoperability, Compliance, Security)
  • Reliability (Maturity, Fault tolerance, Recoverability)
  • Usability (Understandability, Learnability, Operability)
  • Efficiency (Time behaviour e Resource behaviour)
  • Maintainability (Analysability, Changeability, Stability, Testability)
  • Portabilità (Adaptability, Installability, Conformance, Replaceability)

Ogni qual volta si vuole valutare la bontà di un bene o di un servizio risulta pressocchè indispensabile esprimere il giudizio attraverso una metrica.
Per misurare la qualità di un prodotto software le caratteristiche di qualità devono essere tradotte in metriche concrete (che devono tenere conto delle specifiche caratteristiche del prodotto desiderato) che permettano di esprimere una valutazione quantitativa della qualità del bene o servizio osservato.

Una metrica è una funzione che permette di associare ad un attributo di un'entità un valore numerico o scalare.
Il numero di metriche potenzialmente utilizzabili per valutare beni e servizi IT è estremamente elevato. Le metriche dimensionali per il software si basano sul conteggio del numero di istruzioni del programma (come LOC -Lines Of Code, e/o NLOC-Non-commented Lines Of Code) o sul numero di funzionalità presenti nel programma (function points). Altre metriche di prodotto sono quelle che valutano la difettosità di un programma (espresse attraverso rapporti: per esempio numero di errori rilevati per modulo oppure numero di errori rilevati in un periodo di tempo) e altre si riferiscono al lavoro richiesto per sviluppare o modificare un programma (anni/uomo o mesi/uome per indicare il lavoro).
Un programma di misura è costituito dall'insieme di informazioni che specificano quali dati raccogliere e secondo quali modalità operative tale raccolta deve essere condotta.
La definizione di un processo/programma di misura e la relativa creazione è un processo complesso che richiede pianificazione, organizzazione e utilizzo di risorse adeguate.
La qualità del codice
Data la vastità e la complessità dell'argomento, ci concentreremo ora su uno specifico aspetto: la qualità del codice.
Come è possibile misurare la qualità del codice? Quali metriche e/o regole utilizzare per misurare tale qualità ?
In generale è sempre opportuno che tutti coloro che lavorano nell'ambito della stessa azienda o dello stesso progetto seguano le stesse regole nelle varie fasi della costruzione del software.
La motivazione che spinge a definire una convenzione stilistica da seguire per la stesura del codice è quella di aiutare nella realizzazione di un prodotto finale che sia comprensibile nel minor tempo possibile e che consenta di evitare di incorrere in errori banali, ma dagli effetti imprevedibili.
L'aderenza a certe metodologie e tecnologie tipicamente fornisce già degli standard e delle linee guida, che assicurano un buon grado di omogeneita in tutti i prodotti, in particolare a livello di regole di codifica (anche se in taluni casi è opportuno specificare ulteriormente il metodo di lavoro con l'elaborazione di regole linee guida).
Ad esempio SUN fornisce delle Code Convention (vedere [CCJPL]) che riportano indicazioni sulle regole sintattiche da seguire, sull'organizzazione del codice, naming convention e pratiche di programmazione per aiutare gli sviluppatori a scrivere codice uniforme, omogeneo e consistente.
La rilevanza dell'utilizzo delle Code Convention, rispetto alla riusabilità del software e all'intercambiabilità delle risorse umane, è intuitiva.
Metodologie agili come XP enfatizzano l'uso delle Code Convention tanto da inserirle come parte integrante della metodologia; infatti la pratica Coding standards (vedere [XP_CS]) fa parte delle 12 pratiche XP cosiddette "core" (vedere [XP_12P] e [MOKA_MET_2]).
In XP la pratica Coding standards è fondamentale anche per agevolare la pratica Collective Code Ownership (vedere [XP_CCO]) che definisce la proprietà collettiva del codice da parte dell'intero gruppo di lavoro: chiunque può modificare e migliorare una qualsiasi parte del sistema.
Tool di auditing del codice
Esistono sul mercato ed in ambito open source diversi prodotti che permettono di effettuare l'auditing del codice secondo specifiche regole e/o metriche.
Il funzionamento di questi tool si basa sull'analisi del codice in cerca di potenziali problemi come blocchi try/catch/finally vuoti, variabili e/o proprietà e/o metodi non utilizzati, statements vuoti, naming convention disattese, import non utilizzati, ecc …
In questo modo è possibile avere un'oggettiva (ed automatica!) misurazione della qualità del codice rispetto a specifiche regole di audit.



Figura 2: Funzionamento di un tool di code auditing


Tali tool mettono a disposizione dei file di regole per verificare la bontà del proprio codice rispetto alle cosiddette "well-known convention" che nel caso di Java sono le Code convention di Sun. Generalmente questi tool sono facilmente configurabili per permettere di analizzare il codice anche con regole di audit ad hoc per specifiche esigenze.

Prendiamo ad esempio il seguente codice Java che gestisce una semplice conversione da lire in euro e proviamo ad applicare le regole di audit relative alle Sun Code Convention utilizzando il prodotto Open Source Checkstyle (vedere[CHECKSTYLE]):

import java.sql.Connection;
import java.io.File;
import java.net.Socket;

public class myconverter{

private File file;
private Connection connection;
private double lire = 0;
private static final double euro = 1936.27;

public static double Convertilireineuro(String somma, int val) throws ConversionException{
if(somma==""){
String errMsg = " ERRORE ! Somma NON valida!";
System.out.println(errMsg);
throw new ConversionException(errMsg);
}
double valoreSomma=0;
try{
valoreSomma=Double.parseDouble(somma);
}
catch(NumberFormatException nfe){
}
return valoreSomma/euro;
}
}

Applicando le regole di audit sul codice, Checkstyle crea un report HTML che riporta ben 11 violazioni delle Sun Code Convention (vedere figura 2).

<taskdef resource = "checkstyletask.properties"
classpath = "${checkstyle.dir}/checkstyle-all-3.3.jar;
${checkstyle.dir}/checkstyle-optional-3.3.jar"/>
<target name = "checkSrc" description ="ciclo di verifca src" depends="init">
<checkstyle config = "${checkstyle.config.file}"
failureProperty="checkstyle.failure"
failOnViolation="false">
<formatter type = "xml"
toFile = "${checkstyle.error.output.file.xml}"/>
<fileset dir="${base.src.dir}">
<include name="**/*.java" />
</fileset>
</checkstyle>
<style in="${checkstyle.error.output.file.xml}"
out="${checkstyle.error.output.file.html}" style="${result.dir}/checkstyle_errors.xslt"/>
</target>

 


Figura 3
- Report di Checkstyle
(clicca sull'immagine per ingrandire)


Dalle segnalazioni riportate si vede come la Naming Convention consigliata da SUN sia clamorosamente disattesa: il nome della classe è minuscolo così come il nome della costante ed il nome del metodo è maiuscolo (vedere [CCJPL]).
Oltre a queste segnalazioni sulla naming convention ci sono altre segnalazioni importanti come
quella che indica che sono dichiarate tre proprietà (file, connection e lire) che non vengono mai utilizzate all'interno del codice.
Sono inoltre segnalati gli import inutilmente referenziati (java.net.Socket) ed il parametro val del metodo Convertilireineuro() che non è mai utilizzato. Quest'ultimo errore sicuramente metterà in difficoltà l'utilizzatore del metodo che si chiederà cosa deve specificare come valore del parametro.
Tutte queste segnalazioni indicano in generale codice "sporco" e poco leggibile, alcuni dei problemi segnalati rendono anche più complesso il reverse engineering del codice in esame presentando dipendenze non strettamente necessarie.
Un'altra segnalazione importante è relativa alla presenza del catch vuoto in corrispondenza della NumberFormatException (è buona pratica non lasciare mai blocchi catch vuoti inserendo almeno una trace che tenga traccia dell'eccezione avvenuta).
L'ennesima segnalazione riguarda l'uso improprio dell'operatore di uguaglianza al posto del metodo equals. L'ultima segnalazione, ma non la meno importante, è relativa alla completa assenza di Javadoc.
La versione del Javadoc che si ottiene è quella di default e risulta essere poco utile ad un eventuale utilizzatore della classe.
Risultato: la qualità del codice dell'esempio visto lascia alquanto a desiderare rispetto alle Code Convention Sun.


Figura 4 - La "qualità" del codice della classe myconverter

Mettiamoci all'opera per eliminare le segnalazioni di audit che abbiamo ottenuto.

/**
* <p>Title: EuroConverter</p>
* <p>Description: Classe che gestisce la conversione €uro in £ire</p>
* <p>Copyright: Copyright (c) 2001</p>
* <p>Company: Mokabyte</p>
* @author S. Rossini - srossini@mokabyte.it
* @version 1.0
*/
public class EuroConverter{
/** Valore in lire dell'euro */
private static final double EURO = 1936.27;
private EuroConverter(){}
/** Converte le lire in euro
* @param somma il valore delle £ire da convertire
* @return il corrispondente valore in €uro
* @throws ConversionException se la somma <b>non</b> e' un valore valido
*/
public static double convertiLireInEuro(String somma)throws ConversionException{
if(somma.equals("")){
String errMsg = "convertiLireInEuro: ERRORE ! Somma NON valida!";
System.out.println(errMsg);
throw new ConversionException(errMsg);
}
double valoreSomma=0;
try{
valoreSomma=Double.parseDouble(somma);
}
catch(NumberFormatException nfe){
nfe.printStackTrace();
}
return valoreSomma/EURO;
}
}

Dal punto di vista della qualità sintattica e stilistica del codice, le cose sono nettamente migliorate sia in termini di leggibilità che in termini di coerenza (si dichiara ed usa lo stretto necessario).
Da tutto ciò ne trarranno vantaggio sia i programmatori che dovranno utlizzare la classe, sia chi dovrà effettuare la manutenzione e/o le modifiche successive.
Il reverse che si ottiene è veritierio e non riporta inutili dipendenze ed il Javadoc generato semplificherà la vita agli utilizzatori della classe essendo chiaro e utile.


Figura 5 - la "qualità" del codice della classe EuroConverter

Da notare come i tool di auditing del codice tipo Checkstyle, PMD (vedere [PMD]), CodePro (vedere [CODEPRO]) mettano a disposizione gli (ormai) immancabili plugin per eclipse. Grazie ha queste integrazioni è possibile configurare tutto graficamente ottenendo in "tempo reale" i report durante lo sviluppo.

Ad esempio, per avviare il check di audit con il plugin Eclipse di CodePro, è sufficiente selezionare i file Java d'interesse e selezionare la voce Quality Assurance\Audit per ottenere immediatamente le (eventuali) violazioni delle regole all'interno dell'IDE di Eclipse.


Figura 6 - Quality Assurance Audit


Ovviamente sia le regole di audit che i relativi livelli di severity (info, warning, error e fatal) sono configurabili.


Figura 7 - Configurazione regole di audit e livello di severity

Da notare che non solo le regole di audit sono configurabili (si possono attivare/disattivare, modificare il livello di severity,…), ma è anche possibile creare nuovi controlli ad hoc estendendo le classi del tool di Audit Code.
In questo modo è possibile creare regole ad hoc per le proprie specifiche esigenze di audit.
Ad esempio con Checkstyle, per creare nuovi controlli, è sufficiente estendere la classe base com.puppycrawl.tools.checkstyle.Checker ed implementare gli opportuni metodi di callback del framework.


Figura 8 - Un controllo personalizzato di CheckStyle


Nel metodo beginTree() bisogna inserire la logica di inizializzazione del controllo mentre la logica del controllo vero e proprio deve essere implementata nel metodo visitToken() (vedere [CS_DOC]).
La regola custom risulta essere "pluggabile" in Checkstyle come una qualsiasi regola standard:

<module name="it.mokabyte.mokarules.MokaSampleControl">
<property name="severity" value="error"/>
</module>

Da notare infine come i tool di audit code mettano a disposizione anche la possibilità di applicare al codice diverse metriche.
Ad esempio con il plugin Eclipse di CodePro è sufficiente selezionare i file Java d'interesse e selezionare la voce Quality Assurance\Metrics per ottenere informazioni sul numero di linee per codice (LOC), il numero medio dei commenti (CR), il numero dei parametri per ogni metodo (NOP), il numero delle proprietà public (NOPA), gli accessi alle proprietà locali (ALD), il numero delle classi importate(NIC), il numero dei metodi di cui si è fatto override (NNOM), ecc …



Figura 9 - Quality Assurance Metrics

 

Conclusioni
In questo articolo abbiamo introdotto alcuni concetti relativi alla determinazione della "qualità del codice".
Abbiamo visto poi un semplice esempio di verifica di regole base di audit, attraverso alcuni strumenti Open Source.

 

Bibliografia e riferimenti
[MOKAMET_1] S. Rossini:Processi e metodologie di sviluppo(I)-Mokabyte 85 Maggio 2004
[BM_OOSC]B.Meyer: Object-Oriented Software Construction 2nd Edition, Prentice Hall
[ISO9126] ISO 9126: The Standard of Reference
http://www.cse.dcu.ie/essiscope/sm2/9126ref.html
[QPS] A. Fuggetta: La qualità nei prodotti s servizi IT
http://web.cefriel.it/~alfonso/WebBook/Documents/qualita.pdf
[CCJPL]Code Conventions for the Java Programming Language:
http://java.sun.com/docs/codeconv/
[JDTH] JavaDoc Tool Home Page: http://java.sun.com/products/jdk/javadoc/
[WKCC] http://c2.com/cgi/wiki?CodingConventions
[XP_12P] http://www.xpexchange.net/english/intro/practices.html
[XP_CS] http://www.extremeprogramming.org/rules/standards.html
[XP_CCO] http://www.extremeprogramming.org/rules/collective.html
[CHECKSTYLE] http://checkstyle.sourceforge.net
[CS_DOC] Writing checks: http://checkstyle.sourceforge.net/writingchecks.html
[PMD] http://pmd.sourceforge.net
[CODEPRO] http://www.instantiations.com/codepro/default.htm

 


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it