Recentemente mi sono trovato a lavorare con dei colleghi con lo scopo di redigere delle linee guida comuni per lo sviluppo in .NET.
Naturalmente come documentazione di partenza è stata usata quella presente su MSDN e sui blog di sviluppatori .NET.

Ecco un breve riassunto di quanto è uscito da questo 'Brain Storming' :-)

Style Guidelines


Le Style Guidelines puntano a regolamentare lo stile di scrittura del codice, in modo da rendere i listati il piu' possibile leggibili.

Indentazione e tabulazioni

Non credo sia necessario ribadire l'importanza dell'indentazione nella redazione di codice leggibile.
L'indentazione standard e' di 4 spazi.
Parecchi testi a riguardo sconsigliano l'utilizzo del tasto di tabulazione (0x09), in quanto il carattere non viene identificato allo stesso modo da tutti gli editor: nel nostro caso ci viene incontro il sistema di editing di Visual Studio che si occupa di convertire la pressione del tasto TAB in 4 spazi.

Parentesi

Nel caso di linguaggi che utilizzano le parentesi graffe {} per racchiudere blocchi di codice le parentesi di apertura devono trovarsi all'inizio della linea successiva al frammento di codice che apre il blocco; il codice contenuto nelle parentesi deve essere indentato di 4 spazi.

Es.

if (Qualcosa)
{
    FaiQualcosa();
}
else
{
    FaiQualcosaltro();
}


Commenti

I commenti dovrebbero essere usati per descrivere il maggior numero di informazioni utili alla comprensione da parte di terzi del codice che si va a realizzare.
Non ci sono linee guida riguardanti i commenti nella documentazione del .NET Framework, tuttavia sappiamo che e' commentando seguendo lo standard XML possiamo rendere il nostro codice 'parlante':

///
/// Scriviamo una descrizione per la classe Class1
///
/// Un parametro!
/// Informazioni ad uso interno
public class Class1
{
    public Class1()
    {
        //
        // TODO: Add constructor logic here
        //
    }

A questo punto la classe Class1 e' diventata 'parlante':



Questo standard dovrebbe essere rispettato per tutte le classi e i membri presenti in un progetto, allo scopo di rendere chiaro e fruibile il codice ad altri partecipanti allo sviluppo nella maniera piu' rapida possibile.

Uso degli spazi

E' possibile rendere il codice piu' leggibile diminuendone la densita' utilizzando i caratteri di spazio:

  • Usare uno spazio dopo una virgola usata per separare gli argomenti di una funzione
    Es.
    Console.In.Read(myChar, 0, 1);

  • NON usare spazi prima della parentesi di chiusura
    Es.
    Console.In.Read(myChar, 0, 1 );

  • NON usare spazi tra il nome della funzione e le parentesi
    Es.
    Console.In.Read (myChar, 0, 1);

  • Usare spazi prima dei controlli di flusso
    Es.
    while (x == y)
    if (x == y)




Naming Guidelines

La Coding Guidelines specifica le regole che devono essere applicate per scrivere il codice rispettando determinati criteri di sintassi e di forma.

La Naming Guidelines rappresenta quindi un sottoinsieme della Coding Guidelines e si focalizza nel descrivere le linee guida sulla nomenclatura dei membri(classi, interfacce, ...)

La necessità di avere delle regole comuni sulle modalità di scrittura del codice non è una novità introdotta con i nuovi linguaggi del Framework .Net: ad esempio la Notazione Ungherese è stata ed è ancora oggi una delle pratiche più conosciute dalle comunità di sviluppatori.

Con l'introduzione del Framework .Net, Microsoft ha introdotto una nuova modalità di nomenclatura del codice, più adatta ai nuovi linguaggi(completamente object-oriented) e più adatta ai nuovi tools di sviluppo.

Naming Guidelines per librerie pubbliche

Si applicano :

  • per qualsiasi membro pubblicamente esposto

  • in generale per tutte quelle parti di codice che sono documentate


L’obiettivo è quello di fornire agli sviluppatori partecipanti un unica modalità di pubblicazione delle parti pubbliche di componenti e librerie in modo da garantirne la consistenza con il resto del progetto e del Framework .NET.

Naming Convention

Tre brevi concetti prima di iniziare con l'argomento:

  • Si definiscono Pascal Cased i nomi che hanno tutte le iniziali maiuscole.
    Es. RecuperaDatiCliente



  • Sono Camel Cased quelli che hanno l’iniziale della prima parola minuscola e le iniziali delle rimanenti parole maiuscole
    Es. getElementById



  • Nella notazione ungherese, un nome di variabile inizia con un prefisso costituito da una o più lettere minuscole in modo da formare un codice mnemonico per il tipo o lo scopo di questa variabile. Il prefisso è seguito dal nome scelto dal programmatore; quest'ultima parte è spesso indicata come il “nome assegnato”.
    Il primo carattere del nome assegnato è in maiuscolo per separarlo visivamente dal prefisso (quindi in Camel Case)
    Es.



  • nSize: numero intero

  • dwLightYears: double word

  • bBusy: boolean


Le linee guida da applicare sono :

  • Tutti i tipi e membri pubblici devono essere Pascal Cased (i membri “protected” fanno parte dei membri pubblici)


Es.



class MyClass {
public string ClassName { ... } protected string GetClassName() { ... }
}


  • I parametri devono essere Camel Cased


Es.


public void LoadData(int objectId) { ... }




  • Gli acronimi sono gestiti All Cased se di 2 caratteri, Pascal Cased altrimenti



Es.


public int ID;
public string Html;


  • Non è permesso l’utilizzo della Notazione Ungherese


Es.



int iObjectId;
string strText;

Nella definizione dei nomi di metodi, eventi e proprietà con modificatori di accesso public, protected o internal :


  • Non usare gli underscores (_)

  • Non usare parole tutte maiuscole o tutte minuscole

  • Non usare la Notazione Ungherese


Usare i nomi al plurale per metodi e proprietà che ritornano collections o array

Es.

public MemberCollection GetMembers();
public Member GetMember()

Utilizzare il prefisso "Is", "Has" o "Can" nel caso di metodi che restituiscono un boolean

Es.

public boolean IsMemberOfTeam();
public boolean HasRows();
public boolean CanWrite();

Identificatori dei controlli visuali

Su questo argomento è avvenuto il cosiddetto 'scisma degli sviluppatori': sono saltate fuori 2 soluzioni, una basata sulla notazione ungherese e una orientata a sfruttare appieno le funzionalità di autocompletamento del codice presenti in Visual Studio 2005.

Come già detto, la prima scelta suggerisce l'utilizzo della ungherese, con i primi 3 (o 4) caratteri in minuscolo ad identificare il tipo di controllo.

Ecco un breve lista dei possibili prefissi da utilizzare:






































































ControlloPrefisso
Buttonbtn
ComboBoxcmb
CompareValidatorcmv
CustomValidatorctv
DataGriddgr
DateTimePickerdtp
DropDownListddl
Formfrm
Labellbl
LinkLabellnk
Panelpnl
RequiredFieldValidatorrfv
RegularExpressionValidatorrxv
TextBoxtxt
GroupBoxgrp
Ecc...Ecc...

L'altra possibilità suggerisce la possibilità di usare un codice piu' complesso per identificare i controlli visuali:

  • un prefisso di 2/3 lettere ad identificare il gruppo di controlli instanziati dall'utente (in questo caso 'ux')

  • il nome scelto per la variabile, in Pascal Case

  • Il nome del tipo di controllo creato, in Pascal Case


Esempio:
uxIndirizzoTextBox

In questo modo, in fase di scrittura del codice, basta digitare 'ux' e attivare l'autocompletamento per avere l'elenco dei controlli visuali presenti nel progetto; da li, aggiungendo le prime lettere del controllo possiamo completare la stringa con minori battute sulla tastiera.

Dopo lunghe disquisizioni, la scelta è caduta sulla seconda ipotesi. :-D

Class, Structs and Interfaces

Nella definizione di classi e interfacce :

  • Non usare prefissi per i nomi delle classi


Es.



// errato
public class CPersona {...}
// corretto
public class Persona {...}


  • Usare il prefisso “I” per i nomi delle interfacce


Es.


public interface IPersona {...}




  • Utilizzare un nome composto per le classi derivate, aggiungendo come suffisso il nome, o parte del nome, della classe base




Es.



public class PersoneCollection : CollectionBase {...}
public class CustomEventArgs : EventArgs {...}
public class CustomException : Exception {...}

Le classi non hanno bisogno di essere identificate da un prefisso in quanto rappresentano la struttura di default di ogni applicazione realizzata con il .Net Framework.

Per le interfacce è invece necessario utilizzare il prefisso “I” in modo da distinguerle dalle classi.

Denominazione degli Alias di namespace

Le Naming Guidelines documentate nel .NET Framework non suggeriscono se usare il Pascal Case o il Camel case con gli alias di namespace.

Nel C# tuttavia una delle funzioni dell'operatore :: è quella distinguere l'ambiguità che si può creare quando si definisce un Alias omonimo di un tipo, ad esempio:

using Sql = System.Data.Sql;
Class Sql {}
...
Sql::DataRow riga = null;

Questo suggerisce quindi che per evitare problemi inutili (collisioni tra nomi degli alias e dei tipi) è preferibile utilizzare il Camel case.

Naming Issues

E’ molto importante definire con accortezza anche i nomi che si vogliono assegnare ai membri pubblici di una classe che sarà esposta ed utilizzata da altri sviluppatori :


  • Usare nomi che abbiano un significato, che siano “parlanti”

  • Scegliere una lingua per identificatori e commenti

  • Evitare le abbreviazioni

  • Guardare se esistono nomi già utilizzati e conosciuti per quello che vogliamo descrivere


Es.
MyCollection.Count vs MyCollection.NumberOfElements (la proprietà Count è usata in framework diversi ed
è facilmente riconoscibile dallo sviluppatore, non
occore un nome nuovo,in questo esempio NumberOfElements
per specificare il concetto)

Fonte: Blog di Brad Abrams e sezione "Designing .Net Class Libraries" di MSDN.