NAMING CONVENTIONS AND STYLE GUIDELINES
Copyright (c) 1994 Chris St. Valentine All Rights Reserved

Whether you are a professional programmer or just getting started with 
database development, good programming practice requires a consistent, 
maintainable, and readable coding style. Months or even years from now, you 
will want to be able to look back at the objects and code you create today 
and understand them immediately, without having to spend extra time 
deciphering your work.

It is even more important to adopt a consistent style if you work in an 
environment where more than one person contributes to an application. If all 
developers write with the same guidelines in mind, it is easier to 
incorporate code, share work, and improve the efficiency of your 
applications.

This chapter explores a number of naming and style issues; in adopting these 
guidelines, you should keep in mind that you may not always be the only one 
who has to work with your applications. While some users will be experienced, 
professional developers, perhaps fluent in one or more programming languages, 
most users are not so experienced and may look to your applications as 
examples of good design.

This chapter covers the following areas:

     o Naming Database Objects and Controls
     o Laying Out Modules--What Goes Where
     o Designing a Function Procedure
     o Adding Comments and Documenting Your Work
     o Choosing Between Modules and Macros
     o Exploring Miscellaneous Issues

Naming Database Objects and Controls

  Implementing a consistent database object naming convention makes it 
  easier for users to find and identify objects and you and other developers 
  to write and decipher code. This section outlines a number of techniques 
  that you should adopt as you develop your own applications and applications 
  you distribute to others.

  This section is based largely on the CSV conventions widely circulated 
  among Access developers. What follows is the result of many years of 
  research, usability testing, and sometimes heated debate among BASIC and 
  Access programmers both inside and outside the walls of Microsoft.

  Tables and Queries

    Table names should be descriptive, yet relatively short (see figure 
    20.1). They should be I-capped, which means each word begins with a 
    capital letter, but without underscores (_) or  spaces. Underscores are 
    difficult for most people to locate on the keyboard, and names with 
    underscores or all uppercase letters are more difficult to read.

    Figure 20.1 - Name your tables and queries so that they appear together 
    in drop-down lists.

    One exception to using underscores relates to temporary objects. For 
    more information, see "Temporary, Unfinished, and To-Be-Deleted Objects" 
    later in this section.

    Most other software platforms do not allow spaces in table names. If you 
    someday decide to move your tables to such a platform (for example, the 
    SQL Server), you have to rename your tables, plus change any forms, 
    reports, queries, macros, and modules that refer to those tables. Because 
    Access does not support the concept of a data dictionary and has no 
    global search and replace, this results in a significant amount of work 
    on your part.

    Depending on your application, table names should be plural: Agencies, 
    Agents, Cities (and not Agency, Agent, or City), and so on (see figure 
    20.2).

    Figure 20.2 - Try to use plurals for your table names.

    For tables that merge data from more than one table (an intersection 
    table designed to create a many-to-many relationship), choose a name that 
    is descriptive and, where appropriate, includes the names of both or all 
    tables. For example, a table that combines values from a Students table 
    and a Classes table could be named StudentsClasses (see figure 20.3).

    Figure 20.3 - StudentsClasses is an intersection table.

    You can often base the name of a query on the names of the source tables 
    for the query. For example, Agencies by Name Qry identifies a query based 
    on the Agencies table. Similarly, Listings by MLS Qry identifies a query 
    based on the Listings table, and so on. If you adopt this strategy, when 
    you list the queries in the Database window, all queries based on any 
    particular table will appear together. In lists that combine table and 
    query names (for example, the RecordSource drop-down list in a form's 
    Design view), you will see the table and all its queries listed together 
    alphabetically (see figure 20.4).

    Figure 20.4 - All of the agent-related queries appear together.

    As with tables, query names should be descriptive yet brief. Remember 
    that you cannot scroll the Database window (and certain other lists) 
    horizontally, so to view all of an exceptionally long name you must 
    enlarge the window (see figure 20.5).

    Figure 20.5 - Try to avoid particularly long object names.

      Differentiating Between Tables and Queries

	Tables and queries share the same name space--you cannot have a table 
	and a query with the same name. Because tables and queries appear in 
	the same lists several places in the user interface, it is sometimes 
	important to be able to tell the difference between tables and 
	queries. To differentiate between tables and queries, add a suffix, 
	Qry, to the names of queries. For example, Sales for 1991 Qry and 
	Customers by Name Qry.

	You may be accustomed to prefixing table names with "tbl" and queries
	with "qry", or some other prefix. However, queries are already 
	identified with a suffix and therefore there is no need to uniquely 
	identify tables with either a prefix or suffix. It is the absence of 
	a suffix that identifies a given object (in a list of tables and 
	queries) as a table.

	It is not particularly important for you to achieve consistency in 
	using suffixes among all of your object names. What is important is 
	only the need to differentiate tables and queries. Adding suffixes to
	other objects is largely unnecessary and adds nothing to the 
	readability or utility of these other names.

      Table Fields

	As with table names, field names should be descriptive, yet 
	relatively short. The names should be I-capped, using upper- and 
	lowercase letters but no underscores or spaces (remember, most other 
	software platforms do not allow spaces in either table or field 
	names). Avoid unnecessary abbreviations, but do not make them so long
	that they become tedious to type.

	Most fields can be described with a single word. Avoid naming fields 
	with concatenated words that include the name of the table as well as
	the particular field. For example, in a table named Shippers, you can
	name fields Name, State, and so on. Because the name of the table 
	already identifies that you are working with shippers, the field 
	names do not need to be ShipperName, ShipperState, and so on. 
	Wherever the name of the field might otherwise appear in Access, the 
	name of the table also appears.

	Avoid special characters in field names; use only letters (a-z, A-Z) 
	and perhaps numbers (0-9). Specifically, do not use number signs (#),
	dashes (-), or ampersands (&). In certain contexts, the presence of 
	these special characters in a field name can be ambiguous or 
	confusing. For example, you use the number sign to delimit date/time 
	values and the ampersand to perform string concatenation.

	Figure 20.6 - Avoid special characters when you define your field 
	names.

  Controls

    Unless you create a control by dragging and dropping a field name from 
    the Field List, the default control name assigned by Microsoft Access 
    looks something like Text12, Field5, and so on. You should rename all 
    controls to something more meaningful, such as State or Birthdate. To 
    understand the value of giving your controls "real" names, consider the 
    following expressions.

      If Not csvSomethingIn(Forms![Customers]![Field5]) Then...
      If Not csvSomethingIn(Forms![Customers]![ZIP]) Then...

    Clearly, an expression that refers to ZIP is easier to work with than 
    one that refers to Field5. Further, you should rename labels, even if you
    do not think you will ever refer to them in code or in expressions. If 
    you later decide to document (see figure 20.7) your application by 
    listing all of the controls on your forms, you will want to avoid lists 
    with meaningless names.

    Figure 20.7 - Use the Database Documenter to create documentation for 
    your tables.

    Control names should be I-capped, using upper- and lowercase letters, but
    no underscores; avoid any special characters such as numbers signs, 
    dashes, and ampersands. For example, a control that refers to a 
    customer's company name might be named, appropriately enough, 
    CompanyName.

    In contrast, you should avoid naming the control CoNam because that name
    is unnecessarily cryptic.

    Even though you may be accustomed to adding prefixes, or tags, to control
    names to identify the control type, you should avoid such tags (except 
    for label controls, discussed later in this section). For example, you 
    might have created a text box named txtState or a combo box named 
    cboShippers. The txt and cbo identify the control type as a text box or 
    combo box, but in most contexts the control type is either unimportant or
    is apparent from its name or usage.

    On occasion, you may even want to change the type of a control. For 
    example, you may design a form that uses a text box to enter the state in
    a customer's address. If you name the control txtState and later decide 
    you would rather use a combo box, you will either have to name the combo
    box txtState (which conflicts with the prefix naming scheme) or somehow 
    locate and change every occurrence of the name throughout your 
    application to reflect the new control name (but remember, there is no 
    global search and replace mechanism).

    Even though Access allows you to insert spaces in control names, you 
    should avoid using spaces. Always use brackets when you refer to controls
    and other user-defined names, even though they do not contain spaces:

      Code Example                    Satisfactory Comments
      ------------------------------- ------------ --------------------------
      Forms![Customers]![CompanyName] Yes
      Forms!Customers![Company Name]  No           Missing brackets; contains
						   space
      Forms![Customers]![State]       Yes
      Forms!Customers!State           No           Missing brackets

    Although Forms!Customers!State is an otherwise valid reference to a 
    control named State (Access requires brackets only when there are 
    spaces), the preferred syntax is nonetheless Forms![Customers]![State].

    Bound controls (that is, controls that have a ControlSource property 
    setting) should be named the same as the fields to which they are bound, 
    except in those cases where a naming conflict arises in a calculated 
    control. In these cases, rename the control. For example, you might 
    create a text box named City that is actually the concatenation of a 
    record's city, state, and ZIP code. The control source for the text box 
    might look something like this:

      =[City] & ", " & [State] & " " & [ZIPCode]

    Naming the control City will not work because it creates a circular 
    reference: the control is based, in part, on itself. Access cannot 
    resolve the name City, so you have to change the name of the control to 
    something else (perhaps CityEtc).

    Generally, label controls should be named the same as their captions with
    a suffix, Lbl (an abbreviation for label). For example, you might create 
    a label with the caption Company Name. Its control name would be 
    CompanyNameLbl (notice the absence of spaces). You would not name the 
    label CompanyName because that would likely conflict with a text box with
    the same name, the very text box to which the label refers.

  Forms and Reports

    Name your forms and reports with descriptive names using upper- and 
    lowercase letters. In contrast with tables, fields, and controls, 
    however, form and report names should include spaces between words. In 
    particular, report names frequently appear in the user interface in your 
    applications (see figure 20.8) and thus having readable names is a 
    much-desired convenience. Because forms and reports cannot be used 
    outside the Access environment, the usual restriction against using 
    spaces does not apply.

    Figure 20.8 - You can create a form that lists only report objects.

    Try not to make your names so long that they do not fit in the Database 
    window. Most form names can be single words (Agencies, Houses, and so on)
    that adequately describe the form's purpose. Since most forms deal with 
    multiple records, most form names are plural, not singular. For example, 
    you would not name a form Agency or House.

    Reports typically represent a subset of table information and thus 
    warrant more descriptive names than do tables or forms (see figure 20.9).
    For example, avoid naming a report Agencies when Agencies by Name more 
    clearly identifies the report. Name a report according to the data it 
    represents and, where appropriate, its layout. For example, a report 
    named Sales Report, although accurate, is not nearly so good as Sales 
    Report by Sales Rep.

    Figure 20.9 - Create reports with meaningful names: not too short, not 
    too long.

    Name your subforms and subreports, when they are not also used as 
    stand-alone forms and reports, the same as the main, or parent, form or 
    report with an additional suffix, Sub. For example, a form named 
    Customers might contain a subform named Customers Sub. In the Database 
    window, such forms are easily recognized as subforms by this suffix. In 
    the Northwind Traders sample database, the Orders form contains a subform
    named Order Details; although this is an otherwise valid form name, it 
    would be better named Orders Sub.

    Avoid prefixes in form and report names, since using a prefix prevents 
    similarly-named forms and reports from appearing together in lists. For 
    example, Customers and Customers Sub would appear together in the 
    Database window listing of forms. Naming the subform with a prefix (for 
    example, Sub Customers) would likely cause the subform to appear 
    elsewhere in the list of forms, away from the entry for Customers.

  Macros

    All except the AutoExec, AutoKeys, and custom menu macros should be in 
    macro groups, even if a given macro group contains only one macro.

    There are three kinds of macro groups: form- and report-specific macros, 
    menu bar macro groups, and general-purpose macros.

      Form- and Report-Specific Macro Groups

	Generally, create one macro group per form or report, and include all
	of the relevant macros in those groups. Name the macro group the same
	as the form or report using the same upper- and lowercase letters and
	spaces. For example, a form named Agencies would have its own macro 
	group named Agencies, Houses would have one named Houses, and so on.

	Within the macro group, name the individual macros according to 
	either the name of the control or event that triggers the macro, or a
	name that describes what the macro does.

	For example, you might create a form with a command button named 
	Close that calls a macro to close the form. The macro itself should 
	be named Close because that is the name of the control that calls the
	macro (it also happens to describe the action that the macro takes).

	Most macros, however, can be named even more descriptively. For 
	example, a form named Orders might need to update a TotalSales 
	control with a running total each time a product is added, a quantity
	changes, or a line price changes. Rather than call three separate 
	macros, you can create a single macro named Update Total. In this 
	example, Update Total is more descriptive than the name of any of the
	controls that might trigger the macro.

	The decision to use the names of the calling controls or more 
	descriptive names depends on your particular application and the 
	macros you call. In either case, be sure you document the macros by 
	adding a comment that explains or identifies the events that call the
	macro (see figure 20.10).

	Figure 20.10 - Add comments to document your macros.

      Menu Bar Macro Groups

	In addition to the single macro group for each form or report, adding
	custom menu bars requires additional, multiple macro groups. For 
	example, to add File, Edit, and Help menu commands to a custom menu 
	bar requires four menu groups (see figure 20.11).

	Figure 20.11 - Consistently named menu macro groups appear together 
	in the Database window.

	You should adopt a consistent naming convention for these menu macro 
	groups as you would any other macro group. The recommended naming 
	convention uniquely and concisely identifies menu macro groups and 
	their functions:

	  <form name> Menu <menu name>

	In the preceding example, the menu bar macro groups have been named 
	the same as the form, Customers, followed by the words Menu and the 
	name of the menu (Edit, File, and Help).

	The macro group names should be I-capped, using upper- and lowercase 
	letters, with spaces separating the words but no underscores. Menu b
	ar macro groups named in this fashion will appear in the Database 
	window following the form's primary macro group (in this example, 
	Customers).

      General-Purpose Macro Groups

	Depending on your application, you should create additional 
	general-purpose macro groups beyond those specifically designed for 
	your forms and reports. These general-purpose macro groups typically 
	contain macros called from multiple forms or, in some cases, from 
	Access Basic.

	Examples of general-purpose macro groups include the AutoExec and 
	AutoKeys macros. You might also create a macro group containing 
	record navigation macros, form closing macros, or other macros 
	called from multiple places.

	The names you choose for such general-purpose macro groups will 
	likely vary according to your application. Typical names include 
	Generic (when the macros are truly generic), String Manipulation (or 
	simply Strings), Mail, and so on (see figure 20.12). The names are 
	descriptive, but generally short enough to be viewed in the normal 
	Database window.

	Name the macro groups with upper- and lowercase letters and insert 
	spaces between words.

	Figure 20.12 - You may be able to call generic macros from multiple 
	forms.

  Modules

    For suggestions on how you can name your modules, see "Laying Out 
    Modules--What Goes Where", later in this chapter.

  Temporary, Unfinished, and To-Be-Deleted Objects

    Objects in the Database window and in a variety of drop-down list boxes 
    appear in alphabetical order. The following table illustrates how you can
    use this feature when you want to locate certain database objects that 
    represent work-in-progress, are created for some temporary purpose, or 
    are objects you intend to delete.

      Prefix          Example         Comments
      --------------  --------------  ---------------------------------------
      _ (underscore)  _Customers      Use an underscore to prefix 
				      work-in-progress or other incomplete 
				      objects that need additional changes 
				      before they can be fully implemented. 
				      This technique is most useful for 
				      modules because you do not refer to 
				      module names anywhere in Access and 
				      renaming a module will not break 
				      anything. Objects with a leading 
				      underscore appear first in the Database
				      window and in list boxes.
      zt              ztMonthlySales  Use zt to prefix temporary objects you 
				      create in code; for example, queries 
				      you create in Access Basic. The letters
				      zt cause the objects to sort to the end
				      of the Database window (except for 
				      objects beginning with zz, see below).
      zz              zzCustomers     Rather than deleting a database object,
				      consider renaming it with the zz 
				      prefix. That way, you have an 
				      opportunity to change your mind and 
				      recover the "deleted" object. Often, 
				      you will want to scavenge code, macros,
				      or controls from the object.

    Once your application is finished, review all the lists in the Database 
    window to make sure you have no underscore or zz database object names 
    (see figure 20.13).

    Figure 20.13 - Temporary and to-be-deleted objects appear at the end of 
    lists in the Database window.

Laying Out Modules--What Goes Where

  How you organize a module (and the individual function procedures within 
  them) can make it easier or harder to navigate through your code, 
  especially if you share code in a multiuser development environment.

  In a typical module, global variables and constants appear in the 
  Declarations section along with function (API) declarations. Once an 
  application has grown beyond just a few functions, however, a more 
  organized structure is required.

  For example, your application should have separate modules for global 
  constants, variables, function declarations, and user-defined type 
  declarations. The following table lists the minimum modules most 
  applications use.

    Module        Contains
    ------------  -----------------------------------------------------------
    Globals       Global constants and global variables
    Declarations  Function (API) declarations and user-defined type 
		  declarations
    Messages      Text for messages that appear in the user interface

  Depending on your particular application, you may have additional modules 
  dedicated to specific uses. For example, you might create a module named 
  Strings that contains routines for manipulating strings, another named 
  Validation that contains general-purpose validation routines, and yet 
  another named Forms and Controls that contains form- and control-related 
  functions. Not only does naming the modules according to the functions they
  contain make it easier to locate any particular functions, it also makes it
  easier to share code between applications since you can export an entire 
  module to another database and know that you are copying only relevant 
  functions.

  For modules that contain only form- or report-specific code, name the 
  module the same as the form or report. For example, a module that contains
  functions used only by an Orders form would itself be named Orders. This 
  technique follows the same strategy as creating a single macro group for 
  each form and naming it the same as the form.

    Designing a Function Procedure

      Within a function procedure, a consistent layout makes it easy to 
      locate specific elements of the module. The following example 
      illustrates a function designed with an easy-to-read format that 
      includes many of the elements you are likely to encounter in a 
      procedure.

      Function csvGetWindowsColors () As Integer

	  ' Purpose: Determines color settings set in the
	  '          Control Panel.
	  ' Accepts: (nothing)
	  ' Returns: True  - successful
	  '          False - unsuccessful
	  ' ---------------------------------------------------
	  Const COLOR_APPWORKSPACE = 12 ' Background.
	  Const COLOR_BACKGROUND = 1    ' Desktop background.
	  Const COLOR_WINDOW = 5        ' Window background.
	  Const COLOR_WINDOWTEXT = 8    ' Text in windows.
	  Dim AppWorkspace As Long, Background As Long
	  Dim Window As Long, WindowText As Long, X As Integer
	  
	  csvGetWindowsColors = True    ' Assume success.
	  ' Enable error handling.
	  On Error GoTo Err_GetWindowsColors
	  ' Get the various Windows color settings.
	  AppWorkspace = csvGetSysColor(COLOR_APPWORKSPACE)
	  Background = csvGetSysColor(COLOR_BACKGROUND)
	  Window = csvGetSysColor(COLOR_WINDOW)
	  WindowText = csvGetSysColor(COLOR_WINDOWTEXT)
	  ' Disable error handling.
	  On Error GoTo 0

	  ' Additional code that saves or uses the colors would go here.
	  
      Exit_GetWindowsColors:

	  On Error GoTo 0
	  Exit Function

      Err_GetWindowsColors:

	  X = csvDisplayMsg(CANTREADCOLORS, csvMB_ICONEXCLAMATION, "Colors")
	  csvGetWindowsColors = False   ' Function failed.
	  Resume Exit_GetWindowsColors

      End Function

  Order of Elements in a Function

    As a general rule, add elements to your own procedures in the following 
    order:

     o A "header" that describes the purpose of the procedure, the arguments
       it accepts (if any) and the procedure's possible return values. While
       the procedure is still in development (that is, before so-called code 
       complete), consider adding other notes that document the progress of 
       the procedure, remaining work left to be done, or perhaps notes about
       the revision level and the names of the developers.
     o Local constant declarations (Const statements)
     o Variable declarations (Dim statements)
     o Procedure initialization code (for example, setting counters to 0)
     o Remaining code (the bulk of the procedure)
     o Error-handling code (if any)

  Naming Functions

    Function names should be as long as necessary to convey meaning without 
    unnecessary abbreviations and, where possible, without requiring 
    comments. Conversely, however, try to avoid particularly long function 
    names that would otherwise require a lot of typing (for example, 
    GetDailyTasksByPriority).

    Avoid using underscores in function names; instead, use upper- and 
    lowercase letters:

      Satisfactory   Unsatisfactory
      -------------  ---------------
      GetWindowText  Get_Window_Text
      InitGlobals    INITGLOBALS
      FormIsLoaded   Loaded

    In general, name your functions according to their function or context. 
    For example, you might name a function GetWindowText because that is what
    it does--it gets the window text. Still, you might create another 
    function that calculates a shipping charge that might best be named 
    ShippingCharges, not CalculateShipping, even though that is what the 
    function does:

      SalesTotal = OrderAmount + CalculateShipping() ' Bad example.
      SalesTotal = OrderAmount + ShippingCharges()   ' Good example.

    In this second example, the name of the function is appropriate given its
    context. Name your functions according to how and where they will be used.

  Using and Avoiding Subprocedures

    Generally, create user-defined subprocedures only when you know (with 
    reasonable certainty) the procedures will never be needed outside of 
    Access Basic. Consider that you cannot call subprocedures from outside 
    Access Basic, but you can call function procedures from queries and 
    expressions on forms as record sources for controls, in reports, and from
    macros--from anywhere in your application. Therefore, use function 
    procedures, even if the utility of a function's return value is not 
    immediately apparent.
  
    If you were later to decide you need to call a Sub procedure from outside 
    Access Basic, you would have to convert it to a function. Having created 
    a function in the first place is better than having to make the 
    conversion.

  Declaring Private Procedures

    Unless you need to call a Function procedure from outside the module in 
    which it appears, declare it to be a private procedure:

      Private Function GetScreenType() As Integer

    Private procedures are limited in scope, which means the function can be
    "seen" only from within the module in which it appears. The effect of 
    this is that you cannot call the function from outside the module itself.
    At first this may seem like a useless or unnecessary limitation, but in 
    some cases this is a desired effect. One benefit to creating private 
    procedures is that there is no chance of a name conflict with other 
    functions since only non-private procedures are visible, or have scope, 
    throughout an application. In contrast, a private procedure in one module
    can have the same name as another private procedure in a second module.

    Procedures inside form modules are automatically private and do not 
    require the Private reserved word. Consequently, they may be called only 
    from the corresponding form. If you want to be able to call one of these 
    functions from someplace other than the form or the form module in which 
    it appears, you need to create a general-purpose function (in other than 
    a form module) instead of a private function.

  Indenting Code

    You should indent all lines except the function declaration itself, the 
    End Function statement, and any line labels (most functions do not have 
    line labels). You may be accustomed to placing comments or declarations 
    (Dim statements) to the far left of the Module window but doing so 
    disrupts the ability to quickly determine where blocks of code begin and 
    end.

    The default tab stop width in Microsoft Access is four spaces; you should
    avoid changing this default for several reasons:

      o Narrower tab stop widths (fewer than four spaces) result in more 
	compact, often harder-to-read code.
      o Wider tab stops (more than four spaces) result in longer lines that 
	tend to extend beyond the limits of the Module window, thus requiring
	excessive scrolling. In addition, longer lines also tend to wrap when
	you print your code (unless you print in landscape mode, something 
	other developers will not expect).
      o Especially in a multiple-developer environment, the standard tab stop
	width is essential to presenting a unified application that also 
	matches what other non-developer users are accustomed to using.

    Within a function, you should indent additional levels:

      o All lines in a loop
      o Lines in an If...Then...Else construct
      o Cases in a Select Case block
      o All lines within a Case of a Select Case block
      o All lines between an AddNew or Edit method and its corresponding 
	Update or Rollback method

  Line Spacing

    As the preceding example procedure illustrates, you should add blank 
    lines to increase the readability of your code. Insert blank lines before
    and after declarations, between significant blocks of code (you decide 
    what is significant), and before and after loops and similar block 
    constructs. The amount of such "white space" can vary greatly depending 
    on the particular procedure. The goal of blank lines is to isolate major
    sections to increase the readability of your code.

  Naming Constants

    Generally, constants should be all uppercase with allowable underscores. 
    Examples of satisfactory constants include IGNORECASE and HOTPINK. 
    Depending on the application, you may also want to include a prefix that 
    identifies the kind or category of constant, as in the case of message 
    box-related constants that would otherwise start with MB_ (for example, 
    MB_ICONEXCLAMATION).

    Avoid same-name constants that have conflicting scope. For example, 
    avoid naming a global constant and a module-level constant with the same 
    name. Many new users, especially, may not understand the implications of 
    scope and may become confused at how Microsoft Access "ignores" a 
    seemingly good global constant when there is a scoping conflict.

  Declaring and Naming Variables

    If you have included the Option Explicit statement in every module (and 
    you should), you must explicitly declare each variable:

      Dim MyDB As Database, MyTable As Table
      Dim MyControl As Control
      Dim SalesTotal As Currency, X As Integer

    Avoid type-declaration characters. For example, although X% is an 
    otherwise valid variable name, you should avoid using the percent sign 
    (%). One reason for avoiding type-declaration characters is that not all 
    data types have a type-declaration character: for example, Variants.

    Another reason for omitting type-declaration characters is that they add 
    only marginal utility to variable names at the expense of making the 
    variables harder to read. Moreover, most function procedures are so short
    that, if you should have to determine a variable's data type, you can 
    look through the procedure's Dim statements. If your variables have 
    meaningful names, you probably will not need to determine the data type 
    at all. For example, you can generally assume a variable named City is a 
    string, SalesTotal is a currency variable, and NumRecords is a long 
    integer. In contrast, City$, SalesTotal@, and NumRecords& are 
    unnecessarily harder to read and add little, if any, value.

    For the same reasons that they add little utility and make your code 
    harder to read, you should also avoid the so-called Hungarian notation, 
    or prefixes. For example, you would not name these same variables 
    strCity, curSalesTotal, or lngNumRecords. Again, if you need to make sure
    of a variable's data type, look for its Dim statement.

    Generally, group the variable declarations by function; that is, group 
    the database object variables together, looping control variables 
    together, and so on. Within each group, declare the variables 
    alphabetically.

    Variable names should be as long as necessary to convey meaning without 
    undue confusion or unnecessary abbreviations. For example, Org is a poor 
    abbreviation for Original. If you decide to abbreviate, choose 
    abbreviations that are intuitive to general users and not necessarily 
    developers (remember, you may not always be the only one who has to look 
    at your code). In this example, Orig is a better abbreviation than Org, 
    which could be mistaken to mean Organization.

    By convention, only constants and user-defined types appear in 
    all-uppercase. Avoid using underscores in variable names; instead, use 
    upper- and lowercase letters:

      Satisfactory  Unsatisfactory
      ------------  --------------
      SalesTotal    Sales_Total
      RecordsFound  RECORDSFOUND
      X             x

    As with constants, avoid same-name variables that have conflicting scope.

    To make better use of memory, try to avoid declaring large, static 
    arrays. Instead, programmatically determine how large the array needs to 
    be and use the ReDim statement to declare the array.

   When you are done using a static array, ReDim the array to zero elements. 
   In the case of a dynamic array, use the Erase statement to free the memory
   used by the array.

Adding Comments and Documenting Your Work

  No matter how intuitively you name database objects and variables, nothing 
  can replace descriptive, clear, and concise comments. Long after you have 
  worked on your code, you or other developers (or users) will return to the 
  application. One goal of commenting your work is to minimize the time it 
  takes to figure out what your code does and how it works.

  Earlier in this chapter, "Order of Elements in a Function" discussed using 
  a "header" that describes the purpose of the procedure, the arguments it 
  accepts (if any) and the procedure's possible return value(s). These 
  general notes are intended to document what the procedure does but not 
  necessarily how it works.

  Most function procedures contain sufficiently complex code requiring 
  additional comments in the body of the procedure. For some sections of 
  code, particularly Select...Case and If...Then constructs, a block comment 
  is appropriate. A block comment describes the actions or results of a block
  of code (hence the name block comment). A block comment begins in the same 
  column as the block to which it applies.

    ' Loop through the records looking for all Sales
    ' representatives and change their titles to Account
    ' Executive.
    Do Until MySet.EOF
    ...
    Loop

  For many other lines of code, including lines otherwise documented with a 
  block comment, you can add comments to the end of the line, aligned in the
  same column whenever possible.

    Function csvNullToZero (Number As Variant) As Variant

	If Not IsNull(Number) Then  ' If it isn't Null...
	    csvNullToZero = Number  ' ...return same value.
	Else
	    csvNullToZero = 0       ' Otherwise, return 0.
	End If

    End Function

  As you try to align comments in the Module window, it is sometimes 
  difficult to tell which column you are in, especially if previous comments 
  earlier in the procedure have scrolled off the screen. Consider maximizing 
  the Module window and then using the tab key to move the insertion point to
  a reference point on the toolbar. For example, you might position the 
  insertion point at the tab position immediately before or after the Run 
  button.

  Whether a line requires a comment depends on the particular function the 
  line appears in, the function's construction and the comments around and 
  near the line. All comments should end with trailing punctuation, usually a
  period.

Choosing Between Modules and Macros

  The decision to choose modules over macros (or vice versa) depends greatly 
  on your particular application, any product elements you may be trying to 
  illustrate (if you are creating a teaching application), as well as the 
  need for consistency among all of your applications.

  As you decide when and whether to use either modules or macros, try to 
  remember that typical users must first acquire a full understanding of 
  macro actions before they can fully implement the power of Access Basic. 
  Also remember that most users are familiar with macros but not Basic.

  Even so, there are some easily-identified situations in which either 
  modules or macros are the better choice:

    >> Choose macros...
       ...when you do not require error handling; that is, the actions in the
	  macro cannot possibly create a run-time error condition.
       ...to create an AutoExec macro that runs each time users run your 
	  application. Depending on the complexity of the macro and whether 
	  you require any error handling, consider creating a single-action 
	  AutoExec macro that uses the RunCode macro action to call a 
	  function named AutoExec.
       ...for quick prototyping when speed of development is paramount or 
	  when you are testing ideas for application task flow.
       ...to create custom menu bars, something you cannot do in Access 
	  Basic code.
       ...to create an AutoKeys macro that remaps, or reassigns, keys.
       ...when the actions you want to take are simple, fairly 
	  straightforward, and well-defined.
       ...when it is practical, makes sense, and does not require elaborate 
	  branching to other macros, does not involve loops, and is easy to 
	  follow.

    >> Choose modules...
       ...when you require error handling.
       ...when a macro starts to get too involved because of excessive 
	  jumping around between macros (using the RunMacro macro action).
       ...when a condition to a macro action is complex or particularly 
	  lengthy, making it hard to read; in this case, convert the macro to
	  a function.
       ...when the user interface elements prove inadequate and the required
	  macro action does not exist.
       ...to implement transactions.
       ...to process data one record at a time (for example, looping through 
	  a recordset).
       ...to create new database objects.
       ...to call a Windows API function or a function in a Dynamic Link 
	  Library (DLL).

Miscellaneous Issues

  Supplementing the issues raised earlier in this chapter, the following 
  collection of guidelines summarizes additional miscellaneous standards you
  should consider as you develop your applications.

    o Always use the Option Explicit statement. Including Option Explicit 
      requires you to declare every variable. Among the goals and effects of 
      this statement are to prevent misspellings and to make sure you 
      properly declare the variable data types. Note, however, that Option 
      Explicit is effective only in the module in which it appears, so you 
      must add the statement to every module, even such modules as Global 
      Constants, Declarations, and Messages (just in case you or someone else
      adds executable code to these modules).
    o Use the plus sign (+) for math operations and the ampersand (&) for 
      string concatenation. Avoid using the plus sign to handle strings; as 
      it relates to null values, if you want to reproduce the effects of 
      using the plus sign, create a function that handles this correctly.
    o Use the reserved words True and False, and not the values -1 and 0.
    o To improve the speed performance of your application, open all modules,
      choose the Compile Loaded Modules command from the Run menu and then 
      explicitly save each module. This technique ensures that none of your
      code has to be compiled at run time.
    o As you work on your code, certain elements remain work-in-progress. To
      identify these unfinished areas, add a comment formatted like that 
      shown here:

      ' UNDONE

      Follow a single apostrophe with a single space and the word UNDONE and 
      any additional, optional comments. Adopting this guideline not only 
      lets you quickly search for any unfinished code, but also lets others 
      know whether code is broken or simply incomplete.
    o "If you turn it on, turn it off. If you turn it off, turn it back on."
      If you turn echo off, be sure you turn echo back on; if you enable 
      error trapping, disable it when you are finished with it. The same 
      holds true for enabling and disabling system warnings toggled with the 
      SetWarnings macro action. Do not rely on Microsoft Access to turn these
      settings back on for you.
    o When you want to manipulate or work with strings, use the $ forms of 
      functions. Use the non-$ forms when you work with or manipulate 
      Variants. Such functions include Left[$], Right[$], and Format[$].
    o Generally, place only one statement on a each line. Exceptions include 
      simple assignments such as initialization code at the beginning of a 
      procedure.

      X = 0: Y = 0

      One other exception is combining multiple variable declarations on a 
      single line:

      Dim X As Integer, Y As Integer

Summary

  Adopting a consistent naming convention is not just about making your code 
  pretty and compliant with somebody else's guidelines. Rather, a carefully 
  thought-out and readable style is essential to making your applications 
  easy to design and easy to maintain in the future. Indeed, even if you do 
  not agree with all of the guidelines described in this chapter, you should 
  adopt the ones that make sense in the context of your own applications.

  Whereas this chapter has concerned itself largely with behind-the-scenes 
  issues, the next chapter, "Application Design Guidelines," discusses ways 
  you can make your applications more attractive and usable.
