Abstract
Un linguaggio di programmazione non si ferma alla mera specifica
semantico/sintattica unita a qualche reference sulle api di base, bensì
comporta una parte meno evidente, e spesso trascurata, che può risultare
fondamentale nello sviluppo di un progetto in un gruppo: lo stile.
Data di stesura: 04/09/2002
Data di pubblicazione:
04/09/2002
Ultima modifica: 04/04/2006
O più semplicemente trascurato, un po' come l'indentazione (che in qualche
modo si può far ricadere nello stile di programmazione).
Tutti noi probabilmente le prime volte ci siamo chiesti quale fosse il
vantaggio nell'allineare righe e "sprecare" spazio con "inutili"
tabulazioni.
#define r return
#define t int
#define m main
t m(void){t i=0;i=10;r i;}
int
main(void)
{
int i = 0;
i = 10;
return i;
}
Lo stile di programmazione comprende una serie di regole per scrivere dei
sorgenti leggibili (e non interpretabili, compatibilmente con
la complessità algoritmica) da qualsiasi programmatore che conosca il
linguaggio e le sue regole stilistiche.
Queste regole permettono di identificare a colpo d'occhio alcuni aspetti nei
sorgenti che altrimenti richiederebbero una lettura approfondita ed
un'interpretazione delle convenzioni adottate dal programmatore.
Ma poiché c'è spesso una guida di stile che definisce e suggerisce un
insieme di convenzioni ottimali, la sua adozione permette ad un
programmatore di avere una "marcia in piu`" che va al di sopra della
conoscenza comune di un linguaggio.
Seguono ora un paio di esempi utili per confrontare l'adozione di due stili
differenti con lo stesso linguaggio.
class Esempio1
{
// valore costante
public final static int DEFAULT_VALUE = 0;
// variabile
private int value = DEFAULT_VALUE;
public Esempio1()
{
}
public int getValue()
{
return value;
}
public void increment()
{
value++;
}
public void setValue(int v)
{
value = v;
}
}
class Esempio2
{
// valore costante
public final static int valoreiniziale = 0;
// variabile
private int foo = valoreiniziale;
public Esempio2()
{
}
public int ottieni_il_valore()
{
return foo;
}
public void Incrementa()
{
foo++;
}
public void _imposta(int v)
{
foo = v;
}
}
Sono due esempi con due convenzioni differenti, la prima è quella proposta
dalla Sun nelle specifiche del
linguaggio Java, la seconda
è un non-stile.
Per chi è già a conoscenza del linguaggio Java ed abbia un minimo di
esperienza programmativa con questo, sicuramente il primo esempio
risulterà comprensibile ed immediatamente utilizzabile anche solo leggendo
le dichiarazioni dei metodi.
Il vantaggio di uno stile di programmazione è che alla fine il
programmatore quando adotta o sviluppa delle librerie o frameworks può
minimizzare l'impatto con il nuovo oggetto. Il soggetto si aspetterà delle
costanti visibilmente distinguibili da metodi o funzioni, questi ultimi
dovranno avere nomi significativi, spesso "prevedibili" (Es: in Java, se so
che l'oggetto possiede una particolare caratteristica mi aspetto di poterla
modificare con un metodo "setCaratteristica" o ottenerla con un
"getCaratteristica"), packages organizzati secondo criteri comuni, etc.
Provate ora ad immaginare di dover usare una libreria piuttosto complessa
che presenti un interfaccia di programmazione (API) eterogenea (o
soggettiva) come nel secondo caso. Oltre ad un uso meno "spontaneo" ed
immediato dell'interfaccia, questa contribuirà a rendere meno leggibili ed
uniformi anche i vostri sorgenti che l'adotteranno.
...
public void doSomething(int v)
{
Esempio1 es1 = new Esempio1();
for (int i = 0; i < v; i++) {
es1.setValue(i);
es1.increment();
System.out.println(es1.getValue());
}
}
...
...
public void doSomething(int v)
{
Esempio2 es2 = new Esempio2();
for (int i = 0; i < v; i++) {
es1._imposta(i);
es1.Incrementa();
System.out.println(es1.ottieni_il_valore());
}
}
...
Ogni linguaggio ha il suo stile ...
Avere una guida di stile non è obbligatoria ma, mai quanto oggi,
consigliata.
Mi sento di consigliarne l'adozione anche in vista di quella che è la
realtà dell'OpenSource, adottare uno stile comune può voler dire
garantire quel margine di integrazione e collaborazione che può fare la
differenza e garantire una continuità di sviluppo.
Fa parte delle preoccupazioni di chi sviluppa un linguaggio far si che
assieme ad esso vengano date delle linee guida su come organizzare e
razionalizzare il materiale scritto con questo.
Perl dispone di una man page a riguardo (perlstyle), anche Java ha delle
linee guida essenziali ma sufficienti, elencate nelle specifiche del
linguaggio.
Ogni linguaggio ha il suo stile ... o quasi!
C ad esempio non possiede uno stile di linguaggio. Le librerie a corredo
adottano convenzioni fra le più disparate (gestione degli errori, nomi,
strutture, ...). Librerie funzionalmente analoghe possono presentare
interfacce completamente differenti.
E tutto ciò finisce per complicare la vita a chi deve adottarne più d'una
contemporaneamente.
E le notazioni?
L'Hungarian Notation, a mio avviso potenzialmente utile ma non
indispensabile, è una delle più famose (e forse anche odiate) notazioni,
è un po' il surrogato di uno stile per il C, che molti hanno proposto di
estendere anche ad altri linguaggi.
Le notazioni, come nel caso dell'Hungarian, solitamente propongono prefissi
standard per identificare tipi di variabili o costanti e signature di
funzioni.
Va precisato che una notazione ha senso solo per linguaggi non
dinamicamente tipizzati, ovvero quelli in cui il tipo di una variabile
dipende dal contesto in cui essa è usata, ed è completamente inutile, se
non addirittura limitante (pesante e prolissa), in una programmazione
orientata agli oggetti con linguaggi come, ad esempio, Java, Perl e Python.
Confronti, stile: uno, nessuno, centomila
Caso 1: Java
package siforge;
public class ClasseDiProva
{
public final static int UNA_COSTANTE = 0;
private int unaProprieta = -1;
public Test() // costruttore
{
...
}
public int unMetodo(int val)
{
...
}
}
Essenziale, la style guide di Java è estremamente sintetica, ma completa.
I vantaggi sono più che ovvi, ci vuol poco a ricordarla ed ancora meno a
metterla in opera. I package di sistema la seguono (al 99.9%, qualche
svista c'e`) in maniera rigorosa e l'adozione di uno stile omogeneo con
queste è, con il dovuto sforzo di volontà, praticamente immediato.
Caso 2: Perl
package SIForge::ClasseDiProva;
sub un_metodo
{
my ($una_variabile) = @_;
print "Esempio\n" if $verbose;
...
}
La guida di stile del Perl è così puntigliosa da arrivare a definire
anche lo stile dell'indentazione del codice e le dimensioni delle
tabulazioni (4 caratteri).
In quasi 250 righe vengono presi in esame molti dettagli e norme per
scrivere "in Perl".
Caso 3: C
Il C della specifica ANSI non nasce con nessuno stile, molti progetti
complessi hanno adottato soluzioni stilistiche diverse. Soffermandoci per
un attimo sul mondo GNU ho in mente un paio di progetti con altrettanti
stili ben definiti: Linux (il kernel) ed i progetti collegati di GIMP,
GTK+ e glib.
void acct_auto_close(kdev_t dev)
{
lock_kernel();
if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev)
sys_acct(NULL);
unlock_kernel();
}
Il kernel di Linux si porta dietro, nella versione sorgente, un piccolo
documento (linux/Documentation/CodingStyle) in cui si formalizza il modo di
scrivere codice.
void
base_exit (void)
{
swapping_free ();
paint_funcs_free ();
tile_swap_exit ();
}
GIMP ed in particolare l'accoppiata GTK+ e glib adottano uno stile molto
simile a quello del kernel di Linux.
Perdere qualche minuto a leggere le brevi norme legate al coding style in
questi progetti può fruttare molto se siete alla ricerca di un po' di
rigore e standard nei vostri sorgenti in C.
Caso 4: PHP
Anarchia! Mentre in C possiamo sempre ricondurci alle librerie standard che
propongono qualche cosa di tutto sommato coerente (restando all'interno
della libreria), in PHP l'assenza di stile e uniformità sembrano regnare
incontrastate sin dalle funzioni di libreria standard. Aprendo il manuale
di PHP e sfogliando i vari gruppi di funzioni notiamo un'estrema varietà
di convenzioni a seconda del gruppo.
Prendiamo in esame il seguente:
Il gruppo di funzioni sopraccitate mescola almeno tre stili differenti di
nomenclatura di metodi:
Parole unite con la prima lettera maiuscola.
Parole minuscole separate da un carattere di underscore ('_').
Parole minuscole unite in successione.
Tutto ciò è in parte eredità di uno sviluppo delle librerie di sistema
da parte di più persone, con varie esperienze ma con nessuna o poche
convenzioni in comune. Spesso le api di PHP riflettono esattamente le api
delle librerie che stanno integrando (libc, libgd, ...) senza particolari
sforzi nel "piegarle" al contesto in cui si andranno ad inserire.
PEAR Coding Standards, queste norme di stile per PHP valgono
fondamentalmente per chi vuole produrre del codice da integrare con
l'archivio di estensioni per PHP. Sorvolando sulla sezione delle naming
conventions, scarsamente rigorosa su alcuni aspetti, si tratta pur sempre
di norme stilistiche da applicare ad una ridotta parte del codice PHP: non
sono norme valide per il linguaggio "in toto", ma solo per ciò che si
vuole rendere pubblico per estenderlo.
Nel complesso è quasi come non avere regole stilistiche, vista la
tipologia del linguaggio ed il campo applicativo.
Conclusioni
Un "buon" programmatore è (anche) un camaleonte ...
Un buon programmatore dovrebbe imparare che conoscere un linguaggio può
voler dire "cambiare pelle". Il passaggio da un linguaggio ed il
corrispettivo stile deve essere un comportamento quasi spontaneo per
evitare di incappare nel più tragico degli errori, cioè quello di
scrivere in qualsiasi linguaggio così come fosse quello preferito
(scrivere tutto come se fosse in C) o, peggio ancora, ricostruirsi
lentamente le funzioni di libreria preferite scordandosi delle peculiarità
(o ignorandole del tutto) del linguaggio in uso.
... che conosce ed usa lo stesso "dialetto" degli altri
Ricordiamo infine che per un progetto di gruppo lo stile è un punto di
contatto, è importante quasi quanto due persone che decidano di parlare in
dialetto, pur restando italiani (es: programmatori del linguaggio "x")
spesso potrebbero incappare in problemi di scarsa comprensione se uno di
essi parlasse il siciliano (es: le dichiarazioni in testa e tutto
maiuscolo) e l'altro il bergamasco (es: le dichiarazioni man mano e tutto
un po' maiuscolo, un po' minuscolo).
Informazioni sull'autore
Marco Lamberto, laureato in Informatica presso la Statale di Milano, con diversi anni di esperienza sistemistica, di sicurezza e sviluppo prevalentemente in ambienti UNIX (Linux in primis) con linguaggi come C, Java, Perl, PHP, XML, HTML, ...