Convenzioni per la programmazione in Visual Basic
Note: questo articolo è stato tratto da
MSDN - Visual Basic Programming Conventions from Microsoft Consulting Services
Tradotto e riadattato in alcune parti.
Non è quindi da intendersi come documentazione ufficiale.
1. Convenzioni sui nomi.
1.1 Obiettivi
Per aiutare i programmatori (specialmente in progetti di gruppo) standardizza e decodifica la struttura e la logica di un'applicazione.
Per essere precisi, completi, leggibili, semplici da ricordare e non ambigui.
Per essere coerenti con le convenzioni di altri linguaggi (most importantly the Visual Basic™ Programmer's Guide and standard Microsoft® Windows™ Hungarian C)
Per essere efficienti dal dimensionamento di una stringa alla visuale dell'intero progetto fino alla definizione di nomi complessi per tutti gli oggetti.
Per definire il minimo indispensabile per ottenere tutto questo.
1.2 Convenzioni
1.2.1 Option Explicit
"Option Explicit" deve sempre essere usato per forzare la dichiarazione delle variabili ed è un buon ausilio al loro commento.
Il tempo perso cercando di trovare i bugs causati da digitazioni (aUserNameTmp vs. sUserNameTmp vs. sUserNameTemp) supera notevolmente il tempo necessario per una Dim.
1.2.2 Denominazione dei Controlli
La tavola seguente definisce il nostro standard dei prefissi per i controlli.
Tavola 1. Standard Prefissi per i nomi dei controlli
Prefix
Control Type Description
ani
Animation button
bed
Pen Bedit
cbo
Combobox e dropdown Listbox
chk
Checkbox
clp
Picture Clip
cmd
Command Button
com
Communications
ctr
Control (Usato dentro le procedure quando il tipo di controllo specifico è
sconosciuto)
db
ODBC Database
dir
Dir List Box
dlg
Visual Basic Pro Common Dialog
drv
Drive List Box
ds
ODBC Dynaset
fil
File List Box
frm
Form
fra
Frame
gau
Gauge
gpb
Group Push Button
grd
Grid
hed
Pen Hedit
hsb
Horizontal Scroll Bar
img
Image
ink
Pen Ink
key
Keyboard key status
lbl
Label
lin
Line
lst
Listbox
mpm
MAPI Message
mps
MAPI Session
mci
MCI
mnu
Menu
opt
Option Button
ole
Ole Client
pic
Picture
pnl
3d Panel
shp
Shape
spn
Spin Control
txt
Text/Edit Box
tmr
Timer
vsb
Vertical Scroll Bar
1.3 Note per il Prefisso dei Controlli
1.3.1 Menu
Dato che i menu possono essere numerosi, la denominazione dei menu richiede un po' più di attenzione. I prefissi dei menu continuano oltre l'iniziale
"mnu" aggiungendo un ulteriore lettera maiuscola per ogni livello di nidificamento, con il nome del menu derivato dalla stessa caption alla fine.
Quando c'è ambiguità causata da duplicazione di caratteri, come un menu con un Main con la stessa iniziale, ad es: Format e File, verrà usata una lettera minuscola addizionale per differenziarli.
Esempi:
Struttura del menu
Nome del menu
Help.Contents
mnuHContents
File.Open
mnuFiOpen
Format.Character
mnuFoCharacter
File.Send.Fax
mnuFSFax
File.Send.Email
mnuFSEmail
In questo modo tutti i membri di un gruppo di menu saranno elencati vicini gli uni agli altri.
Questo è un sistema molto efficiente di trovare un particolare menu, specie se ve ne sono molti.
Per ridurre il numero di menu elencati un eccessivo sparpagliamento del codice è possibile definire un array di menu per tutte le voci dello stesso livello.
In questo caso la denominazione segue le stesse regole di cui sopra omettendo però la parte finale del nome.
Gli indici verranno identificati da costanti con prefisso "MNU_" e il relativo codice sarà gestito nell'evento click tramite una Select.
Esempi:
Struttura del menu
Nome del menu
Help.Contents
mnuH(MNU_CONTENTS)
File.Open
mnuFi(MNU_OPEN)
Format.Character
mnuFo(MNU_CHARACTER)
File.Send.Fax
mnuFS(MNU_FAX)
File.Send.Email
mnuFS(MNU_EMAIL)
1.3.2 Altri controlli
Per i controlli non elencati sopra viene lasciato al buon senso del programmatore trovare un prefisso univoco che identifichi la classe.
1.3.3 Denominazione di variabili e routine
Il nome di variabili e funzioni ha la seguente struttura:
<prefisso><corpo><qualificatore><suffiso>
Il prefisso descrive l'uso e lo scopo di una variabile come in iRecordNext e sNameFirst.
ll qualificatore denota uno standard di derivazione di una variabile o funzione come in iRecordNext e sNameFirst.
Il suffisso è l'opzionale carattere che identifica il tipo ($, %, #, e così via).
Il prefisso per le funzioni pubbliche dovrebbe identificare, a differenza di quanto avviene per le variabili, il modulo di provenienza seguendo le stesse regole per il suffisso dei controlli.
Es: Modulo Graphics.bas -> Function DrawLine --> Function grpDrawLine
E' consigliato l'uso del descrittore As Tipo nella dichiarazione, anzichè il carattere di tipo.
Le variabili devono sempre essere tipizzate anche se dichiarate Variant.
L'uso del tipo Variant sarà discusso più avanti.
Prefissi
La tavola seguente definisce i prefissi delle variabili che sono basati sul C ungherese.
Questi dovrebbero essere usati universalmente, persino con le variabili tipizzate.
Tavola 2. Prefissi per i nomi di variabili
Prefisso
Descrizione del tipo di variabile
b
Boolean
c
Currency - 64 bits (vb type = @)
d
Double - 64 bit signed quantity (vb type = #)
db
Database
ds
Dynaset
dt
Date+Time
f
Float/Single - 32 bit signed floating point (vb type = !)
h
Handle (vb type = &)
i
Index (vb type = %, &) *NDO* riconducibile a "l"
l
Long - 32 bit signed quantity (vb type = &)
n
Integer (sizeless, counter) (vb type = %) *NDO* riconducibile a "l"
s
String (vb type = $)
u
Unsigned - 16 bit unsigned quantity (must use &) *NDO* riconducibile a "l"
ul
Unsigned Long - 32 bit unsigned quantity (must use #) *NDO* riconducibile a "l" se la quantità lo permette
v
Variant (big and ugly to discourage use and make sure it gets the reader's attention)
w
Word - 16 bit signed quantity (vb type = %) *NDO* riconducibile a "i"
a
Array
t
User defined type
y
Byte
Il metodo ungarico è utile in Visual Basic in quanto il nome da solo non dà informazioni sufficienti sullo scopo di una variabile e del suo contenuto.
Per esempio, iSend (che probabilmente è un contatore per i messaggi spediti),
bSend (che probabilmente è un flag che indica il successo dell'ultima operazione di invio), e
hSend (che probabilmente è un handle per un oggetto) suggeriscono molto concisamente qualcosa di differente. Questa informazione è persa quando il nome è semplicemente
Send.
Corpo
Il corpo di un nome di variabile o routine dovrebbe usare lettere maiuscole e minuscole in modo da descrivere il loro scopo. Nomi di funzioni dovrebbero inoltre iniziare con un verbo come in InitNameArray o CloseDialog.
Per termini lunghi o usati frequentemente, abbreviazioni (come Init, Num, Tbl, Cnt e Grp per Number, Table, Count, e Group) sono suggerite per mantenere il nome della funzione il ragionevolmente corto.
Quando queste abbreviazioni sono usate DEVONO essere usate coerentemente in tutto il progetto: passare casualmente da "Cnt" a "Count" all'interno dello stesso progetto produce frustrazione negli sviluppatori.
Qualificatori
Spesso vengono usate variabili e relative routines per gestire e manipolare oggetti comuni.
In questi casi può essere veramente d'aiuto standardizzare i qualificatori. Benchè mettere il qualificatore dopo il corpo può suonare male (come in sGetNameFirst, sGetNameLast anzichè sGetFirstName e sGetLastName), questa pratica aiuterà ad ordinare e a tenere raggruppati nell'editor di VB le funzioni rendendo anche più semplice la comprensione della struttura dell'applicazione
La tavola seguente definisce i qualificatori più comunemente usati e il loro significato.
Tavola 3. Qualificatori comuni
Qualificatore
Descrizione (a seconda del corpo)
First
primo elemento di un set.
Last
ultimo elemento di un set.
Next
prossimo elemento in un set.
Prev
elemento precedente in un set.
Cur
elemento corrente di un set.
Min
valore minimo in un set.
Max
valore massimo in un set.
Save
Usato per salvare un valore che sarà ripristinato in seguito.
Tmp
Una variabile temporanea con scopo fortemente localizzato.
Src
Sorgente (Source).
Dst
Destinazione (Destination). Spesso usata insieme a Source.
1.3.4 Denominazione di Constanti
Il nome di una costante deve essere scritto in MAIUSCOLO con un underscores ("_") tra le parole.
Un eventuale prefisso che denota lo scopo di una costante deve essere anteposto al nome sempre in maiuscolo e separato dal nome da un underscore
Esempi:
WM_CLICK
Window Message, con valore per "Click"
NEW_LINE
New Line character string
1.3.5 Tipi di dato Variant
Con la sola eccezione elencata sotto i tipi Variant NON dovrebbero essere usati.
Quando è necessaria una conversione di tipo le variabili Variant probabilmente offrono una performance leggermente migliore rispetto alle funzioni di conversione esplicita (val(), str$(), and the like), ma questo non è sufficiente per giustificare l'ambiguità e la
trascuratezza generale del codice
Esempi:
vnt1 = "10.01" : vnt2 = 11 : vnt3 = "11" : vnt4 = "x4"
vntResult = vnt1 + vnt2 ' Does vntResult = 21.01 or 10.0111?
vntResult = vnt2 + vnt1 ' Does vntResult = 21.01 or 1110.01?
vntResult = vnt1 + vnt3 ' Does vntResult = 21.01 or 10.0111?
vntResult = vnt3 + vnt1 ' Does vntResult = 21.01 or 1110.01?
vntResult = vnt2 + vnt4 ' Does vntResult = 11x4 or ERROR?
vntResult = vnt3 + vnt4 ' Does vntResult = 11x4 or ERROR?
Additionally, the type conversion routines assist in documenting implementation details, which make reading, debugging, and maintaining code more straightforward.
Esempio:
(iVar1 = 5 + val(sVar2) 'usa questo
vntVar1 = 5 + vntVar2 'non questo!
Eccezione
Raramente è necessaria (specie lavorando con database, message, DDE, o OLE), una funzione generica che può ricevere dati di qualsiasi tipo.
Esempio:
Sub ConvertNulls(rvntOrg As Variant, rvntSub As Variant)
If rvntOrg = Null, replace the Null with rvntSub
If IsNull(rvntOrg) Then rvntOrg = rvntSub
End Sub
2. Commenti
Tutte le procedure devono iniziare con una breve descrizione delle caratteristiche funzionali.
Questa descrizione NON deve dire come è implementata la routine, poichè questo può variare nel tempo portando a perdite di tempo nel rivedere i commenti e soprattutto a commenti erronei
Il codice stesso e ogni eventuale suo commento descriverà l'implementazione.
I parametri devono essere descritti se (a) sono di dubbia interpretazione (questo non dovrebbe mai accadere) (b) richiedono dei valori specifici per il funzionamento della funzione (c) il valore viene modificato all'interno della routine (questo dovrebbe accadere solo se il parametro modificato è un valore di ritorno richiesto: nessuna funzione deve prendersi la libertà di modificare il valore dei parametri che non devono restituire un valore)
Ogni variabile di dubbia utilità deve essere commentata.
I nomi di variabili, funzioni, controlli e quant'altro deve essere chiaro a
sufficienza.
Note: la Project window descrive solo i files nel progetto, quindi tutti i files esterni (come INI, DB ecc...) dovrebbero essere descritti.
3. Formattazione del Codice
I blocchi di indentazione (tab) devono essere di quattro spazi.
Il commento alla funzione dovrebbe essere indentato di una tabulazione.
Il primo statement della funzione dovrebbe partire indentato di un tab, e un tab per ogni linea di codice all'interno del blocco.
Function iFindUser (rasUserList() as String, rsTargetUser as String) as Integer
' Search UserList and if found, return index of first occurrence of TargetUser,
' else return -1
Dim i as Integer 'loop counter
Dim bFound as Integer 'target found flag
iFindUser = -1
i = 0
While i <= Ubound(rasUserList) and Not bFound
If rasUserList(i) = rsTargetUser Then
bFound = True
iFindUser = i
End If
Wend
End Function
Variabili e costanti devono risiedere nella sezione "Dichiarazioni" raggruppare per scopo/utilità.
Tutte le dichiarazioni globali dovrebbero risiedere in un modulo comune.
Le dichiarazioni delle variabili e costanti dovrebbero seguire il seguente ordine:
public const
public enum
public type
private const
private enum
private type
public
private / dim
Declare
4. Operatori
Usare SEMPRE "&" quando si concatenano stringhe e "+" lavorando con valori numerici.
L'uso del solo "+" può portare a problemi lavorando con due variabili (specie con i variant).
Per esempio:
vntVar1 = "10.01"
vntVar2 = 11
vntResult = vntVar1 + vntVar2 'vntResult = 21.01
vntResult = vntVar1 & vntVar2 'vntResult = 10.0111
5. Scope
Le variabili vanno sempre definite con il più piccolo scope possibile.
Variabili globali possono creare enormi e complessi stati di macchina e rendere incomprensibile la logica di un'applicazione.
Inoltre rendono il riuso e il mantenimento del codice molto più complesso.
Se vengono usate variabili globali vanno tenute raggruppate per funzionalità e commentate bene.
Con l'eccezione di variabili globali che non dovrebbero essere passate, le funzioni DEVONO lavorare SOLO con ciò che gli è stato passato.
Variabili globali che devono essere passate alle funzioni devono essere commentate adeguatamente.
Segmenta la logica dell'applicazione in blocchi il più possibile.
Questo aiuterà a suddividere la complessità dell'applicazione e a minimizzare il suo run-time everhead.
Per tutti i Sistemi Operativi