This article provides the recommended
standards, as directed by Microsoft, for developing and maintaining Visual
Basic applications. I'm sure there are
some areas that maybe unclear or that you may not agree with, remember these
are recommended standards and I realize that there are always exceptions, so by
all means please feel free to make suggestions or recommend publications. I have also included three utilities
to help you quickly modify your existing code (be sure you check them
out). These utilities will not fix
everything, but it is a start. There is
a forth utility, an add-in called “Code Fixer” written by Roger Gilchrist that
you can download from PSC, which may also help point you to problem areas in
your existing code.
Why use programming
standards? The same attributes that
make the Visual Basic® development system exceptionally productive and easy to
use can also inadvertently lead to sloppy programming. Whether you’re writing just a few lines of
code or you’re part of a team, building a full-scale e-commerce application,
using standardized techniques can help you exploit the power of rapid
development without creating hidden land mines in performance and
maintainability.
I am not a professional
programmer but I do try to write applications that not only work well but also
look good, both to the user of the application and my fellow programmers. There are a lot of excellent applications on
PSC that have received poor votes just because they were written poorly. I have learned a lot from the code posted
here on PSC and hopefully you will find this helpful.
Standards for VB programming:
- Always include Option Explicit
in the declaration section of every code window. This will help you catch errors caused by typing
mistakes. If you don’t, any
variables or Functions you don’t explicitly declare will be set to the
Variant data type by default, which is very memory intensive and very slow
to process.
- Always declare integer
variables as Longs whenever possible (this is especially true for
variables used in math functions).
VB6's Integer data type is 16 bit, unlike all the other programming
languages, while the Long data type is 32 bit. Since the OS is 32 bit, it
takes longer to process 16 bit data.
Also, if you are doing integer division use “\” instead of “/”; it
is much faster.
- Don’t use the obsolete
type suffixes to define a variable (example: Dim
strString as String is better then Dim
strString$). See the included utility for automatically formatting
your code.
- Use an ampersand
(&) to concatenate strings instead of the addition (+) symbol.
- If a variable is not
going to change, then declare it as a constant. Constants can make your
programs self-documenting and easy to modify. Unlike variables, constants
can't be inadvertently changed while your program is running.
- Never let VB determine
the date type. For example Const C_SPI_GETWORKAREA = 48 should be Const C_SPI_GETWORKAREA As Long = 48&. If you declare it as Long and then pass it an
integer, VB does a data conversion that takes processor time (48 vs.
48&).
- Dim should not be used
in the declaration section of code; instead use Private or Public. The Global
declaration type is an old command and should not be used.
- Use common naming
conventions, for instance Form names begin with ‘frm’, Modules begin with
‘mod’, Classes begin with ‘cls’, Textbox begins with ‘txt’, Labels begins
with ‘lbl’, ComboBox begins with ‘cbo’, Command Buttons begin with ‘cmd’,
and so forth. If you're declaring
module scope variables, use the m followed by the data type prefix (see the Appendix for a
complete list of Microsoft naming standard for VB6). By following these naming standards,
you will be able to look at a variable in the middle of some code and, by
its name, know its data type and scope (global, module level, or procedure
level).
- Don’t define variables
with same name as a Visual Basic® Command/Property/Control
(like Width or Height).
Although this is allowed by VB, it makes you code difficult to
read. Also, Main is a VB system
Sub name and should not be used for anything else.
- Try to avoid using Static variables, they are very memory
intensive (use about 3 times the memory); try using a Private module level
variable instead.
- Avoid multiple
declarations on a single line, but instead expand them to one per line.
Multiple Dim lines are more difficult to read. Note: Declaring a whole line
with a single ‘As Type’ is no longer supported.
- Avoid using Colon
delimited lines of code (X=1: Y=4).
- The VB documentation consistently omits the trailing $
character in all string functions.
A $-less function returns a Variant that contains the string result,
which means in most cases the Variant
must be reconverted to a string before it can be reused in expressions or
assigned to a String variable. This is a time-consuming process that gives
you nothing in return. Informal benchmarks show that the Left$ function is
up to twice as fast as its $-less counterpart. A similar reasoning
applies to other functions that exist in both forms, including LCase, UCase, LTrim, RTrim, Trim, Chr, Format, Space, Dir, and String.
- Using
End alone is a poor way to close an
application. It does not always
clean all of your code out of memory when your application closes. You
should always clean up after yourself.
In the Form’s unload event you should always set the FormName = Nothing, thus correctly unloading
form and freeing the resources it consumes. This is a big issue. When a
form is unloaded its resources remain in memory. For example, you can
still access procedures from a form that has been unloaded. You can test
this by setting a local Form variable to something, unload the Form, then
reload the Form and you will see the variable is still set.
- Never
Dim anything As
New if you're concerned about
speed. VB6 will treat such a variable as an auto-instantiated variable.
Every time you use it, VB will check if it should be instantiated. This
will cost you some extra CPU cycles.
- When
you are done with a Class you should set it to nothing to free memory (Set clsGradient = Nothing). Also, the Erase
command should be used to clear publicly declared arrays. As a general rule-of-thumb, if you Set
it then always Set it equal to Nothing when you are finished.
- The Move method should always be preferred to
individual property assignment for at least two reasons; this operation is
two to three times faster than four distinct assignments, and if you were
modifying the Width and Height
properties of a form, each individual property assignments would fire a
separate Form_Resize event, thus adding a lot of overhead to your code.
- If
you are going to use a function but don’t need the return variable, then
don’t use one. For example, instead of lngR =
SetWindowPos(?,?,?) use Call
SetWindowPos(?,?,?).
Using the Call command before
Subs or Functions (where you don’t need the returned value) will make your
code easer to read.
- Don’t create a
Function when a Sub will do. It
just adds memory overhead with no benefit.
- If
you are passing a variable to a Sub or Function that you do not intend to
pass back the change, then use the ByVal
prefix to pass it’s value only.
This will prevent the variable's actual value from being
inadvertently changed. If you’re a
purest and don’t want to leave anything to chance then use default ByRef in all other cases. Note of caution: Visual
Basic may rearrange arithmetic expressions to increase internal
efficiency. Avoid using a Function procedure in an arithmetic expression
when the function changes the value of variables in the same expression.
- Include error handling
in every procedure of your application regardless of its size or
purpose. Use On Error GoTo to trap unexpected
errors and On Error Resume Next to
trap expected errors. Give
procedures a single exit point (there should only be one Exit Sub/Function). See the
included utility for automatically inserting error handling into your
existing projects.
- Do not declare a
module level variable and a procedure level variable with the same name
(within the same module). Although
this is allowed, it makes for very confusing code.
- Never
permanently jump out of a structure like For/Next or Do/Loop.
Always return to the structure and then exit using Exit For or Exit
Do before completion.
This will prevent Stack Overflow errors and memory leaks. Also, do not end your application
inside a structure for the same reasons.
- Use
Do/Loop
instead of the older While/Wend command. Do/Loop has 'While', 'Until' and' Exit' methods
which make it clearer and easier to code.
- Limit
the use of DoEvents; anytime you
pass control to the operating system your code stops running and could
cause unpredictable results. In addition, do not use DoEvents if other applications could possibly
interact with your procedure in unforeseen ways during the time you have
yielded control.
- Indent,
add spaces between lines of code (where appropriate) and add comments before
sections of code when necessary. This will make your code easer to read and
may help you figure out what you were trying to do when you are looking at
it in the future. The standard
number of characters per tab stop is 3 (as directed by Microsoft) although
VB defaults to 4. Using anything less than 3 characters reduces the visual
definition and anything more wastes too much space, especially in
complicated code. Insert a blank
line before and after each If...Then,
Select Case, For, Do and While
loop constructs. Insert a blank line after declaring a block of variables
and between groups of statements that perform unified tasks. See the
included utility for automatically formatting your code.
- Use the default property of an object. For example, when setting a Text Box’s
value, txtTextBox.Text = “Sample”
is better then txtTextBox = “Sample”. This will make your code easer to
read. It is clearer if you don’t
depend on the default property of a control.
- Use VB’s built-in system constants when ever
possible. For example use vbNullString instead of “”, vbTab
instead of Chr$(9), and MsgBox "My
Message", vbYesNo
instead of MsgBox "My Message", 4
just to mention a few.
- Hard-Coded Paths are generally unwise, use the
SpecialFolders API to find standard Window folders like Program Files,
DeskTop, or Windows System folders.
If your application needs a data folder, make sure it exists first
and if not then create it; also don’t forget to use App.Path when looking for a file in the
application’s folder or sub-folders (App.Path & "\FileName" and not just "\FileName"). See the
included clsSysDirs.cls Class for help in getting Special System Folders.
- If each of the
comparisons contain a common member, then in most cases the Select Case construct is a better choice
over ElseIf. The Select
Case structure is easier to read and therefore less prone to
errors. The one exception is when
using the TypeOf condition, which does not work with Select Case
statements.
- Don’t keep the default
names for the controls you use, like Command1, List1, Combo1, etc., but
give them meaningful names. It may
take you more time up front but will save you time in the future. The only exceptions to this are any
labels used only as static prompts on the surface of a form. If a label is
referenced anywhere in code, even once, then it must be given a meaningful
name along with the other controls.
- Always provide
feedback to the user, especially for any lengthy process. This will give your application a more
professional look as well giving the user some indication that your
application is still running.
- Use the continuation
character ( _ ) to break long lines.
A 90-character line is the recommended length (because it works
best when printed), but I don’t know anyone who actually counts
characters.
- Some good resources
for coding standards and naming conventions: http://www.gui.com.au/html/coding_standards.htm
http://support.microsoft.com/kb/q173738/
By:
Morgan Haueisen
PanetSourceCode.com
E-Mail
A
Side Note on Copyright confusion:
Just
for the record, all code submitted to PSC code is copyrighted. If you use someone else’s unmodified code
(modified does not mean variable name changes, bug fixes or other minor
changes) in your application, even if the author did not put his/her name in
the code, you are still required to give them credit for the work they have
done. If the author did not give
specific limitations or instructions, then just include their name in the
declaration section of the code they wrote.
Redistribution of the code, whole or in part, as source code or in
binary form, alone or as part of a larger distribution or product, is forbidden
for any commercial or for-profit use without the author's explicit written
permission.
Appendix: Below is a list of
the naming conventions recommended by Microsoft.
|
Prefixes for Variable Data Types:
|
|
Prefixes for Variable Scope:
|
Data Type
|
Prefix
|
|
Scope
|
Prefix
|
|
Array
(used with the following)
|
a
|
|
Global
|
g
|
|
Byte
|
byt
|
|
Module/Form
|
m
|
|
Boolean
|
bln
|
|
Static
|
s
|
|
Currency
|
cur
|
|
Procedure
|
(no prefix)
|
|
Date/Time
|
dtm
|
|
|
|
|
Double
|
dbl
|
|
Prefixes for Arguments
|
|
Long
|
lng
|
|
Item
|
Prefix
|
|
Integer
|
int
|
|
ByRef
|
r
|
|
Single
|
sng
|
|
ByVal
|
v
|
|
String
|
str
|
|
Enum
|
enu
|
|
Variant
|
vnt
|
|
User-defined
type
|
udt
|
|
|
|
|
|
|
|
Prefixes for Common Controls:
|
|
Control
|
Prefix
|
|
Control
|
Prefix
|
|
Check
box
|
chk
|
|
List
box
|
lst
|
|
Class
|
c
|
|
List
view
|
lvw
|
|
Class
object (instantiated)
|
cls
|
|
MAPI
message
|
mpm
|
|
Combo
box
|
cbo
|
|
MAPI
session
|
mps
|
|
Command
button
|
cmd
|
|
MDI
child form
|
mdi
|
|
Common
dialog
|
dlg
|
|
Menu
|
mnu
|
|
Communications
|
com
|
|
Module
|
mod
|
|
Data
control
|
dat
|
|
OLE
container
|
ole
|
|
Dictionary
|
dic
|
|
Option
button
|
opt
|
|
Directory
list box
|
dir
|
|
Outline
|
out
|
|
Drive
list box
|
drv
|
|
Panel
|
pnl
|
|
File
list box
|
fil
|
|
Picture
box
|
pic
|
|
Form
|
frm
|
|
Picture
clip
|
clp
|
|
Frame
|
fra
|
|
Report
|
rpt
|
|
Graph
|
gra
|
|
Shape
|
shp
|
|
Grid
|
grd
|
|
Spin
|
spn
|
|
Group
push button
|
gpb
|
|
Status
bar
|
stb
|
|
Horizontal
scroll bar
|
hsb
|
|
Text
box
|
txt
|
|
Image
|
img
|
|
Timer
|
tmr
|
|
Label
|
lbl
|
|
Tree
view
|
tvw
|
|
Line
|
lin
|
|
Vertical
scroll bar
|
vsb
|
|
|
|
|
|
|
Prefixes for Database Objects:
|
|
|
|
|
Object
|
Prefix
|
|
Microsoft
recommends naming Constants with the C_ prefix as in C_MaximumValue.
|
|
Database
|
db
|
|
|
Field
|
fld
|
|
|
Index
|
idx
|
|
|
Query/QueryDef
|
qry
|
|
|
Recordset
|
rst
|
|
|
Table/TableDef
|
tbl
|
|
|
|
|
|
|
|
|
|
|
|