If you make any changes to these coding conventions notify the development team of the change!
Class Naming Conventions
All classes should have a 3 letter prefix, with the initial letter capitalized, that indicates the kind of class. For example, DlgModelDefinition says that the Model Definition class is a dialog (Dlg) form. The 3 letter prefixes are listed in the following sections.
In addition, some classes which are very closely associated with another class (usually a form) have second 2 letter prefix. This comes between the class prefix and the name, indicating which class they are assocated with. For example, DlgABColumnManager is the Column Manager dialog (Dlg) form attached to the Analysis Browser (AB). The 2 letter prefixes used are as follows:
|2-letter prefix||Class associated with|
|CD||Conventional distance sampling engine (properties)|
|DF||Data Filter (properties)|
|MD||Model Definition (properties)|
When saving classes to file, drop the prefix e.g. form DlgABColumnManager becomes ColumnManager.frm. See Form and Module Filenames below for more details.
All classes that are not standard VB classes and are not user-defined should be fully qualififed. For example:
Dim fldTemp As Field 'No qualifying here as a standard VB class Dim mofldTemp As MapObjects.Field Dim flxGrid As New vsFlexLib.vsFlexArray
Prefixes for Form Modules
|Dialog form||Modal form, usually with BorderStyle property = Fixed Dialog||Dlg||DlgOpenProject|
|Wizard form||Special type of Dialog form that provides an interactive user interface for complex tasks||Wiz||WizDataImport|
|MDI parent form||Multiple document interface parent form - only one in the app||Mdi||MdiMain|
|Multiple instance form||Child form of the MDI parent where more than one can be shown at once||Mif||MifAnalysisDetails|
|Single instance form||Child form of the MDI parent where only one can be shown at once||Sif||SifDataExplorer|
|Other (general) form||Anything else - should be very few of these!||Frm||FrmDialogStorage|
Prefixes for Code Modules
Database-specific code modules are prefixed with Dbe, for Database Engine.
All other code modules are prefixed with Mod e.g. ModMain.
Prefixes for Class Modules
Class modules are prefixed with Cls e.g. ClsAnalysisServerInterface.
Classes that are collections have pluralized names e.g. the Analysis Server Interface collection is ClsAnalysisServerInterfaces.
Prefixes for User Control Modules
In general, user controls have the prefix Ctl e.g. CtlLabelLine.
However, there are two special subsets of the users controls:
- Input Pages, with prefix Pag. An input page is a user control that contains many standard controls and is presented to the user as an input page on a dialog or wizard form (usually the pages are selected among using a tab control). See DlgModelDefinition for an example. Input page classes are given the prefix Pag, and always have a second prefix indicating the form they are placed on e.g. PagMDModels is the Models input page that goes on the Model Definition form.
- Details Pages, with prefix Det. These are user controls that go on a Details form. They are given the prefix Det, to separate them from the other controls e.g. CDetDDInputs is the design details inputs control.
Object Naming Conventions
Prefixes for Controls (mapping controls excluded) and other classes
Other classes include, for example, StringBuilder.
|Control type||Prefix||Example||Date added|
|ActiveBar (by Data Dynamcs)||bar||barAnalysis||6/4/98|
|Browse dialog (by Common Controls Replacement Program)||bdlg||bdlgBrowse||14/7/98|
|Chart (by Microsoft)||chrt||chrtResults||5/7/98|
|Combo box, drop-down list box||cbo||cboEnglish|
|Control (used when the specific type is unknown)||ctr||ctrCurrent|
|Data-bound combo box||dbcbo||dbcboLanguage|
|Data-bound list box||dblst||dblstJobType|
|Directory list box||dir||dirSource|
|Drive list box||drv||drvTarget|
|File dialog (by Common Controls Replacement Program)||fdlg||fdlgOpen||14/7/98|
|File list box||fil||filSource|
|FlexArray (by Video Soft)||flx||flxDataSheet||2/2/98|
|FlexString (by Video Soft)||flxstr||flxstrResults||17/2/98|
|Horizontal scroll bar||hsb||hsbVolume|
|ImprintPro (by Far Point)||imp||impDataSheet||24/2/98|
|Input page (by ljt - group of user controls)||pag||pagModel||16/3/98|
|LabelLine (by ljt)||lal||lalInput|
|ListBar (by Sheridan Software)||lbr||lbrAnalysisInputs|
|ListItem (by Sheridan Software)||lit||litModel|
|MsgDisplay (by ljt)||msg||msgOutput|
|Input page (by ljt)||pag||pagModel|
|ParseListBox (by ljt)||prslst||prslstLog|
|Ribbon (by Sheridan Software)||rib||ribPlotStyle|
|Splitter (by Sheridan Software)||spl||splAnalysisDetails|
|Tab (see next)||tab||tabOptons|
|TabPro (by Far Point)||tap||tapDefinitions|
|Tool (by Data Dynamcs)||tool||toolPaste|
|User Control (unless given specific prefix)||uct||uctInputs|
|Vertical scroll bar||vsb||vsbRate|
Collection objects should have an ‘s’ added to the prefix, and the variable name should be pluralized. For example:
Dim nodMember As Node Dim nodsMembers As Nodes
Choosing Prefixes for Other Controls
For controls not listed above, standardize on a unique two or three character prefix. Use more than three characters only if needed for clarity.
Once you decide on a new prefix, add it to the table above, write in the date, and notify the development team of the update.
Prefixes for ESRI MapObjects
Prefix for the Control:
Prefixes for Objects:
Prefixes for Collections:
Prefixes for Data Access Objects (DAO)
Dim dbBiblio As Database Dim recPubsInNY As Recordset, strSQLStmt As String 'Open database. Set dbBiblio = OpenDatabase("BIBLIO.MDB") ' Set text for the SQL statement. strSQLStmt = "SELECT * FROM Publishers WHERE " & _ State = 'NY'" ' Create the new Recordset object. Set recPubsInNY = db.OpenRecordset(strSQLStmt, _ dbReadOnly)
Prefixes for User-defined Class Instances
Includes Class, Form, Code and User control Modules.
In general, the prefix for all instances of classes defined is the same as the class prefix, but with the initial capital in lower case. For example:
Dim dlgModelDefinition As DlgModelDefinition Dim clsAnlaysisServerInterface As New ClsAnalysisServerInterface
An exception to this is the user control LabelLine, which is used widely as a general control, and is given all sorts of object names. Instead of the prefix uct, it has the prefix lal. For example:
Dim lalModelHeader As UctLabelLine
Constant and Variable Coding Conventions
In addition to objects, constants and variables also require well-formed naming conventions. This section lists recommended conventions for constants and variables supported by Visual Basic. It also discusses the issues of identifying data type and scope.
Variables should always be defined with the smallest scope possible. Global (Public) variables can create enormously complex state machines and make the logic of an application extremely difficult to understand. Global variables also make the reuse and maintenance of the code much more difficult.
Variables in Visual Basic can have the following scope:
|Procedure-level||Private in procedure, subroutine, or function||The procedure in which it is declared|
|Module-level||Private in the declarations section of a form or code module (.frm, .bas)||Every procedure in the form or code module|
|Global||Public in the declarations section of a code module (.bas)||Everywhere in the application|
In a Visual Basic application, global variables should be used only when there is no other convenient way to share data between forms. When global variables must be used, it is good practice to declare them all in a single module, grouped by function. Give the module a meaningful name that indicates its purpose e.g. modPublic.
It is good coding practice to write modular code whenever possible. For example, if the application displays a dialog box, put all the controls and code required to perform the dialog’s task in a single form. This helps to keep the application’s code organized into useful components and minimizes its run-time overhead.
With the exception of global variables (which should not be passed), procedures and functions should operate only on objects passed to them. Global variables that are used in procedures should be identified in the declaration section at the beginning of the procedure.
Declaring all variables saves programming time by reducing the number of bugs caused by typos (for example, aUserNameTmp vs. sUserNameTmp vs. sUserNameTemp).
Within Visual Basic, select Tools => Options… then, in the Editor tab, check the Require Variable Declaration option. This puts an Option Explicit statement at the beginning of each new form, which in turn requires that all variables in a Visual Basic program are declared explicitly.
Variables should be prefixed to indicate their data type. The prefix should also be extended to indicate the scope of the variable (see following section).
Variable Data Types
Use the following prefixes to indicate a variable’s data type.
The only exception to the above is for simple looping variables in For loops, which are always integers (see below).
Variable Scope Prefixes
As project size grows, so does the value of recognizing variable scope quickly. A one-letter scope prefix preceding the type prefix provides this, without greatly increasing the size of variable names.
|Local to procedure||None||dblVelocity|
A variable has global scope if it is declared Public in a standard module or a form module. A variable has module-level scope if declared Private in a standard module or form module, respectively.
Note Consistency is crucial to the productive use of this technique - the syntax checker in Visual Basic will not catch module-level variables that begin with “p.”
The body of constant names should be all upper case. In addition, use the same prefix rules as for variables. For example:
mintUSER_LIST_MAX 'Max entry limit for User list '(integer value,local to module) gstrNEW_LINE 'New Line character '(string, global to application)
These are all given the prefix dst (for Distance). For example:
Public Enum ProjectSettingsLocations dstProject = 0 dstRegistry = 1 dstProjectThenRegistry = 2 End Enum
Enumerations should be used in place of constants wherever possible, as they then appear in the drop down list when you are typing, reducing typing errors.
In a large project with many user-defined types, it is often useful to give each such type a three-character prefix of its own. If these prefixes begin with “u” they will still be easy to recognize quickly when you are working with a user-defined type. For example, “ucli” could be used as the prefix for variables of a user-defined Client type.
The following is a list of user defined types:
|Data type||Prefix||Example||Date added|
|none yet||none yet||none yet||none yet|
Descriptive Variable, Constant and Procedure Names
The body of a variable or procedure name should use mixed case and should be as long as necessary to describe its purpose. In addition, function names should begin with a verb, such as InitNameArray or CloseDialog.
For frequently used or long terms, standard abbreviations are recommended to help keep name lengths reasonable. In general, variable names greater than 32 characters can be difficult to read on VGA displays.
When using abbreviations, make sure they are consistent throughout the entire application. Randomly switching between Cnt and Count within a project will lead to unnecessary confusion.
When you use a new abbreviation, add it to the list below and write in the date.
The following is the current list of abbreviations:
|Looping variable (note - this is the only time no prefix is required)||i, j, k||i||2/2/98|
Array Lower Bounds
Use base 0 wherever possible, and put Option Base 0 at the beginning of all modules, so it is the default.
Structured Coding Conventions
Structure of Forms and Modules
All forms and code modules should have the same basic structure:
- Introductory Comments - giving the purpose of the module, its assumptions, and public interface (see next section).
- Global Definitions (if there are any) - global type definitions, constants and variables.
- Module level Definitions - module level variables and constants.
- Public Properties.
- Public Methods.
- Private Subroutines and Functions (i.e. non event-driven subroutines and functions) - arranged in some kind of “logical order” (i.e. most important, high-level procedures first, with the procedures the call following them). There will obviously be some leeway for placement here.
- Control Event Subroutines, arranged in alphabetical order (this is the Windows default).
Separate each of these sections with a dashed line
See the Distance code for examples.
Code Commenting Conventions
All procedures and functions should begin with a brief comment describing the purpose and functional characteristics of the procedure (what it does), unless it is extrememly obvious. This description should not describe the implementation details (how it does it) because these often change over time, resulting in unnecessary comment maintenance work, or worse yet, erroneous comments. The code itself and any necessary inline comments will describe the implementation. However, for procedures that implement complex algorithms or use tricky programming, some brief implementation notes can be useful, so long as they are clearly delimited from the rest of the text (see table below).
Arguments passed to a procedure should be described when their functions are not obvious and when the procedure expects the arguments to be in a specific range. Function return values and global variables that are changed by the procedure, especially through reference arguments, should also be described at the beginning of each procedure.
Procedure header comment blocks should include the following section headings as required. For examples, see the next section on Formatting Code.
|Section heading||Comment description|
|Purpose||What the procedure does, but not how|
|Called from||List of modules that call this module, only where this would be useful (mostly for non event driven utility procedures)|
|Called when||For event procedures, where not obvious|
|Assumptions||List of each external variable, control, open file, or other element that is not obvious|
|Effects||List of each affected external variable, control, or file and the effect it has, only if this is not obvious|
|Inputs||Each argument that may not be obvious. Arguments are on a separate line with inline comments.|
|Returns||Explanation of the values returned by functions|
|Implementation note||General notes about the algorithm used or other implementation details can be included if they will be useful to the understanding of the procedure|
|Seperate these from the other comments by one blank line, so they can be easily identified and changed if the implementation changes.|
Remember the following points:
- Every important variable declaration should include an inline or before-line comment describing the use of the variable being declared.
- Variables, controls, and procedures should be named clearly enough that inline commenting is only in more complex cases.
- At the start of the .bas module that contains the project’s Visual Basic generic constant declarations (usually public.bas), you should include an overview that describes the application, enumerating primary data objects, procedures, algorithms, dialogs, databases, and system dependencies. Sometimes a piece of pseudocode describing the algorithm can be helpful. This can be written near the end of the project development cycle.
- Too many comments are better than too few, especially because other people will be working with the code we write!
Because many programmers still use VGA displays, screen space should be conserved as much as possible while still allowing code formatting to reflect logic structure and nesting. Here are a few pointers:
- Standard, tab-based, nested blocks should be indented four spaces (the default).
- Highest level statements that follow the overview comment should be indented one tab, with each nested block indented an additional tab. For example:
Function intFindUser (strUserList() As String, strTargetUser As _ String)As Integer 'Purpose: Locates the first occurrence of a ' specified user in the UserList array. 'Inputs: ' strUserList(): the list of users to be searched. ' strTargetUser: the name of the user to search for. 'Returns: The index of the first occurrence of the ' rsTargetUser in the rasUserList array. ' If target user is not found, return -1. Dim i As Integer ' counter. Dim blnFound As Integer ' Target found flag. intFindUser = -1 i = 0 Do While i <= Ubound(strUserList) and Not blnFound If strUserList(i) = strTargetUser Then blnFound = True intFindUser = i End If Loop End Function
Defined constants at the module level should be grouped by function and placed at the beginning of the module to which they refer. Modules used in more than one form should do in ModGlobal. Where there is any doubt, put it in ModGlobal!
& and + Operators
Always use the & operator when linking strings and the + operator when working with numerical values. Using the + operator to concatenate may cause problems when operating on two variants. For example:
vntVar1 = "10.01" vntVar2 = 11 vntResult = vntVar1 + vntVar2 'vntResult = 21.01 vntResult = vntVar1 & vntVar2 'vntResult = 10.0111
Creating Strings for MsgBox, InputBox and SQL Queries
When creating a long string, use the underscore line-continuation character to create multiple lines of code so that you can read or debug the string easily. This technique is particularly useful when displaying a message box (MsgBox) or input box (InputBox) or when creating an SQL string. For example:
Dim Msg As String Msg = "This is a paragraph that will be " _ & "in a message box. The text is" _ & " broken into several lines of code" _ & " in the source code, making it easier" _ & " for the programmer to read and debug." MsgBox Msg Dim strQuery As String strQuery = "SELECT *" _ & " FROM Titles" _ & " WHERE [Year Published] > 1988" TitlesQry.SQL = strQuery
Form and Module Filenames
The filename should be the same as the form or module name, minus the prefix. The file extension is the standard .frm for Forms, .mod for Modules, .cls for Classes and .ctl for User Controls. Examples: