Visual Basic Programming Conventions from Microsoft Consulting Services

1. Naming Conventions

1.1 Objectives

1.2 Conventions

1.2.1 Option Explicit

"Option Explicit" must always be used to force proper variable declarations and aid good variable commenting. The time lost trying to track down bugs caused by typos (aUserNameTmp vs. sUserNameTmp vs. sUserNameTemp) far outweighs the time needed to Dim variables.

1.2.2 Control naming

The following table defines our standard Control name prefixes. (These are consistent with those documented in the Visual Basic 2 Programmers Guide.)

Table 1. Standard Control Name Prefixes

Prefix Control Type Description
ani Animation button
bed Pen Bedit
cbo Combobox and dropdown Listbox
chk Checkbox
clp Picture Clip
cmd Command Button
com Communications
ctr Control (Used within procs when the specific type is unknown)
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 Control Prefix Notes

1.3.1 Menus

Because Menu handlers can be so numerous, Menu names require a little more attention. Menu prefixes therefore continue beyond the initial Mnu label by adding an additional (upper case) character prefix for each level of nesting, with the final menu caption being spelled out at the end of the name string. When there is ambiguity caused by character duplications, such as a menu having both main Format and File menus, use an additional (lower case) character to differentiate the items. Examples:

Menu Caption Sequence Menu Handler Name
Help.Contents mnuHContents
File.Open mnuFiOpen
Format.Character mnuFoCharacter
File.Send.Fax mnuFSFax
File.Send.Email mnuFSEmail

This results in all the family members of a particular menu group being listed right next to each other. This multi-tiered format provides a very direct way to find a menu handler, especially when there are a great many of them.

1.3.2 Other controls

For new controls not listed above, try to come up with a unique 3-character prefix. However, it is more important to be clear than to stick to 3 characters. For derivative controls, such as an enhanced list box, extend the prefixes above so that there is no confusion about what control is really being used. For example, a control instance created from the Visual Basic Pro 1.0 3D Frame could use a prefix of fra3d to make sure there is no confusion over which control is really being used.

1.3.3 Variable and routine naming

Variable and function names have the following structure:

<prefix><body><qualifier><suffix>

The prefix describes the use and the scope of the variable, as in iGetRecordNext and sGetNameFirst. The qualifier is used to denote standard derivatives of a base variable or function, as in iGetRecordNext and sGetNameFirst. The suffix is the optional Visual Basic type char ($, %, #, and so on).

Prefixes

The following table defines variable/function name prefixes that are based on Hungarian C. These must be used universally, even when Visual Basic suffixes (such as %, &, #, and so on) are also used.

Table 2. Prefixes for Variable and Function Names

Prefix Variable Use Description (precedes Control prefix and body)
b Boolean (vb type = %)
c Currency - 64 bits (vb type = @)
d Double - 64 bit signed quantity (vb type = #)
db Database
ds Dynaset
dt Date+Time (vb type = variant)
f Float/Single - 32 bit signed floating point (vb type = !)
h Handle (vb type = %)
i Index (vb type = %)
l Long - 32 bit signed quantity (vb type = &)
n Integer (sizeless, counter) (vb type = %)
s String (vb type = $)
u Unsigned - 16 bit unsigned quantity (must use &)
ul Unsigned Long - 32 bit unsigned quantity (must use #)
vnt Variant (big and ugly to discourage use and make sure it gets the reader's attention)
w Word - 16 bit signed quantity (vb type = %)
a Array
User defined type
Prefix Scope or Use (precedes Use prefix above)
g Global
m Local to module or form
st Static variable
v Variable passed by value (local to a routine)
r Variable passed by reference (local to a routine)

Hungarian is as valuable in Visual Basic as it is in C because the Visual Basic type suffixes alone do not provide standard (and valuable) information about what a variable/function is used for or where it is accessible. For example, iSend (which might be a count of the number of messages sent), bSend (which might be a flag/Boolean defining the success of the last Send operation), and hSend (which might be a handle to the Comm interface) all succinctly tell a programmer something very different. This information is fundamentally lost when the name is reduced down to Send%. Scope prefixes such as g and m also help reduce the problem of name contention, especially in multideveloper projects. Hungarian is also well known to Windows programmers and constantly referenced in Microsoft and industry programming books. Additionally, the bond between C programmers and Visual Basic programmers can be expected to become much stronger as Visual C++ begins to live up to its potential. This transition will result in many Visual Basic programmers moving to C for the first time and many programmers moving fluidly back and forth between each environment.

Body

The body of variable and routine names should use mixed case and should be as long as needed to describe their purpose. Function names should also begin with a verb, such as InitNameArray or CloseDialog.

For frequently used or long terms, abbreviations (such as Init, Num, Tbl, Cnt, and Grp for Initialization, Number, Table, Count, and Group) are suggested to help keep name lengths reasonable. Names greater than 32 characters generally begin to inhibit readability on VGA displays. When abbreviations are used, they must be used consistently throughout the application. Randomly switching between "Cnt" and "Count" within a project will greatly frustrate developers.

Qualifiers

Often related variables and routines are used to manage and manipulate a common object. In these cases it can be very helpful to use standard qualifiers to label the derivative variables and routines. Although putting the qualifier after the body of the name might seem a little awkward (as in sGetNameFirst, sGetNameLast instead of sGetFirstName, and so on), this practice will help order these names together in the Visual Basic editor routine lists, making the logic and structure of the application easier to understand.

The following table defines common qualifiers and their standard meaning.

Table 3. Common Qualifiers

Qualifier Description (follows Body)
First First element of a set.
Last Last element of a set.
Next Next element in a set.
Prev Previous element in a set.
Cur Current element in a set.
Min Minimum value in a set.
Max Maximum value in a set.
Save Used to preserve another variable which must be reset later.
Tmp A "scratch" variable whose scope is highly localized within the code. The value of a Tmp variable is usually only valid across a set of contiguous statements.
Src Source. Frequently used in comparison and transfer routines.
Dst Destination. Often used in conjunction with Source.

1.3.4 Constant naming

mnUSER_LIST_MAX 'Max entry limit for User list (integer value, local to module)
gsNEW_LINE 'New Line character string (global to entire application)

1.3.5 Variant data types

With the single exception listed below, variants should NOT be used. When a type conversion is needed, variant use would probably provide a slight performance win over the explicit basic type conversion routines (val(), str$(), and the like), but this gain is not sufficient to overcome the ambiguity and general sloppiness they allow in code statements.

Example:

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.

Example:

(iVar1 = 5 + val(sVar2)     'use this
vntVar1 = 5 + vntVar2       'not this!

Exception

While working with databases, messages, DDE, or OLE, a generic service routine can receive data that it does not need to know the type of in order to process or pass on.

Example:

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. Commenting

3. Code Formatting

Because many programmers still use VGA displays, screen real estate must be conserved as much as possible while still allowing code formatting to reflect logic structure and nesting. For this reason:

4. Operators

5. Scope