Articoli Manifesto Tools Links Canali Libri Contatti ?
Linguaggi

Programmare? Questione di stile!

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
di Marco Lamberto Discuti sul forum   Stampa

Lo stile, questo sconosciuto

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.
  1. #define r return 
  2. #define t int 
  3. #define m main 
  4. t m(void){t i=0;i=10;r i;} 
  1. int 
  2. main(void) 
  3.   int i = 0; 
  4.    
  5.   i = 10; 
  6.    
  7.   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.

  1. class Esempio1 
  2.   // valore costante 
  3.   public final static int DEFAULT_VALUE = 0; 
  4.  
  5.   // variabile 
  6.   private int value = DEFAULT_VALUE; 
  7.  
  8.   public Esempio1() 
  9.  
  10.   public int getValue() 
  11.     return value; 
  12.  
  13.   public void increment() 
  14.     value++; 
  15.  
  16.   public void setValue(int v) 
  17.     value = v; 
  1. class Esempio2 
  2.   // valore costante 
  3.   public final static int valoreiniziale = 0; 
  4.  
  5.   // variabile 
  6.   private int foo = valoreiniziale; 
  7.  
  8.   public Esempio2() 
  9.  
  10.   public int ottieni_il_valore() 
  11.     return foo; 
  12.  
  13.   public void Incrementa() 
  14.     foo++; 
  15.  
  16.   public void _imposta(int v) 
  17.     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.

  1. ... 
  2. public void doSomething(int v) 
  3.   Esempio1 es1 = new Esempio1(); 
  4.    
  5.   for (int i = 0; i < v; i++) { 
  6.     es1.setValue(i); 
  7.     es1.increment(); 
  8.     System.out.println(es1.getValue()); 
  9. ... 
  1. ... 
  2. public void doSomething(int v) 
  3.   Esempio2 es2 = new Esempio2(); 
  4.    
  5.   for (int i = 0; i < v; i++) { 
  6.     es1._imposta(i); 
  7.     es1.Incrementa(); 
  8.     System.out.println(es1.ottieni_il_valore()); 
  9. ... 

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

  1. package siforge; 
  2.  
  3. public class ClasseDiProva 
  4.   public final static int UNA_COSTANTE = 0; 
  5.  
  6.   private int unaProprieta = -1; 
  7.    
  8.   public Test() // costruttore 
  9.     ... 
  10.  
  11.   public int unMetodo(int val) 
  12.     ... 
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

  1. package SIForge::ClasseDiProva; 
  2.  
  3. sub un_metodo 
  4. 	my ($una_variabile) = @_; 
  5.  
  6. 	print "Esempio\n" if $verbose; 
  7. 	... 
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.
  1. void acct_auto_close(kdev_t dev) 
  2.   lock_kernel(); 
  3.   if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev) 
  4.     sys_acct(NULL); 
  5.   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.
  1. void 
  2. base_exit (void) 
  3. {  
  4.   swapping_free (); 
  5.   paint_funcs_free ();   
  6.   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:

JDToGregorian
GregorianToJD
JDToJulian
JulianToJD
...
easter_date
easter_days
unixtojd
jdtounix
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, ...

È possibile consultare l'elenco degli articoli scritti da Marco Lamberto.

Altri articoli sul tema Linguaggi.

Risorse

  1. Perl Style Guide.
    http://www.perldoc.com/perl5.6/pod/perlstyle.html
  2. The Java Language Specification.
    http://java.sun.com/docs/books/jls/
  3. Hungarian Notation in MSDN.
    http://msdn.microsoft.com/library/en-us/dnvsgen/html/hunganotat.asp
  4. Hungarian Notation - The Good, The Bad and The Ugly
    http://ootips.org/hungarian-notation.html
  5. How To Write Unmaintainable Code
    http://mindprod.com/unmain.html
  6. Applying Hungarian Notation to Java programs: Part 1
    http://softwaredev.earthweb.com/java/sdjjavase/article/0,,12395_615891,00.html
  7. Applying Hungarian Notation to Java programs: Part 2
    http://softwaredev.earthweb.com/java/sdjjavase/article/0,,12395_615981,00.html
  8. Sito ufficiale del kernel di Linux.
    http://www.kernel.org/pub/linux/kernel/
  9. Sito ufficiale di GIMP.
    http://www.gimp.org/
  10. Sito ufficiale di GTK+/glib.
    http://www.gtk.org/
Discuti sul forum   Stampa

Cosa ne pensi di questo articolo?

Discussioni

Questo articolo o l'argomento ti ha interessato? Parliamone.