Naming Conventions: An Overview
In our Access naming style, an object name is made up of four
parts: one or more prefixes, a tag, a base name, and a qualifier.
The four parts are assembled as follows:
[prefixes]tag[Basename][Qualifier]
Note The brackets
denote that these components are optional and aren't part of the
name.
The tag is the only required component, but in almost all cases
the name will have the base name component because you need to
be able to distinguish two objects of the same type. (Having the
tag as the only required part may seem counterintuitive, but in
Access Basic you can have code that deals with a generic form
passed as a parameter. In this case you'd use "frm" as the parameter
name; the base name isn't required except to distinguish it from
a different form object variable in the code.). Here are a few
examples:
Name |
Prefix |
Tag |
Base |
Qualifier |
tblCustomer |
|
tbl |
Customer |
|
aintPartNum |
a |
int |
PartNum |
|
strCustNamePrev |
|
str |
CustName |
Prev |
Prefixes and tags are always lowercase so your eye goes past
them to the first uppercase letter where the base name begins.
This makes the names more readable. The base and qualifier components
begin with an uppercase letter.
The base name succinctly describes the object, not its
class. This is the name you'd likely give the object if
you weren't using any particular naming style. For example, in
the query name qryPartNum, "PartNum" is the base name;
it's an abbreviation for Part Number. Object tags are short and
mnemonic. Object prefixes precede some object names and tags and
provide further information. For example, if an integer variable
intPartNum is an array of part numbers, the prefix "a"
for array is added to the front, as in aintPartNum(). Further,
a variable that provides an index into the array would use the
name of the array prefixed with the index prefix "i", for example,
iaintPartNum.
Applying a naming style like this requires more effort up front,
but try to imagine which of these two code samples will make more
sense to you a year from now when you attemptto modify or reuse
your code:
Z = Y(X)
or
intPart = aintPartNum(iaintPartNum)
Object qualifiers may follow a name and further clarify names
that are similar. Continuing with our parts index example, if
you kept two indexes to the array, one for the first item and
one for the last, the variable iaintPartNum above would
become two qualified variables—iaintPartNumFirst
and iaintPartNumLast.
Naming Database Objects
Database objects (tables, queries, forms, reports, macros, and
modules) are the most frequently referenced items in an Access
application. They appear in your macro code, in your Access Basic
routines, and in properties. Thus, it's important that you standardize
how you name them.
Microsoft's examples in the Northwind Database and Access manuals
allow for spaces in object names, but we don't use them in our
style. In most database engines and programming languages, including
Access Basic, a space is a delimiter character between items,
it isn't a logical part of an item's name. Also, spaces in field
names don't work in most other database platforms or Microsoft
Windows®-based applications such as Microsoft SQL Server™
or Word for Windows. Instead, use upper and lowercase designations
in names, such as tblAccountsPayable. If spacing is still
necessary, use the underscore (_) character instead of a space
to be consistent with traditionally accepted SQL syntax and with
Access 2.x function naming conventions.
Tags for Database Container Objects
All database container object names in our style have tags. Adding
tags to these objects may make them less readable to nondevelopers,
but new users will understand their value when they're trying
to discern a table from a query in the listbox for a New Report
wizard or a form's Control Source property. This is because Access
merges table and query names into one long list. Here are Level
1 database container object name tags:
Object |
Tag |
Example |
Table |
tbl |
tblCustomer |
Query |
qry |
qryOverAchiever |
Form |
frm |
frmCustomer |
Report |
rpt |
rptInsuranceValue |
Macro |
mcr |
mcrUpdateInventory |
Module |
bas |
basBilling |
At Level 1, the only name qualifier (appended to the name) that
we use for database container objects is Sub, which we place at
the end of a form or report name for a subform or subreport. The
form frmProductSupplier would have the related subform frmProductSupplierSub.
This allows objects and their subform or subreport to sort next
to each other in the database container.
Level 2 tags, shown here, provide more descriptive information.
Object |
Tag |
Example |
Table |
tbl |
tblCustomer |
Table (lookup) |
tlkp |
tlkpShipper |
Query (select) |
qry (or qsel) |
qryOverAchiever |
Query (append) |
qapp |
qappNewProduct |
Query (crosstab) |
qxtb |
qxtbRegionSales |
Query (data definition) |
qddl |
qddlAddWorkColumn |
Query (delete) |
qdel |
qdelOldAccount |
Query (form filter) |
qflt |
qfltSalesToday |
Query (lookup) |
qlkp |
qlkpStatus |
Query (make table) |
qmak |
qmakShipTo |
Query (pass-through) |
qspt |
qsptArchiveQuantity |
Query (union) |
quni |
quniOrderDetail |
Query (update) |
qupd |
qupdDiscount |
Form |
frm |
frmCustomer |
Form (dialog) |
fdlg |
fdlgLogin |
Form (menu) |
fmnu |
fmnuUtility |
Form (message) |
fmsg |
fmsgWait |
Form (subform) |
fsub |
fsubOrder |
Report |
rpt |
rptInsuranceValue |
Report (subreport) |
rsub |
rsubOrder |
Macro |
mcr |
mcrUpdateInventory |
Macro (for form) |
m[formname] |
mfrmCustomer |
Macro (menu) |
mmnu |
mmnuEntryFormFile |
Macro (for report) |
m[rptname] |
mrptInsuranceValue |
Module |
bas |
basBilling |
Using our Level 2 style causes objects with similar functions
to sort together in the database container in large applications.
Imagine that you have a database container with 100 forms in it
(we do!), 30 of which are messages that display during the application.
Your users now want all message forms to have red text instead
of black, so you must change each of the 30 forms. Having the
message forms sort together in the database container (because
they've all got the same tag) saves you significant effort trying
to discern which forms you need to change.
Choose your table names carefully. Since changes to the names
of Access objects do not propagate through the database, it is
important to name things correctly when the object is created.
For example, changing the name of a table late in the development
cycle requires changing all the queries, forms, reports, macros,
and modules that refer to that table.
You may want to name each database object that refers to a table
with the same base name as the table, using the appropriate tag
to differentiate them. For example, if your table is tblCustomer,
its primary form would be frmCustomer, its primary report would
be rptCustomer, and the macros that drive all of the events would
be mfrmCustomer and mrptCustomer. We also suggest that you not
make table names plural (for example, use tblCustomer, not tblCustomers),
because a table usually holds more than one record, so it's plural
by implication.
Database Object Prefixes
We use four database object prefixes:
- "zz" denotes objects you've deserted but may want to keep
in the database for awhile for future reference or use (for
example, zzfrmPhoneList). "zz" causes the object name to sort
to the bottom of the database container, where it's available
but out of the way.
- "zt" denotes temporary objects (for example, ztqryTest).
- "zs" denotes system objects (for example, zstblObjects). System
objects are items that are part of the development and maintenance
of an application not used by end users, such as error logs,
development notes, documentation routines, relationship information,
and so on. (Note that "zs" is a prefix. It causes the system
objects to sort toward the bottom of the database container).
- "_" denotes objects under development (for example, _mcrNewEmployee).
An underscore before an object name sorts to the top of the
database container to visually remind you that it needs attention.
Remove the underscore when the object is ready to use and it
will sort normally.
Tags for Fields
Using tags in field names is a hotly debated issue, even between
the authors of this article. Greg maintains that tags in field
names uniformly apply the naming style across all database elements
and further document your work in Access Basic routines and form
or report properties. Stan prefers that the database schema remain
pure (platform- and data type-independent) for migration and connectivity
to other products or platforms. He prefers that a field name remain
independent of its data type.
Consider both positions, along with your unique needs, when you
choose whether to apply the field name tags shown here:
Field Type |
Tag |
Example |
Binary |
bin |
binInternal |
Byte |
byt |
bytFloorNum |
Counter |
lng |
lngPKCnt |
Currency |
cur |
curSalary |
Date/Time |
dtm |
dtmHireDate |
Double |
dbl |
dblMass |
Integer |
int (C programmers may prefer "w") |
intUnit |
Long |
lng (C programmers may prefer "dw") |
lngPopulation |
Memo |
mem |
memComments |
Ole |
ole |
oleEmpPhoto |
Single |
sng (Some users find "sgl" more
mnemonic ) |
sngScore |
Text |
str (Used as opposed to "txt" because
a textbox control uses "txt". C programmers may prefer "sz") |
strFirstName |
Yes/No |
ysn (C programmers may prefer "f") |
ysnDiscounted |
Notes:
- The Access engine ("Jet") supports a data type called binary
but the Access user interface doesn't expose it to the user.
It's still possible to get a field with the binary data type
by importing or attaching certain external tables. Also, some
of the system table fields use this data type.
- Internally, Access treats a counter data type as a long integer
with a special property called auto-increment. Because counter
fields are often referenced by foreign keys and the data type
in the other table is a long, Greg uses the same tag as a long.
Optionally, if you want to distinguish a counter from a long,
use the qualifier Cnt at the end of the name.
Tags for Control Objects
Access forms and reports automatically assign the field name
to the Control Name property when you create a new bound control.
Having the control name and field name the same creates some ambiguity
in the database schema and in some cases may cause errors in Access
Basic code referencing both a control and a field with the same
name. To resolve this situation, apply the naming style to form
and report controls by inserting the appropriate tag from the
list below, in front of the control name suggested by Access.
For example, the control name for a field whose Control Source
is LastName would be txtLastName.
At Level 1, we recognize that users need to know the difference
between an active control and a label, but may not be concerned
with the type of the control. Thus the control tags are as follows:
Object |
Tag |
Example |
Label |
lbl |
lblLastName |
Other types |
ctl |
ctlLastName |
Level 1 tags provide the minimum differentiation necessary to
still prove useful in functions, macros, and program documentation.
For example, the control tags above allow you to differentiate
between labels, which aren't modifiable at runtime, and other
controls, which accept values from code and users.
Level 2 control tags denote the specific type of the control
on the form or report (see table below). This makes Access Basic
code and macros more explicit with respect to the properties and
events of the individual control.
Object |
Tag |
Example |
Chart (graph) |
cht |
chtSales |
Check box |
chk |
chkReadOnly |
Combo box |
cbo |
cboIndustry |
Command button |
cmd |
cmdCancel |
Frame (object) |
fra |
fraPhoto |
Label |
lbl |
lblHelpMessage |
Line |
lin |
linVertical |
List box |
lst |
lstPolicyCode |
Option button |
opt |
optFrench |
Option group |
grp |
grpLanguage |
Page break |
brk |
brkPage1 |
Rectangle (Visual Basic uses the
term "shape") |
shp |
shpNamePanel |
Subform/report |
sub |
subContact |
Text box |
txt |
txtLoginName |
Toggle button |
tgl |
tglForm |
The only prefix for controls, "zs", appears at Level 2. It denotes
system-level controls used by the form or code but not displayed
to the user. Such controls usually aren't visible at run time
but they may store temporary values or parameters passed to the
form.
Naming Access Basic and Macro Objects
Using standardized and descriptive variable, constant, and function
names greatly enhances the ability of developers to share, maintain,
and jointly develop code.
Procedures and Macros
Access Basic requires that each nonprivate procedure name in
a database be unique. For a function called from a property on
a form in Access 1.x, construct the function name as follows:
formname_controlname_propertyname
For example:
frmEmployee_cmdAdd_Push
This tells you that this function is called from the OnPush property
of the control cmdAdd on the form frmEmployee. For a property
that affects the entire form, just use formname_propertyname,
as in frmEmployee_Open. If two or more controls on one form execute
the same code, create unique functions for each using the naming
style in this section, then have each of these functions call
the same private function that contains the common code.
In Access 2.x, the code for controls on a form is stored attached
to the form, so the form name is implied in the function and does
not need to be in the function name. Thus, the example above becomes:
cmdAdd_Click
Macro names inside a macro group also use this format. In the
macro group mfrmEmployee, the macro txtName_BeforeUpdate contains
the actions for the txtName control's BeforeUpdate event. For
example, the txtName control on your frmEmployee form would have
one of these properties, depending on whether you use modules
(Access 1.x), attached code (Access 2.x), or macros to implement
the task:
1.x code:BeforeUpdate....=frmEmployee_txtName_BeforeUpdate()
2.x code:BeforeUpdate....=txtName_BeforeUpdate()
Macros:BeforeUpdate...mfrmEmployee.txtName_BeforeUpdate
You should prefix procedure names in library databases with a
unique set of characters to prevent their names from conflicting
with any other names from attached libraries. The prefix should
be in uppercase letters, followed by an underscore, and be no
more than four letters. For example, we prefix all the library
function names for our mail-merge utility, Access To Word, with
"ATW_". Global constants and variables in a library should use
the same prefix because they must also be unique across the entire
database name space. Similarly, it is important to use these prefixes
in Declare statements to alias all external dynamic-link library
(DLL) function and procedure calls.
Tags for Access Basic Variables
Every Access Basic variable should have a type tag from the following
list:
Variable Type |
Tag |
Example |
Container |
con |
Dim conTables as Container |
Control |
ctl |
Dim ctlVapor As Control |
Currency |
cur |
Dim curSalary As Currency |
Database |
db |
Dim dbCurrent As Database |
Document |
doc |
Dim docRelationships as Document |
Double |
dbl |
Dim dblPi As Double |
Dynaset |
dyn |
Dim dynTransact As Dynaset |
Flag (Y/N, T/F) |
f |
Dim fAbort As Integer |
Field |
fld |
Dim fldLastName as Field |
Form |
frm |
Dim frmGetUser As Form |
Group |
gru |
Dim gruManagers as Group |
Index |
idx |
Dim idxOrderId as Index |
Integer |
int |
Dim intRetValue As Integer |
Long |
lng |
Dim lngParam As Long |
Object |
obj |
Dim objGraph As Object |
Parameter |
prm |
Dim prmBeginDate as Parameter |
Property |
prp |
Dim prpUserDefined as Property |
QueryDef |
qdf (or qrd) |
Dim qdfPrice As QueryDef |
Recordset |
rec (or rst) |
Dim recPeople as Recordset |
Relation |
rel |
Dim relOrderItems as Relation |
Report |
rpt |
Dim rptYTDSales As Report |
Single |
sng |
Dim sngLoadFactor As Single |
Snapshot |
snp |
Dim snpParts As Snapshot |
String |
str |
Dim strUserName As String |
Table |
tbl |
Dim tblVendor As Table |
TableDef |
tdf (or tbd) |
Dim tdfBooking as TableDef |
Type (user-defined) |
typ |
Dim typPartRecord As mtPART_RECORD |
User |
usr |
Dim usrJoe as User |
Variant |
var |
Dim varInput As Variant |
Workspace |
wrk (or wsp) |
Dim wrkPrimary as Workspace |
Yes/No18 |
ysn |
Dim ysnPaid As Integer |
Our style doesn't use data-type suffixes such as $ and % on variable
names, because the Access and Visual Basic documentation recommends
against using these suffixes.
Tags for database object variables such as the Form and Report
types are the same as those used for the objects. This helps when
coding, because the variable you assign an object to (for example,
tblVendor) usually has the same name as the object it references
(tblVendor), providing you with consistent object names when coding.
Constants and User-Defined Types
It is common practice in programming for Windows to use uppercase
names for constants, but the authors differ on how to treat constants.
Stan prefers using the uppercase notation and adding a scope prefix
(see below), so a global constant for a specific error might be
gNO_TABLE_ERROR. Greg prefers to treat constants as typed variables
without scope, for example, strNoTableError.
In the above table, we've added a variable type tag of "typ"
for user-defined types, and suggest a convention that matches
that of constants, because you can think of both user-defined
types and user-defined constants as persistent, user-created objects.
The recommendations for a user-defined data type syntax include
the following:
- Use uppercase letters (or upper/lower syntax if you use that
optional convention for globals).
- Use a tag of "t" in front of the type name to denote that
it's a type structure.
- Use "g" and "m" prefixes to denote the scope of the type (see
below).
Prefixes for Scope
Level 2 of the naming convention introduces scope prefixes for
variables and constants. The scope prefix comes before any other
prefixes.
- Variables declared locally with a Dim statement have no prefix.
- Variables declared locally with a Static statement are prefixed
with an "s", as in "sintAccumulate".
- Variables that are declared in the Declarations section of
a module (or form in Visual Basic) using a Dim statement are
prefixed with an "m", as in "mcurRunningSum".
- Variables declared with global scope using a Global statement
in the Declarations section have the prefix "g", as in "glngGrandTotal".
- Variables that denote parameters passed to a function (in
the parentheses after the function name) have a prefix of "p",
as in "pstrLastName". Alternately, we sometimes use "r" instead
of "p" for values passed to a function by reference, and "v"
for values passed ByVal, when both types of parameters are used
in a single function declaration.
Object qualifiers follow the variable name and further differentiate
it from similar names. You'll probably devise a list of qualifiers
relevant to the types of applications you develop, but here are
some of our common ones:
Variable Property |
Qualifier |
Example |
Current element of set |
Cur |
iaintCur |
First element of set |
First |
iaintStockFirst |
Last element of set |
Last |
iaintStockLast |
Next element of set |
Next |
strCustomerNext |
Previous element of set |
Prev |
strCustomerPrev |
Lower limit of range |
Min |
iastrNameMin |
Upper limit of range |
Max |
iastrNameMax |
Source |
Src |
lngBufferSrc |
Destination |
Dest |
lngBufferDest |