The purpose of this document is to describe a set of coding conventions (a frame-work if you will) which
can be used for your Visual Basic projects. This standard uses a combination of Hungarian
notation and information from other sources such as TMS’s VB Vogue, and various Microsoft publications.
Using these standards as a platform, additions and modifications were performed by software developers
in real-world applications. Adhering to a standard like this will ensure uniform development
across your code, and across applications.
Naming Conventions
Type Information
Hungarian type prefixes have two parts: a base type to represent the base data
type and a modifier to denote an aggregate type. An example of a base-type prefix is n,
which denotes an integer, while adding the a modifier to the base type denotes an array of integers.
Dim nCount As Integer
Dim anCounters(1 to 5) As Integer
The variable name itself starts with an upper case character to show where the prefix stops and
the variable name starts. There may be cases where you would need to use more than one modifier,
as in the case of a multi-dimensional array.
Dim aanMultiTable (1 to 5, 1 to 10) As Integer
The letter ‘a’ is the only single type aggregate supported by Visual Basic, so it will be the
only type modifier listed here. (note: a collection is not single type and is denoted by the prefix ‘col’).
Calls made to windows API functions are commonly given different naming conventions such as sz
and LPSTR. These standards are used in MS Windows documentation and for simplicity and reference
should not be modified. You may also see p used to denote a pointer and pcb used to denote the
address of a callback function.
For variables defined with user-defined types and classes, the base-type characters udt and c are used.
The upper case C is used to name a class module, and any object created from that class is named with a
lower case c. User-defined types and variables instantiated from them are prefixed with UDT and udt,
respectively.
Dim cNewUser As New CPerson
Dim udtNewUser As New UDTPerson
Menus are named with the type prefix mnu, but the names are aggregated to show
the actual structure of the menu. For example, the About item of the Help menu would be named:
mnuHelpAbout
mnuFileOpen
Scope Information
There are also prefixes used to denote an object’s scope. The scope prefixes come between the
type prefix and the object name, so you need to make sure that they start with an uppercase
and end with a lowercase letter. This way the scope will stand out from the type prefix and
the object itself. Examples some scope modifiers are Gb, for global, and Pi for private.
Variables
Variables are named in the following manner:
The is simply the variable name written with mixed case as described earlier.
It is considered bad practice to name a variable using the underscore character ‘_’.
This character is more commonly used for sub and function names.
Local Variables do not have a scope prefix. Here are some examples of local variable defenitions:
Dim nCount As Integer
Dim sQuery As String
Dim cUser As New Cperson
Private variables defined at the module level have Pi as a scope prefix:
Private nPiCount As Integer
Private sPiQuery As String
Private cPiUser As New Cperson
Public variables defined at the module level of a standard module
(i.e. BAS file) have the scope prefix Gb:
Public nGbCount As Integer
Public sGbQuery As String
Public anGbThisArray() As Integer
NOTE: Public variables defined at the module level of classes or Forms, are considered
Properties and do not have and scope or type prefix.
Functions and Subroutines
Public functions and subroutines have scope prefixes in the same way that variables do.
Public and private functions also use the type prefix to show what type of value they return.
The rules for choosing the type and scope prefix are the same as for variables.
Private subroutines and functions do NOT require scope prefixes.
Here are some examples of private subroutines:
Private Sub ClearGrid()
Private Sub DeleteImportantInfo()
And Private functions:
Private Function nNextItem() as Integer
Private Function sGetPath (byVal sFileName As String) As String
Global subroutines are prefixed in exactly the same way that global variables are:
Public Sub GbClearGrid()
Public Function nGbNextValue() As Integer
Public functions and subroutines defined in classes and forms are methods and
do not have type or scope prefixes.
Protected form and class properties, Property Let, Property Set, and Property Get
routines do not have scope of type prefixes.
Declaring Windows API functions.
Use the Alias keyword to add the prefix Win.
For example, CallWindowProc becomes WinCallWindowProc. When declaring other
DLL functions, use the prefix Dll.
Contols and Forms
Prefixes for controls and forms are given at the end of this document. Forms are named in the
same manner as controls, though a form behaves like, and basically is, a class. Forms are named
with the prefix frm.
Dim frmNewBrowser As New frmSaleBrowser
Constants
Constants are named in all uppercase letters with no type or scope prefix. Arbitrary prefixes,
possibly separated by and ‘_’ (since it is all uppercase) can show the relationship between contants.
Const DEFAULT_KEY As String = "VBMAHJONGG"
Const DEFAULT_SECTION As String = "DATABASE INFO"
Type and Class Definitions
Type names are prefixed with UDT for the declaration and for the dimensioned variable,
the lowercase udt is used. This rule applies to classes as well, using uppercase C
and lowercase c respectively.
Type UDTPerson
sFullName As String
nSalary As Integer
End Type
And in use:
Dim udtNewUser As UDTPerson
Dim cNewOpp As New Copportunity
Coding Conventions
This section contains several conventions that should be useful when writing code.
They are by no means comprehensive, but should nonetheless be seriously considered
in development. This section will continue to be developed in order to obtain a
complete development guide. The Changing Your Approach subsection talks about
four very important rules that you can follow that help you take advantage of VB5/6’s
object oriented capability. The Principles subsection gives smaller and more specific
suggestions on coding style.
Changing Your Approach
There are three rules (so far) that you can quickly apply to your coding style that
will quickly improve its quality. These rules are also a simple way to force yourself
to take advantage of VB5/VB6’s Object Oriented Programming capability. These are not
necessarily in order of importance, but number one is, in my opinion, extremely important
and simple to implement. Some of this information may be repeated in the Principles subsection.
- Do not use global variables. This means literally NO global variables. Understanding class modules and the (finally) ability to treat forms as objects in VB5 makes it unnecessary to have any global variables. Why not? Well the short answer is that global variables create a possible dangerous interdependency between different parts of your program. They are also difficult to trace properly. If you need to share information between objects or forms, make that information a property or method of your object, do not use a global variable. A global variable is easy to define and use initially, but they ALWAYS create more problems then they solve in the long term. Some applications have a particular functionality that may seem to lend itself to a small number of global variables. An example of this could be a global instance of a User class. This could be seen as acceptable because the nature of this variable is truly global, in the sense that it could be needed in every part of the application. For the most part, you should never have more global variables than you can count on one hand.
- Do not use user-defined types. This means anything with the Type statement in it. These structures were quite effectively replaced by classes in VB5. If you have something that is a candidate for a user-defined type, then it is a candidate for a class. Besides classes are more powerful and FUN! There is one exception to this rule, that is if you are calling a DLL that requires a structure.
- Do not pass function parameters by reference. Unfortunately, the default way in which variables are passed in Visual Basic is by reference. Prefix all of your sub and function parameters with the keyword ByVal. There are a million reasons not to pass by reference, but mainly it is very hard to trace a bad value if a called procedure is (knowingly or unknowingly) modifying your variable in memory.
Principles
Write your code for the reader. In rapid application development clarity is more cost effective than
efficiency. Understanding efficiency is important, and should serve as a guide in your coding,
however clearly written and documented code is easier to understand and maintain. By today’s
standards, processing cycles are extremely inexpensive, so highly efficient and cryptic code can
cost more in the later phases of the development life cycle. Here are some high level guidelines:
- Be verbose rather than terse.
- Parenthesize _expression to make them clearer.
- Code for clarity, not efficiency.
- Limit the scope of variables, constants, functions and subroutines. If you have the choice, always use local objects instead of global ones.
- Use explicit type conversions (Cint, Cstr, and so on) when assigning different variable types.
Some Specifics:
Follow these guidelines when writing your code.
- Define all variables explicitly. Option Explicit enforces this, and you can force Option Explicit in all objects by checking the Require Variable Declaration under the Tools > Options > Editor.
- Always specify the upper and lower bounds in an array definition.
- Define constants, and use them in place of hard-coded numbers in your code.
- Always use the ByVal and ByRef keywords in the parameter lists of your subroutines and functions. You should generally not use ByRef at all (see Changing Your Approach above)
- Always use the Private keyword on functions and subroutines that are not used outside of a module.
- Declare all variables explicitly. Dimensioned variables are variant if no type is supplied but you should always supply a type, even if that type is variant (e.g Dim nX As Integer, Dim vThing as Variant). This also applies to subroutines and functions. Such as Function sTest () as String instead of Function sTest().
- Do not use implicit type suffixes such as ! and & in variable definitions.
- In For loops, use Next instead of just next.
Documentation
One of the best sources of documentation is the code itself. If you follow specific coding
standards throughout your application and thoroughly comment your code, you are making your
program more readable and providing valuable information to yourself and to other programmers
that might have to make modifications later.
Formatting
Follow these rules when formatting your code:
- Indent your code to 4 spaces. This setting is available in the code settings sections available through Tools>Options>Editor.
- Punctuate your code with blank lines.
- Keep your procedures to a manageable size, preferably not more than a single screen.
- Keep your indentation under control, if you are having difficulty remaining within the right margin, you are probably nesting too deeply.
- Use Parenthesis to enhance the readability of your code. People should be able to tell what a given formula does at first glance.
End-of-Line Comments
End-of-Line comments should be used to annotate variable and constant definitions.
Const MAX_LINES = 200 'The max lines allowable in grdOne
Dim nX As Integer 'used to index record counting loop in my VB program!
In-Line Comments
End-of-line comments are usually not needed for annotating your actual code. In general the syntax
of VB is readable. In cases where a function or subroutine contains a certain number of logical blocks,
you can introduce each block with a separate comment on it’s own line. Use as many lines for the
comment as you need, but keep the lines short so that they can be displayed on a VGA monitor without
scrolling left and right. End-of-line comments are sometimes helpful to comment ‘Loop’, ‘Next nJ’, ‘Else’
and ‘ElseIf’ in order to clarify the expected condition, or identify the top of the loop.
Use comments to explain the code, not echo it; if your comments become very involved, consider
restructuring the code. For more complicated subroutines, it may be more informative to move
complicated documentation into the routine’s header documentation.
File Headers
Every module should have a header that sits as a comment in the module’s defenitions area.
This header identifies the module and summarizes the external interfaces to it. Here is an example:
'***************************************************************
'* Module: Utilities
'*
'* File Name: util.bas
'*
'* Author: Orville Chomer
'*
'* Description:
'*
'* This module contains all of the generic utilities used
'* in the cool Chomer.com application.
'*
'*
'*
'* Revisions:
'*---date------rev. by--------------brief descr.-----------------
'* 1.27.2006 O.Chomer added instance checking
'*
'*
'***************************************************************
Function and Subroutine Headers
A function header is a comment that describes what the function does and summarizes its interface.
The description should focus on what the function does, although for complicated or longer functions
it might be appropriate to summarize the how as well.
Here is an example of a function header.
'***************************************************************
'* Synopsis: Initialize the Opp Browser form
'*
'*
'* Parameters:
'*----name------------------[I/O]--description------------------
'*
'*
'* Nonlocal Data:
'*----name------------------[I/O]--description------------------
'*
'*
'*
'* Description:
'* - init forms and private variables
'* - init the user selection tree, or load if management
'* - check user permissions to use the form
'* - load the grid with current opps
'*
'* > O.Chomer 11/2/05
'***************************************************************
Type Prefixes
This section details the type prefixes to use in you applications. Remember that, in
order to be effective, these should be used consistently throughout your code.
Variable Prefixes:
| Prefix |
Data Type |
| b |
Boolean |
| byt |
Byte |
| col |
Collection |
| cur |
Currency |
| dte |
Date |
| d |
Double |
| hf |
File handle (Long) |
| h(...lowercase) |
Handle to something (long) |
| n |
Integer |
| l |
Long |
| o |
Object |
| c |
Object instantiated from a class |
| f |
Single |
| s |
String |
| v |
Variant |
| hwnd |
Window handle (Long) |
Modifiers and Special Type Prefixes
Table 2
| Prefix |
Data Type |
| a |
Array |
| C |
Class (not class instance) |
| udt |
User defined type |
| e |
Enumerated type or instance |
| p |
Pointer (used in API calls) |
| pcb |
Pointer to a callback function (used with AddressOf) |
Data Objects: DAO Prefixes
Table 3
| Prefix |
Visual Basic Data Type |
| bk |
SelBookmarks |
| ct |
Container |
| db |
Database |
| dc |
Document |
| ds |
Dynaset |
| er |
Errors |
| fld |
Field |
| gp |
Group |
| idx |
Index |
| pa |
Parameter |
| qd |
QueryDef |
| rs |
Recordset |
| rl |
Relation |
| ss |
Snapshot |
| tbl |
Table |
| td |
TableDef |
| usr |
User |
| wrk |
Workspace |
Data Objects: RDO Prefixes
Table 4
| Prefix |
Visual Basic Data Type |
rdoEng
rdoEngine
rdoEnv
rdoEnvironment
rdoConn
rdoConnection
rdoTbl
rdoTable
rdoCol
rdoColumn
rdoPrepS
rdoPreparedStatement
rdoParam
rdoParameter
rdoRS
rdoResultset
rdoErr
rdoError
Control Prefixes
Table 5
| Prefix |
Control Type Description |
| pnl |
3d panel |
| ani |
Animation button |
| chk |
Checkbox |
| cbo |
Combobox/Dropdown Listbox |
| cmd |
Command button |
| crp |
Crystal Reports Control |
| dlg |
Common dialog |
| com |
Communications |
| *cur |
Currency Control |
| dat |
Data control |
| *dte |
Date Control |
| dir |
Directory listbox |
| drv |
Drive listbox |
| fil |
File listbox |
| frm |
Form |
| fra |
Frame |
| gau |
Gauge |
| gra |
Graph |
| grd |
Grid |
| gbp |
Group pushbutton |
| hsb |
Horizontal scroll bar |
| img |
Image |
| iml |
ImageList |
| key |
Keyboard key status |
| lbl |
Label |
| lin |
Line |
| lst |
listbox |
| lvw |
ListView |
| mpm |
MAPI message |
| mps |
MAPI session |
| msk |
Mask TextBox |
| mci |
MCI |
| mnu |
Menu |
| ole |
Ole Client |
| opt |
Option button |
| out |
Outline Control |
| bed |
Pen BEdit |
| hed |
Pen HEdit |
| ink |
Pen ink |
| pic |
Picture |
| clp |
Picture clip |
| pbr |
ProgressBar |
| Rdc |
Remote date control |
| Rtf |
RichTextBox |
| Shp |
Shape |
| Sld |
Slider |
| spn |
Spin control |
| tab |
SS Tab Control |
| txt |
Text box |
| tim |
Timer |
| tbr |
Toolbar |
| tvw |
TreeView |
| vsb |
Vertical scroll bar |
*dte and cur are also variable prefixes but dte and cur would commonly begin with two
letter signifying the third party vendor, for example the cur control could be named fpcurMonthlyTotal.
Data-Bound Control Prefixes
Table 6
| Prefix |
Control Type Description |
| dbcbo |
Databound ComboBox/Dropdown ListBox |
| dblst |
Databound listbox |
| dbgrd |
Databound grid |
* These are also used for the Currency and Date variable types, as well as custom or third
party currency and date controls.
|