(Other Format - BK&CD ROM)
Because Visual Basic powerful development capabilities are within ready grasp of both the professional and the recreational programmer, many Visual Basic developers are self-taughtand therefore lack formal training on programming standards. But anyone who writes even a single line of codeand especially developers working in concert on a single projectshould employ some basic, standardized techniques to optimize application maintainability and extensibility, as well as sidestep costly errors and pitfalls. But until now, there has been no definitive handbook describing these standards. Practical Standards For Microsoft Visual Basic fills this critical need, providing pragmatic guidelines on both where and how to apply programming standards for maximum benefit. Readers discover that by consistently utilizing standards in how they design interfaces and organize code, they can realize substantial gains in efficiency, reliability and performancefor themselves and in the solutions they build.
Key Book Benefits:
About the Author(s): James Foxall is Vice President of Tigerpaw Software, Inc. (www.tigerpawsoftware.com), a software development firm specializing in commercial database applications. James is responsible for the management of all Windows® application development including Pursuit, a certified Office Compatible contact and customer-information system reviewed in many major software and trade publications. James's experience in creating certified Office Compatible software has made him an authority on application interface and behavior standards of applications for the Microsoft Windows and Office environment. James has personally written over 90,000 lines of commercial production code in both single-programmer and multiple-programmer environments.
James has written several computer books on both Access and Visual Basic. The author has also written for Access/Office/VBA Advisor magazine and is an international speaker on Microsoft Access and Microsoft Visual Basic, and he is a Microsoft Certified Solution Developer (MCSD). In addition to speaking and writing, James has taught Visual Basic at the college level, and has been featured on numerous television news shows, in trade publications, and in newspaper articles for his technology expertise.
More Reviews and RecommendationsJames Foxall is Vice President of Tigerpaw Software, Inc. (www.tigerpawsoftware.com), a software development firm specializing in commercial database applications. James is responsible for the management of all Windows® application development including Pursuit, a certified Office Compatible contact and customer-information system reviewed in many major software and trade publications. James's experience in creating certified Office Compatible software has made him an authority on application interface and behavior standards of applications for the Microsoft Windows and Office environment. James has personally written over 90,000 lines of commercial production code in both single-programmer and multiple-programmer environments.
James has written several computer books on both Access and Visual Basic. The author has also written for Access/Office/VBA Advisor magazine and is an international speaker on Microsoft Access and Microsoft Visual Basic, and he is a Microsoft Certified Solution Developer (MCSD). In addition to speaking and writing, James has taught Visual Basic at the college level, and has been featured on numerous television news shows, in trade publications, and in newspaper articles for his technology expertise.
Reader Rating:
See Detailed Ratings
February 09, 2000: I just finished this book. It offers advice on how to write better code. The section on creating enumerations was very helpful, but you can read that chaptr on Microsoft Press's web site. The error-handling chapter was also very good. It also teaches some cool things with user interaction and interface. Every Visual Basic programmer should have this on their bookshelf! I'm sure I'll write better code because of this book!
The Barnes & Noble Review
Visual Basic isn't just about hacking around and quick-&-dirty prototyping any more. It's serious business, and yesterday's sloppy code and voodoo variables no longer cut it. If you're serious about writing solid, high-performance, maintainable VB code, you want Practical Standards For Microsoft Visual Basic.
In this book, James D. Foxall offers specific standardization "directives" for each key aspect of Visual Basic development. For instance, he starts by offering specific recommendations and techniques for creating object and project templates that promote reuse and application consistencyfrom common splash screens and switchboard forms to half-completed applications containing intricate code, such as multiple document interfaces.
Next, you'll learn the best ways to design modules and procedures. Using plenty of examples, Foxall shows how to give procedures and modules descriptive names, give each procedure a single exit point and clearly defined scope, and call your procedures in a consistent, self-documenting manner.
There are chapters on naming conventions; more effective use of constants and enumerations; variables, error handling; formatting and commenting code; looping structures and code flow; and especially user interaction and team developmentincluding practical tips for version and source code control, and working with Visual SourceSafe. There have been programming standards guides before, but few have focused entirely on Visual Basic. If you're one of the 3,000,000+ VB developers out there,you'llbe glad this one did.
Because Visual Basic powerful development capabilities are within ready grasp of both the professional and the recreational programmer, many Visual Basic developers are self-taughtand therefore lack formal training on programming standards. But anyone who writes even a single line of codeand especially developers working in concert on a single projectshould employ some basic, standardized techniques to optimize application maintainability and extensibility, as well as sidestep costly errors and pitfalls. But until now, there has been no definitive handbook describing these standards. Practical Standards For Microsoft Visual Basic fills this critical need, providing pragmatic guidelines on both where and how to apply programming standards for maximum benefit. Readers discover that by consistently utilizing standards in how they design interfaces and organize code, they can realize substantial gains in efficiency, reliability and performancefor themselves and in the solutions they build.
Key Book Benefits:
About the Author(s): James Foxall is Vice President of Tigerpaw Software, Inc. (www.tigerpawsoftware.com), a software development firm specializing in commercial database applications. James is responsible for the management of all Windows® application development including Pursuit, a certified Office Compatible contact and customer-information system reviewed in many major software and trade publications. James's experience in creating certified Office Compatible software has made him an authority on application interface and behavior standards of applications for the Microsoft Windows and Office environment. James has personally written over 90,000 lines of commercial production code in both single-programmer and multiple-programmer environments.
James has written several computer books on both Access and Visual Basic. The author has also written for Access/Office/VBA Advisor magazine and is an international speaker on Microsoft Access and Microsoft Visual Basic, and he is a Microsoft Certified Solution Developer (MCSD). In addition to speaking and writing, James has taught Visual Basic at the college level, and has been featured on numerous television news shows, in trade publications, and in newspaper articles for his technology expertise.
Loading...Special Characters
& (ampersand)
concatenating strings, 99-100, 106-7
creating command button access keys, 303-4
creating menu access keys, 282
' (apostrophe), 189-91
* (asterisk), 186, 189
: (colon)
label control captions and, 268
line labels and, 117
multiple statements and, 150
... (ellipsis), 282
( ) (parentheses)
clarifying expressions with, 242-43
function calls and, 46
+ (plus sign), 99-100, 106
_ (underscore)
as line continuation character, 151-56
simulating spaces in names, 35, 86
A
abbreviations
avoiding, in comments, 192-93
procedure names and, 34, 35
variable names and, 83-84, 87-88
About dialog boxes, version numbers in, 22, 332-33, 333
About Face: The Essentials of User Interface Design, 251
accelerator keys, 253, 285-88, 286
access keys. See also shortcut keys
command button, 303-4, 304, 305
menu, 282, 282, 303, 304
ActiveBar software, 286
active error handler, 122
ActiveX components, backward compatibility of, 333-41, 338, 340
Binary Compatibility level, 340
conditions for, 336-37
Project Compatibility level, 339
overview of, 334-36
relinquishing, 338
version compatibility vs., 333-34
Visual Basic levels of, 337, 338
ActiveX controls, 57, 273. See also controls
add-in menu, Visual SourceSafe, 352-53, 353
AddNew method, indentation and, 162, 166
Admin user, 351
aligning statements, 154-55
Alt key, 303
ampersand (&)
concatenating strings, 99-100, 106-7
creating command button access keys, 303-4
creating menu access keys, 282
API viewer, 65
apostrophe ('), 189-91
application consistency, 253
application names in object templates, 21-22
application prefixes, 71-73
application titles, 320, 320
App object properties, 20-22, 333
arrays
control, 70-71, 276-77
looping through, 226-27
naming, 55
of Variants, 100
asterisk (*), 186, 189
author information, 195
Auto List Members feature, 61-62, 62
B
background compilation, 110-12, 111
backing up files, 339, 342. See also copying projects
backward compatibility, 334. See also ActiveX components, backward compatibility of
BeginTrans method, indentation and, 162, 166-67
Binary Compatibility level, 337, 338, 340
binary files, 15, 356, 360
blank lines, grouping statements with, 169-77
Boolean data type, 97
Boolean expressions, comparing, 241
Boolean operators, 155-56
Boolean variables, 89-91, 241-42
border styles, form
default, 254-55
Fixed Dialog, 255, 255
Fixed Single, 256-57, 257
Fixed ToolWindow and Sizable ToolWindow, 258-59, 259, 260
none, 255-56, 256
Sizable, 255, 257, 258
boxes, comment, 188-89
branching constructs. See flow control constructs
breaking statements, 154-56
buttons
command (see command buttons)
menu items for toolbar, 288-89
message box, 61-62, 62, 74, 321-23, 323
ByRef and ByVal keywords, 41-42
C
calling procedures, 45-47, 156, 158
Call keyword, 45-46
call stack, error handlers and, 122-24, 125
Cancel command buttons, 302-3
CancelUpdate method, indentation and, 162, 166
capitalization. See case of characters
captions, 268
Case Else statements, 77, 78, 236-37
case of characters
in comments, 193
constant names, 65, 67
formatting code and, 146
GoTo labels, 65, 118, 246-47
procedure names, 34-35
system constant names, 75
variable names, 86-87
Case statements
indentation and, 162, 164
multiple result values in, 234
ordering, 237-39
central error handlers, 127-34, 130
characters
case of (see case of characters)
comment lines of solid, 185-88
maximum, of code per line, 153-56
using special, for each developer, 190-91
check box controls, 268, 278, 279
checking files in and out
using Visual Basic IDE, 361-64, 362, 363
using Visual SourceSafe Explorer, 359-61, 360, 361
Class IDs (CLSIDs), 336, 340
class modules, 28
cleanup code, 36, 38-39
CLSIDs (Class IDs), 336, 340
Code Complete (McConnell), 9, 148
code helper drop-down lists, 61, 62, 63, 63, 73-74, 73
coding standards, 1-11
benefits of, 3-5
commenting violations of, 182
constructs (see commenting code; flow control constructs; formatting code; looping constructs)
conventions (see constants; enumerations; error handling; naming conventions; variables)
design (see modules; object templates; procedures; project templates)
team projects (see Microsoft Visual SourceSafe; projects; version control)
coding standards, continued
this book about, 9-11
user interfaces (see interface design)
Visual Basic and necessity for, 5-9 (see also Microsoft Visual Basic)
Visual SourceSafe violations of, 345, 365
coercion, 6, 94, 99
cohesion, modules and, 26-28
collections
looping through object, 223-28
of procedures, modules as, 26-28
colon (:)
label control captions and, 268
line labels and, 117
multiple statements and, 150
colors, system, 289-93, 290, 291
combo box controls, 265-67, 266, 267, 278, 278
command buttons
assigning access keys to, 303-4, 304, 305
creating default and cancel, 302-3
disabling vs. hiding, 270, 270, 271
comment boxes, avoiding, 188-89
commenting code, 179-203
avoiding comment boxes, 188-89
benefits of, 179-80
documenting changes with, in Readme files, 341-42
documenting code processes with inline, 198-203
documenting code purposes, 180-82
documenting expected errors, 182-84
documenting variables with end-of-line, 203
explaining violations of coding principles, 182
goals of, 180
If...End If constructs, 170-71
indentation and, 168, 193
line continuation and end-of-line, 153
commenting code, continued
nested constructs, 239-40
in object templates, 23-24
parameters, 42
procedures, 193-98
as pseudocode, 184-85
readability and, 191-93
using apostrophes for, 189-91
using solid-character lines, 185-88
CommitTrans method, indentation and, 162, 166-67
Common database, Visual SourceSafe, 349
company prefixes, 71-73
comparing file revisions, 367-70, 367, 368, 369
compatibility, types of, 333-34. See also ActiveX components, backward compatibility of
compilation
data types and errors, 227
incrementing version numbers at, 330-32, 331
options, 110-12, 111
compile errors, 109-12, 111, 227
compound conditions, short-circuiting, 232-34
concatenating strings, 99-100, 106-7, 152
consistency, 138-41, 252-54
constants. See also enumerations
default scope of, 66
global, 20-21
goals of using, 64
magic numbers vs., 21, 59-61, 67-68
naming, 64-67
system (see system constants)
using, 59-61
using, in For...Next loops, 208, 212
using, as references to elements of control arrays, 70-71
container controls, 275-76, 279-80, 301
context menus, 307-11, 308, 315-17
continuation lines
indenting, 156-59, 162, 164-65
using, 151-56
controls
ActiveX vs. standard, 273
advanced interface techniques and, 265
avoiding picture box, 279-80
benefits of naming conventions for, 51
check box captions, 268
denoting default properties, 53
disabling, vs. hiding, 269-70, 270, 271
displaying lists with combo box, 278, 278
displaying lists with list box, 277, 277
displaying static lists with option buttons, 275-77, 275
displaying text with text box, 274, 274
height of single-line, 265-67, 266, 267
looping through arrays of, 276-77
prefixes for ActiveX, 57
prefixes for standard, 56-57
referencing, in control arrays, 70-71
setting maximum length of data-bound, 305-7, 306, 307
standardizing appearance of, 265-73
tab order and, 299-301, 301, 302
toggling options with check boxes, 278, 279
transparent backgrounds for labels, 269, 269
using frame, 280
using scroll bar, 280-81, 280
using Tag properties, 271-73
vertical alignment of labels, 268, 268
conventions. See constants; enumerations; error handling; naming conventions; variables
coordinates
frame control, 280
variables for, 83
copying projects, 358-59, 358, 359. See also backing up files
copying text in Visual SourceSafe, 370
copyright information, 196
counter variables, For...Next, 209, 212-15
critical messages, 318, 319
Ctrl+C key combination, 370
Ctrl+F5 key combination, 110, 111
Currency data type, 98
D
data
data entry problems with magic numbers, 60
enumerated (see enumerations)
hard-coded (see hard-coded values; magic numbers)
input/output procedures, specialized, 31
numerical conditions in If...End If constructs, 231
object templates and sharing, 20-22
passing, between procedures using parameters, 41-44 (see also parameters)
return values (see return values)
True and False values, 89, 231, 238-39, 241
types (see data types)
validating (see data validation)
database object prefixes, 58
databases, Visual SourceSafe
adding users to, 351-52, 351, 352
creating, 349, 349
.ini file extension, 350, 351
opening, 349-51, 350
data-bound controls, maximum length of, 305-7, 306, 307
data ink, 187
data types
choosing, for variables, 94-98, 95
data types, continued
coding standards and, 6
collection elements, 223-24, 226, 227
constants and, 65-66
enumerations as, 61, 63 (see also enumerations)
Hungarian notation and, 52-53
indentation and user-defined, 168-69
for parameters, 41
prefixes for variable names, 53-55
suffixes, 52
using specific in For Each...Next loops, 227-28
Variant (see Variant data type)
data validation
constants, 60
enumerated type parameters, 64, 76-78
parameters, 42-44
date, code modification, 195-96
Date data type, 98
debugging code
enabling and disabling error handlers, 125-27, 126, 127 (see also error handling)
single exit points and, 35-36
specialized procedures and, 29
tightly coupled procedures and, 30
decision structures. See flow control constructs
declarations
of enumerations, 62
explicit, of constants, 66
explicit, of parameters, 41
explicit, of variables, 5, 60, 79, 91-94, 93
indentation and, 168-69, 170, 174-75
indenting procedure, 156, 157-58
single, of variables per line, 101-2
Declarations section, 23, 60, 62, 168-69
default command buttons, 302-3
default message box buttons, 322
default project templates, 16-17, 16, 17
default properties of controls, 53
descriptive names. See also names; naming conventions
for procedures and modules, 33-35
for variables, 82-86
design. See coding standards; interface design; modules; object templates; project templates; procedures
design consistency, 253-54
Developing User Interfaces for Microsoft Windows, 251
dialog boxes. See also forms
About, 332-33, 333
border styles, 255, 255
design consistency and, 253-54
tool windows, 258-59, 259, 260
differences, file revision, 368-70, 369
Dim statement, 53, 91, 103
directories. See folders
disabling error handlers, 124-27, 126, 127
disabling items on forms, 269-70, 270, 271
disabling menu commands, 283
disabling object templates, 18-19, 19
Dispatch IDs, 337
display resolution, 153
documentation, Readme files and, 341-42. See also commenting code
Do...Loop loops, 216-23
commenting, 201-2
GoTo statement vs., 221-23, 244-46
indentation and, 162, 164
testing exit conditions, 219-21
While...Wend loops vs., 223
Double data type, 98
dynamic lists, 275, 277, 277, 278, 278
E
Edit menu commands, 284
Edit method, indentation and, 162, 166
element variables, 223-24
ellipsis (...), 282
ElseIf statement, 235
Else statement, 162, 163
enabled error handler, 122
Enabled property, 269, 283
enabling error handlers, 125-27, 126, 127
enabling object templates, 18-19, 19
encapsulation, 28, 31
End Function statement, 140
End If statement, 231-32
endless loops, 139
end-of-line comments, 153, 203, 239-40
End Property statement, 140
End Sub statement, 140
Enter key, 302-3
enumerations. See also constants
custom, 62-64, 63
goals of using, 64
indentation and, 169
naming conventions, 71-73
parameters and, 44, 75-76
system constants vs., 73-75, 73, 74
using, 61-62, 62, 68-69
validating passed values, 76-78
Enum keyword, 62
environmental errors, 109
Err object, 112-13, 114-15
error handling, 109-41
call stack and, 122-24
Case Else statements and, 236-37
central, 127-34, 130
creating consistent blocks, 138-41
data types and, 227
disabling, with On Error GoTo 0, 124-25
documenting expected errors, 182-84
enabling and disabling, in debugging, 125-27, 126, 127 (see also debugging code)
Err object and, 112-13
goals of, 134
logging errors to text files, 130-34
error handling, continued
object templates and, 18
overflow errors, 94-95, 95
single exit points and, 140-41, 244
trapping expected errors with On Error Resume Next, 114-16, 136-38
trapping unexpected errors with On Error GoTo, 116-22, 134-36
types of, 113-28
types of errors, 109-10
using GoTo with, 244
Visual Basic compilation options, 110-12, 111
Esc key, 302
Event procedures, documenting, 196
events
backward compatibility and, 336-37
mouse, 310-11, 315-17
evil type coercion (ETC), 99
exclamation icon, 318, 319, 321
execution flow. See flow control constructs
Exit Do statement, 218,
Exit For statement, 210, 215-16
Exit Function statement, 35, 118, 119
exit points for procedures, 30-31, 35-39, 140-41, 244
Exit Property statement, 118, 119
Exit Sub statement, 35, 118, 119
expected errors
documenting, 182-84
trapping, 113, 114-16, 136-38
explicit declaration
of constants, 66
of parameters, 41
of variables, 5, 60, 79, 91-94, 93
expressions
breaking statements between, 155-56
comparing Boolean, to True or False, 241
formatting, 241-43
indenting continuation lines, 156, 158-59
using parenthesis in, 242-43
F
F1 key, 74
F5 key, 110
False value, 89, 231, 241
fan-in and fan-out, 31-32, 32
File menu commands, 283
files
backing up, 339, 342
binary, 15, 356, 360
.ini file extension, 350, 351
logging errors to text, 130-34
Readme, 341-42
Visual Basic (see projects)
Visual SourceSafe database (see databases, Visual SourceSafe)
Fixed Dialog style, 255, 255
Fixed Single style, 256-57, 257
Fixed ToolWindow style, 258-59, 259, 260
flow control constructs, 229-47
avoiding GoSub statements, 243-44
documenting, 243
documenting nested, with end-of-line comments, 239-40
formatting expressions, 241-43
goals of, 230
GoTo statements, 244-47
If...End If, 230-34
overview of, 229-30
Select Case...End Select, 234-39
using On Error Goto for, 116-22
focused variables, 80-81, 82
folders
designating working, 356-57, 357, 358
for object templates, 14-15, 14, 15, 19-20, 19
paths and object templates, 21
for project templates, 16, 17
sharing working, 357
Visual SourceSafe database, 349, 349
For Each...Next constructs, 223-28, 277
formatting characters for each developer, 190-91
formatting code, 145-77
benefits of, 145-49
expressions, 241-43
goals of, 149
indenting comments, 193
indenting continuation lines, 156-59
indenting declarations to show subordination, 168-69
indenting For...Next constructs, 210, 215
indenting to show organizational structure, 160-68, 160
menus, 281-85, 282
using line continuation character, 151-56
using single statements per line, 102, 150-51
using white space to group statements, 169-77
forms, 254-65
assigning access keys to command buttons, 303-4, 304, 305
avoiding morphing, 264-65
border styles, 254-59, 255, 256, 257, 258, 259, 260
controls on (see controls)
creating command buttons, 302-3
disabling templates, 18, 18
keyboard navigation, 298-99 (see also keyboard navigation and interaction)
pop-up menus (see pop-up menus)
setting maximum length of data-bound controls, 305-7, 306, 307
setting tab order of, 299-301, 301, 302
startup positions, 260-64, 261, 262, 263
templates, 14-15, 14
unloading, 264
For...Next constructs
commenting, 201-2
GoTo statement vs., 221-23
looping through arrays, 226-27
using, 205-16
frame controls, 275-76, 279-80, 301
Friend keyword, 39-41
functionality, backward compatibility and, 337
Function keyword, 26
Function procedures. See also procedures
calling, 45-46
defined, 25, 26
documenting return values, 198
retrieving return values, 45, 46-47
Variant return values, 101
G
global constants, 20-21, 30, 66. See also system constants
globally unique identifiers (GUIDs), 336
global scope, 39
global variables
commenting, 202-3
parameters vs., 20-21, 30, 41
problems of, 103-4
GoSub statement, 243-44
GoTo statements
case of line labels, 65, 118, 246-47
indentation of line labels, 167-68
line numbers and labels, 117
looping constructs vs., 221-23
single exit points and, 36
using, 244-47
grammar mistakes, 324
Guest user, 351
GUIDs (globally unique identifiers), 336
H
hard-coded values
numbers (see magic numbers)
in object templates, 20-22
strings, 59
height of single-line controls, 265-67, 266, 267
Help menu commands, 285
hiding
items on forms, 269-70, 270, 271
menu commands, 283
history, file revision, 367-68, 367, 368
hot keys, 282, 282, 285-88, 286
hourglass pointer icon, 312-13
Hungarian notation, 52-53, 79. See also prefixes
I
icons
message box, 318, 320, 320, 321
mouse pointer, 311-15
source code control, 355, 355, 362
IDE. See integrated development environment (IDE)
If...End If constructs
blank lines and, 170-71
commenting, 199-200
indentation and, 156, 159, 162-63
numerical conditions, 231
Select Case...End Select vs., 235
short-circuiting compound conditions, 232-34
using, 230-34
using End If statements with, 231-32
validating enumerated values, 76-78
ignoring errors. See expected errors
image controls, 279
indentation
of comments, 193
of continuation lines, 156-59
of For...Next constructs, 210, 215
self-documenting code and, 148
to show organization structure, 160-68, 160
indexes of control arrays, 70-71
information messages, 318, 319
.ini file extension, 350, 351
inline comments, 182, 198-203
input, specialized procedures for, 31. See also interface design; user input
Insert menu commands, 284
installation programs, 332
Integer data type, 97
integrated development environment (IDE). See also Microsoft Visual Basic
checking files in and out using, 360, 361-64, 362, 363
run-time errors in, 110
setting in error trapping, 126-27, 126, 127
interactive duality, 297
interface design, 251-93
benefits of standards, 4-5
consistency in, 252-54
controls (see controls)
forms (see forms)
goals of, 254
menus (see menus)
using system colors, 289-93, 290, 291
J-K
jargon, avoiding, 324-25
keyboard navigation and interaction, 295, 298-325
assigning access keys to command buttons, 303-4, 304, 305
dialog box command buttons and, 302-3
setting maximum length of data-bound controls, 305-7, 306, 307
setting tab order of forms, 299-301, 301, 302
keys. See access keys; shortcut keys
L
label controls, 268-69, 268, 269, 274, 274
labels. See line labels
line continuation character (_), 151-56. See also continuation lines
line labels. See also GoTo statements
case of, 65, 118, 246-47
indentation and, 167-68
line numbers and, 117
line labels, continued
PROC_ERR, 117
PROC_EXIT, 36, 118, 119, 140, 244
line numbers, 117
list box controls, 277, 277, 315-17
lists
dynamic, 277, 277, 278, 278
selecting items before displaying pop-up menu, 315-17
static, 275-77, 275
local constants, 66
local variables, 84, 103
logging errors to text files, 130-34
log in, Visual SourceSafe, 353, 353
Long data type, 98
looping constructs, 205-28
benefits of, 205
blank lines and, 170, 173
commenting, 201-2
Do...Loop, 216-23
For Each...Next, 223-28
For...Next, 205-16
goals of, 205
loops, endless, 139
loosely coupled procedures, 30
lowercase. See case of characters
M
magic numbers. See also hard-coded values
constants vs., 21, 59-61, 67-68
data validation and, 77-78
loops and, 208
MaxLength property, 305-7, 306, 307
memory resources
picture box controls and, 279
scope and, 103, 104
unloading forms to free, 264
Variants, 100
Menu Editor, 282, 286
menus, 281-89
access keys, 282, 282
basic and extended shortcut keys, 288
Edit menu commands, 284
File menu commands, 283
menus, continued
formatting and organizing Windows style, 281-85, 282
Help menu commands, 285
Insert menu commands, 284
items corresponding to toolbar buttons, 288-89
keyboard access, 298
pop-up, 307-11, 308, 315-17
shortcut keys, 253, 285-88, 286
tools for creating, 286
Tools menu commands, 285
View menu commands, 284
Visual SourceSafe add-in, for Visual Basic, 352-53, 353
Window menu commands, 285
message boxes, 318-25
avoiding technical jargon, 324-25
button enumerations, 61-62, 62, 74
choosing appropriate, 318-20, 319, 320
choosing buttons, 321-23, 323
error handling and, 139
notification messages and, 297-98
proofreading messages, 324, 324
methods
backward compatibility and, 336-37
indentation of Recordset, 162, 166-67
PopupMenu, 309-10
SetFocus, 136, 183-84
Microsoft Office, 4-5, 252-53
Microsoft Outlook-style navigation bars, 265
Microsoft Visual Basic
Auto List Members feature, 61-62, 62
compilation options, 110-11
data types, 97 (see also data types)
declarations settings, 5, 60, 92-93, 93
default scope, 40
IDE (see integrated development environment (IDE))
Microsoft Visual Basic, continued
levels of ActiveX component compatibility, 337, 338
levels of scope in, 103
necessity for standards for, 5-9 (see also coding standards)
projects (see projects)
project templates, 16-17, 16, 17
setting in error trapping, 126-27, 126, 127
source code control (see Microsoft Visual SourceSafe)
system constants, 71 (see also system constants)
tab stop settings, 160, 160
template settings, 19-20, 19
viewing multiple procedures, 32-33, 33, 176, 177
Microsoft Visual SourceSafe, 345-72
adding new files to projects, 364-65, 364
adding users, 351-52, 351
benefits and complexities of, 345-46
checking files in and out with Visual Basic IDE, 361-64, 362, 363
checking files out with Explorer, 359-61, 360, 361
comparing revisions, 367-70, 367, 368, 369
components and functions of, 347-48
creating databases, 349, 349
creating working copies of projects, 358-59, 358, 359
designating working folders, 356-57, 357, 358
opening databases, 349-51, 350
placing projects under control of, 352-55, 353, 354, 355
project development under, 355-70
retrieving latest version of files, 365-67, 365, 366, 367
Microsoft Visual SourceSafe, continued
setting up, with Administrator, 348-55, 348
team development challenges, 346-47
version control and, 343 (see also version control)
Microsoft Windows
interface, 252-53, 281-85, 282
viewing version numbers with Explorer, 330, 331
mixed-case. See case of characters
modules. See also projects
alphabetizing procedures in, 32, 33
compiling (see compilation)
creating, 26-28
Declarations sections, 23-24, 168-69 (see also declarations)
descriptive names for, 33-35
error handling and, 18 (see also error handling)
goals of designing, 33
procedures and, 25-26 (see also procedures)
requiring variable declaration, 92-93, 93
module scope, 39-40, 41, 103
monitor resolution, 153
morphing forms, 264-65
mouse interaction, 295, 307-17
pop-up menus, 307-11, 308
selecting list items before displaying pop-up menu, 315-17
using pointer for user feedback, 311-15
MousePointer property, 311-12
MsgBox statement, 61-62, 62, 74, 139, 297, 318. See also message boxes
multiline text boxes, 306
multiple-document interface (MDI) mode, 261-62, 262
multiple-line statements, 154-55
multiple procedures, viewing, 32-33, 33, 176, 177
multiple statements per line, 101-2, 150-51
multiselection list boxes, 277, 277
N
names
alphabetizing procedure, in modules, 32, 33
application, 21-22
in comments, 181
constant, 60
conventions (see naming conventions)
descriptive, for procedures and modules, 33-35
descriptive, for variables, 82-86
hard-coded application, in object templates, 21-22
naming conventions, 51-58
for constants, 64-67
data type suffixes, 52
denoting variable data type, 53-55
denoting variable scope, 55-56
differentiating variables from controls, 51
for enumerations, 71-73
Hungarian notation, 52-53
for modules, 26
for objects, 56-58
navigation. See keyboard navigation and interaction
navigation bars, Outlook-style, 265
nested constructs
commenting, 239-40
indenting, 161
nested procedures, 122-24
No Compatibility level, 337, 338, 338
Nothing, setting forms equal to, 264
notifications. See also user input
goals of, 298
message boxes, 318-25 (see also message boxes)
overview of, 295, 297-98
numbers
as conditions in If...End If constructs, 231
line, 117
magic (see magic numbers)
O
Object data type, 223-24, 227
objects
controls (see controls)
default properties, 53, 148
Err, 112-13, 114-15
error handling with, 116
looping through collections of, 223-28
prefixes for, 54, 56-58
reusable, 13, 16
templates (see object templates)
Variant data type and, 98
object templates. See also project templates
benefits of, 13
comments in, 23-24
editing, 15
enabling and disabling, 18-19, 18, 19
error handling and, 18
goals of using, 20
hard-coded values and, 20-22
setting folder for, 19-20, 19
using, 14-15, 14, 15
obj prefix, 54
OK buttons, 302-3, 321-22
On Error GoTo 0 statement, 117, 124-25
On Error GoTo statement, 113, 116-22, 134-36
On Error Resume Next statement, 113, 114-16, 136-38
option buttons, 275-77, 275
Option Explicit statement, 5, 60, 92-93
ordering Case statements, 237-38
organizational structure, indentation to show, 160-68, 160
output, specialized procedures for, 31
overflow errors, 94-95, 95
P
parameters
backward compatibility and, 337
documenting, 197
enumerations for, 44, 64, 75-76
global data vs., 20-21, 30
passing data between procedures using, 41-44
system constants for, 74, 74
validating, 42-44, 76-78
parent controls, 275-76, 279-80, 301
parentheses ()
clarifying expressions with, 242-43
function calls and, 46
passing by reference vs. by value, 41-42
passwords, Visual SourceSafe, 351-52, 351
paths, object templates and hard-coded, 21. See also folders
performance, 7, 100-101, 223, 241
picture box controls, 279-80
pixels, 266280
plus sign (+), 99-100, 106
pointer, mouse, 311-15
pointing devices, 295
PopupMenu method, 309-10
pop-up menus, 307-11, 308, 315-17
positive form in Boolean variables, 89-91, 241-42
prefixes
application or company, for enumerations, 71-73
constant, 64-67
Hungarian notation and, 52-53
object, 56-58
variable data type, 53-55
variable scope, 55-56, 105-6
Private keyword, 39-41, 66, 91, 103
procedural scope, 103
Procedure IDs, 337
procedures
alphabetizing, in modules, 32, 33
procedures, continued
blank lines and, 170, 176-77, 177
calling, 45-47
clearly defined scope for, 39-41
comment headers for, 193-98
descriptive names for, 33-35
documenting code processes in, 198-203
error handling in (see error handling)
goals of designing, 33
indenting continuation lines of, 156, 157-58
minimizing fan-in and fan-out, 31-32, 32
modules and, 25-28 (see also modules)
object templates and Property, 22
parameters to pass data between, 20-21, 41-44 (see also parameters)
self-contained, 30-31
single exit points for, 35-39
specialized functions and, 28-30
types of, 25-26
viewing multiple, 176, 177
PROC_ERR label, 117
PROC_EXIT label, 36, 118, 119, 140, 244
programmer errors, 109
programming standards. See coding standards
Project Compatibility level, 337, 338, 339
Project Explorer, 355, 355, 361-64, 362, 363
projects. See also modules
adding objects to, 14-15, 14, 15
coding standards (see coding standards)
compatibility at level of, 337, 338, 339
compiling (see compilation)
error trapping setting, 126-27, 126, 127 (see also error handling)
source code control (see Microsoft Visual SourceSafe)
projects, continued
team development challenges, 8, 346-47
templates (see project templates)
version control (see version control)
project templates. See also object templates
benefits of, 13
custom, 17-18
goals of using, 20
Visual Basic, 16-17, 16, 17
proofreading messages, 324, 324
properties
App object, 20-22, 333
backward compatibility and, 336-37
denoting default, of controls, 53
determining system constants for, 74, 74
Err object, 112-13
exposing, for template objects, 22
MaxLength of data-bound controls, 305-7, 306, 307
MousePointer, 311-12
tab order, of forms, 299-301
Tag, 271-73
Property keywords, 26
Property procedures, 22, 25, 26, 196
pseudocode, comments as, 184-85
pseudosubroutines, 243-44
Public keyword, 39-41, 66, 91, 103
purpose
of code, 180-82
of procedures, 197
of variables, 80-81, 82
Q
qualifiers, variable name, 88-89
quantity, indicating, 280-81, 280
question messages, 318 319
R
readability
comments and, 6, 191-93
constants and, 61, 68
formatting and, 6, 148
Readme files, 341-42
read-only files, Visual SourceSafe and, 348
Recordset methods, indentation and, 162, 166-67
redundancy, 205
reentrancy, preventing, 104-5
Registry, 336
REM keyword, 189
reserved words, 154
resolution, monitor, 153
resources. See memory resources
restoring backup files, 342
return values
documenting, 198
enumerations, 64
message box constants, 322-23
retrieving, 45, 46-47
Variant, 101
reusability, 13, 16, 20, 252
revisions
comparing, 367-70, 367, 368, 369
history, 196
RollBack method, indentation and, 166-67
rounding, 6, 94, 99
routines. See procedures
run time, disabling error handlers at, 124-25
run-time errors, 109-10
S
scope
denoting constant, 61, 64-67, 70
denoting variable, 55-56, 105-6
minimizing variable, 30, 41, 103-6
of procedures, 39-41
scroll bar controls, 280-81, 280
Select Case...End Select construct
blank lines and, 170, 172
Case statements that are never True, 238-39
commenting, 200-201
determining selected option button, 236
Select Case...End Select construct, continued
including Case Else with, 236-37
indentation and, 162, 163-64
ordering Case statements, 237-38
using, 234-39
validating enumerated type parameters, 77, 78
selecting list items before displaying pop-up menus, 315-17
self-contained procedures, 30-31
sentences, using complete, 191-92
SetFocus method, 136, 183-84
Shift+F2 key combination, 66
short-circuiting compound conditions, 232-34
shortcut keys, 253, 285-88, 286. See also access keys
Simonyi, Charles, 52
single declarations per line, 102
single-document interface (SDI) mode, 261, 261
single exit points for procedures, 30-31, 35-39, 140-41, 244
single statements per line, 150-51
Sizable style, 257, 258
Sizable ToolWindow style, 258-59, 259, 260
solid-character comment lines, 185-88
source code control. See Microsoft Visual SourceSafe; version control
source code standards. See coding standards
spaces
splitting statements after, 154-55
underscores for, 35, 86
special characters for each developer, 190-91
specialized procedures, 28-30, 31
speed, indicating, 280-81, 280
spelling mistakes, 75, 146, 324, 324
standard controls, 56-57, 273. See also controls
standards. See coding standards
startup position, form, 260-64, 261, 262, 263
statements
blank lines between groups of, 170, 175-76
breaking, 154-56
grouping, with blank lines, 169-77
indentation and, 162, 164-65
single, per line, 102, 150-51
Static keyword, 91
static lists, 275-78, 275, 277, 278, 279
static variables, 104-5
Step keyword, 205, 207-8, 212
String data type, 97
strings
breaking large, 152-53
concatenating, 99-100, 106-7, 152
eliminating hard-coded, 59
passing, 42
strong cohesion, 27
Sub keyword, 26
Sub procedures, 25, 26, 46, 47. See also procedures
suffixes
data type, 52
qualifier, 88-89
syntax errors, 109-10, 154
system colors, 289-93, 290, 291
system constants
message box buttons, 321-23, 323
message box icons, 320
message box return values, 322-23
mouse pointer icons, 311-12
naming conventions, 71
pop-up menu, 310
system colors, 292
using, 73-75, 73, 74, 83
T
Tab controls, 265
tablets, 295
tab order of forms, 299-301, 301, 302
tab stops, 160, 160
Tag properties, 271-73
team development, challenges of, 8, 346-47. See also Microsoft Visual Source-Safe; version control
technical jargon, avoiding, 324-25
Template folder, 14-17, 14, 15, 16, 17
templates. See object templates; project templates
temporary variables, 84-86
territorial statements, 151
text box controls
displaying editable text, 274, 274
height of, 265-67, 266, 267
maximum length of text in, 306-7, 307
referencing control array elements, 70-71
text copying in Visual SourceSafe, 370
text files, logging errors to, 130-34
tightly coupled procedures, 30-31, 32
time values, 98
timing errors, 109
toggling options, 278, 279
toolbar buttons, menu items for, 288-89
Tools menu commands, 285
tool windows, 258-59, 259, 260
touchpads, 295
trackballs, 295
trapping errors. See error handling
Tree view controls, 265
True value, 89, 231, 238-39, 241
twips, 280, 316
type coercion, 6, 94, 99
type_ prefix, 54-55
U
udt prefix, 55
underscore (_)
as line continuation character, 151-56
simulating spaces in names, 35, 86
unexpected errors, trapping, 113, 116-22, 134-36
unfocused variables, 80
unloading forms, 264
Until keyword, 217, 219-21
Update method, indentation and, 162, 166
update problems, 60-61
uppercase. See case of characters
user accounts, adding Visual SourceSafe, 351-52, 351, 352
user-defined data types
indentation and, 168-69
naming, 54-55
user input. See also notifications
data entry problems, 60
goals of, 298
keyboard interaction,
298-307 (see also keyboard navigation and interaction) mouse interaction, 307-17 (see also mouse interaction)
overview of, 295, 296-97
specialized procedures for, 31
user interfaces. See interface design
V
validating. See data validation
values. See data
variables, 79-107
abbreviating names of, 87-88
benefits of naming conventions, 51
blank lines and blocks of, 170, 174-75
choosing data types for, 94-98, 95 (see also data types)
concatenating strings, 106-7
data type prefixes, 53-55
data type suffixes, 52
descriptive names for, 82-86
differentiating, from controls, 51
documenting, with end-of-line comments, 203
element, 223-24
explicitly declaring, 5, 60, 79, 91-94, 93
focused, 80-81
For...Next counter, 209, 212-15
global (see global variables)
goals of using, 79
variables, continued
Hungarian notation, 52-53, 79
minimizing scope of, 30, 41, 103-6
mixed case in naming, 86-87
names in comments, 181
passing, between procedures, 41-44 (see also parameters)
positive forms for Boolean, 89-91, 241-42
qualifiers for, 88-89
scope prefixes, 55-56, 106
setting, and indenting continuation lines, 156, 157, 158-59
setting, to Function procedure result, 46
temporary, 84-86
using Variant data type for, 98-102
voodoo, 5
Variant data type
as default type of parameters, 41
element variables of collections and, 223-24, 226, 227
and initial values, 92
type coercion problems of, 6, 98-102
version compatibility, 334
version control, 329-43
backing up files, 342
benefits of, 329-30
displaying version numbers in About dialog boxes, 332-33, 333
documenting changes in Readme files, 341-42
goals of, 330
incrementing version numbers at compilation, 330-32, 331
maintaining backward compatibility in ActiveX components, 333-41, 338, 340
Microsoft Visual SourceSafe and, 343 (see also Microsoft Visual SourceSafe)
version control, continued
object templates and hard-coded version numbers, 22
View menu commands, 284
violations of programming style, explaining, 182
visibility. See scope
Visible property, 269, 283
Visual Basic. See Microsoft Visual Basic
Visual Display of Quantitative Information, The (Tufte), 187
Visual SourceSafe. See Microsoft Visual SourceSafe
Visual SourceSafe Administrator, 348, 348, 352
Visual SourceSafe Explorer, 357, 357, 358, 359-61, 360, 361, 363
voodoo variables, 5
W
warning messages, 318, 319
weak cohesion, 27
While keyword, 216-17, 219-21
While...Wend constructs, 223
white space, grouping statements with, 169-77
Window menu commands, 285
windows
tool, 258-59, 259, 260
viewing multiple procedures in, 32-33, 33, 176, 177
Windows. See Microsoft Windows
Windows Explorer, 330, 331
Windows Interface Guidelines for Software Design, The, 251
With statement, indentation and, 162, 165
working copies of projects, 358-59, 358, 359
working folders, 35657, 357, 358
When you hard-code numbers in your procedures, a myriad of things can go wrong. Hard-coded numbers are generally referred to as "magic numbers" because they're often shrouded in mystery; the meaning of such a number is obscure because the digits themselves give no indication as to what the number represents. This chapter discusses the drawbacks of magic numbers and offers alternatives using constants and enumerations.
A constant is much like a variable; you create a name and assign it a value. However, unlike a variable, a constant is given its value at design time, and this value cannot be changed at run time. You should always use constants in place of magic numbers, for reasons I'll discuss in this section.
One of the critical problems with magic numbers is that you can easily mistype a number, transposing its digits. When you type the number 10876, for instance, it's not at all difficult to mistakenly type 10867 or 18076. In contrast to the way it handles variables and reserved words, Microsoft Visual Basic's compiler takes no issue with transposed or incorrect numbers—it's happy to use whatever magic number you supply it. Sometimes the problems caused by asimple mistake don't surface immediately, and when they do they can appear as random miscalculations that are difficult to pinpoint. When you use a constant in place of a magic number, Visual Basic checks the validity of the constant at compile time. If the constant does not exist, Visual Basic tells you so and refuses to compile. This eliminates the problem of inaccurately typed numbers; as long as the single constant has the correct value, all the code that uses that constant will use the correct value as well.
Another serious drawback to magic numbers is that they're difficult to keep updated. Say you're developing a financial application and the current mortgage interest rate is 7.25 percent. Also assume that this value is hard-coded in a number of procedures that perform calculations based on the interest rate. What do you do when the rates change (which they do regularly)? You could perform a global search and replace, but that exposes your code to errors. Another loan rate used within the application might also have the value 7.25. If you perform a global search and replace on 7.25 percent, you'll change that loan rate as well. If you manually change each value in the code, you risk transposing or otherwise mistyping the new values. A selective search and replace with a confirmation on each change would be time-consuming. If you use a constant instead, you simply change the value once (in the constant's declaration), and every line of code that uses the mortgage interest rate instantly uses the new, updated rate.
A by-product of using constants to create more error-free code is code that is much more readable. Generally, magic numbers are anything but intuitive. They might be obvious to you, but they can be difficult for others to decipher. By intelligently naming your constants, the code that uses those constants becomes a bit more self-documenting and a lot easier to read. Consider the following two code statements. Which makes the most sense to you?
Magic numbers:
curInterestAmount = (curLoanAmount * .06) / 12
Named constants:
curInterestAmount = _ (curLoanAmount * c_sngInterestRate) / c_intMonthsInTerm
One last note on constants: it's quite acceptable to give constants higher scope, unlike when you use variables, a situation in which it's highly advisable to reduce scope. As a matter of fact, you should never create the same constant twice within an application. If you find that you're duplicating a constant, move the original declaration to a higher scope until the constant becomes available to all procedures that reference it.
Enumerations are similar to constants in that they are named entities that are assigned values. However, enumerations behave like groups of public constants in a module. They're treated as data types, and you use them to create constants of suitable values for variables and properties. You might already be using enumerations in Visual Basic. For instance, when you use the MsgBox statement, Visual Basic's Auto List Members feature displays a drop-down list (commonly referred to as the "code helper drop-down list") for the Buttons parameter. (See Figure 5-1.)
The time that the developers of the MsgBox statement invested to provide the Buttons parameter's values in an enumeration pays you dividends as a programmer. You never have to remember the numeric values of the parameter, and the chance of incorrectly specifying a value is greatly diminished. Although you can still specify a numeric value for a parameter rather than the name of an enumeration member, you should never do so. To actually use a magic number when an associated member name is available is just south of insane.
You create enumerations much like you do user-defined data types. In the Declarations section of a module, you type the word Public or Private, type Enum, and then type the name of your custom enumeration. The following is a sample enumeration:
Public Enum otBorderStyle otNone = 0 otRaised_Light = 1 otRaised_Heavy = 2 otSunken_Light = 3 otSunken_Heavy = 4End Enum
This enumeration creates an enumerated type with five values. Although you always refer to the name of an enumeration member when you write code, the name simply represents its numeric value, much like a constant. All members of enumerations are long integers; you can't use other data types.
Once you've created an enumeration, you can use it as the data type for any variable, Function procedure, or Property procedure within the scope of the enumeration. For instance, to create a BorderStyle property that uses the enumerated type shown previously, you can declare a procedure like this:
Public Property Let BorderStyle(lngNew_BorderStyle _ As otBorderStyle) End Property
This property procedure accepts a value into the parameter lngNew_BorderStyle. lngNew_BorderStyle is a long integer because it is declared as an enumerated type and all members of enumerations are long integers. When you reference this property in code, Visual Basic displays the code helper drop-down list with all the enumeration members, as shown in Figure 5-2.
You can also use an enumerated type as the data type returned by a function or a Property procedure. For instance, to create the Property Get procedure that corresponds to the previous Property Let procedure, you can use code like this:
Public Property Get BorderStyle() As otBorderStyle End Property
Note that simply declaring a parameter as an enumerated type does not guarantee that the value passed to the parameter will be one of the defined enumeration members. As a matter of fact, this is one of the most common misconceptions about enumerated types. When you define an enumeration, you define a list of named values, but these are not the only values that a parameter of that enumerated type will accept. As mentioned previously, parameters that are defined as enumerated types are actually long integers. As such, they accept any value that fits into a long integer; Visual Basic does not confirm that the number passed into a parameter corresponds to a member of the enumeration. For this reason, you should always validate the data passed to a parameter declared as an enumerated type, as I'll discuss in Directive 5.8.
The goals of using constants and enumerations include
In the past, one convention for denoting a constant was to use all uppercase letters for the constant's name. For instance, when you created a constant to store a column index in a grid, you would use a statement like this:
Const COLUMN_INDEX = 7
Typing anything in code in all uppercase letters is now considered antiquated and undesirable. Mixed-case text is much easier to read. However, since variable and procedure names are also entered in mixed case, it's important to denote when an item is a constant. A better convention is to prefix the constant name with c_. For example, the constant shown above would be declared like this:
Const c_Column_Index = 7
This constant name is a bit easier to read, and you can still immediately tell that you're looking at a constant as opposed to a variable. The second underscore is optional. Some developers (including me) prefer not to use an underscore in this way. This is fine, as long as your approach is consistent. The same constant declaration without the second underscore would look like the following line of code. (Remember that you'll always have an underscore in the constant prefix.)
Const c_ColumnIndex = 7
Another identifying characteristic of a constant as opposed to a variable is the lack of a data type prefix. For instance, if you were storing the column indicator in a variable, you would probably declare the variable by using a statement like this:
Dim intColumnIndex As Integer
Many developers don't realize that you can actually create a constant of a specific data type. For instance, the following statement is completely legal:
Const c_InterestRate As Single = 7.5
You can specify a data type for a constant, but it adds complexity, and I don't know of a good reason to do so. If you decide to do it anyway, you should use the variable-naming prefixes discussed in Chapter 4, "Naming Conventions." The previous declaration, for instance, is not correct—according to the directives presented in this book—because the data type prefix is omitted. The proper declaration would be as follows:
Const c_sngInterestRate As Single = 7.5
Although the prefix for constants is different from the prefixes for variables, you should still use the same prefix scheme for indicating the scope of constants that you use for variables. For constants declared locally (within a procedure), no scope indicator is necessary. For constants declared as Private in the Declarations section of a module, you should use the prefix m. For global constants (constants declared as Public within a standard module), you should use the prefix g. The following are declarations of the same constant at different levels of scope:
Procedure: Const c_InterestRate = 7.5Module (private): Private Const mc_InterestRate = 7.5Global: Public Const gc_InterestRate = 7.5
By consistently specifying the scope of a constant in addition to denoting the constant with c_, you'll make your code easier to read and to debug. If you're ever unsure where a constant is declared, simply place the cursor anywhere within the name of the constant and press Shift+F2. Visual Basic will take you directly to the constant's declaration.
Practical ApplicationsWhen you uniquely identify constants and denote their scope, you create more readable code.
5.1.1 Declare constants using mixed-case characters, prefixing each constant with c_. Remember that identifying constants by using all uppercase letters is out.
Incorrect:
Const USDATE = "mm/dd/yyyy"Const KEYCONTROL = 17
Correct:
Const c_USDate = "mm/dd/yyyy"Const c_KeyControl = 17
Also correct:
Const c_US_Date = "mm/dd/yyyy"Const c_Key_Control = 17
5.1.2 Denote a constant's scope using a scope designator prefix. Knowing a constant's scope is extremely important for debugging. All constants declared in the Declarations section of any type of module need a g or an m designator.
Incorrect (module level or global level):
Private Const c_US_DATE = "mm/dd/yyyy"Public Const c_KeyControl = 17
Correct:
Private Const mc_US_Date = "mm/dd/yyyy"Public Const gc_KeyControl = 17
I hope that the first part of this chapter has convinced you of the importance of replacing hard-coded numbers (magic numbers) with constants, regardless of scope. It might be tempting to use a hard-coded number within a procedure because it seems silly to create a constant for a single use in a single place. Certainly, maintaining the value is easy enough; you don't need to perform a search and replace when the number exists only once. However, readability is still a problem. Magic numbers are called "magic" for a reason. When someone else looks at the code, how can you be sure that the number will make complete sense to him or her? Regardless of scope, you should always replace magic numbers with constants. All together now: "Use constants in place of magic numbers, regardless of scope."
Incorrect:
'* Fill a most recently used list.For intCount = 1 To 4 strFileName = RetrieveRecentFileName(intCount) '* If an entry was found, add it to the list. If strFileName <> "" Then Set objItem = lvwRecent.ListItems.Add() objItem.Text = strFileName objItem.SmallIcon = "Database" End IfNext intCount
Correct:
'* Fill a most recently used list.Const c_Max_Recently_Used = 4For intCount = 1 To c_Max_Recently_Used strFileName = RetrieveRecentFileName(intCount) '* If an entry was found, add it to the list. If strFileName <> "" Then Set objItem = lvwRecent.ListItems.Add() objItem.Text = strFileName objItem.SmallIcon = "Database" End IfNext intCount
When a procedure or a parameter is declared as an enumerated type, it's common courtesy—nay, it's your duty—to reference the enumeration member names rather than their values. When you use an enumeration, your code is much easier to read and less likely to contain errors. Your code is also less likely to fail if someone later breaks backward compatibility by changing the values that correspond to the member names. For instance, say you're using an ActiveX component and one of its properties is BorderStyle. The developer has designated 0 - Flat and 1 - 3D as the possible values and has exposed them as members of an enumeration, as shown here:
Public Enum BorderStyle psFlat = 0 ps3D = 1End Enum
Say that you use the literal values rather than the enumeration's member names and you're updating to a new component. The developer has added a new BorderStyle value called Chiseled to the component. However, he wasn't really thinking of backward compatibility, and he changed the enumeration structure to the following:
Public Enum BorderStyle psFlat = 0 psChiseled = 1 ps3D = 2End Enum
You can see that if you hard-code 1 to designate a 3-D border, you'll get unexpected results after you upgrade. Obviously, component developers should not break backward compatibility in this way, but it does happen. If you use the member's name rather than its value, your code will not be affected by such an oversight. Whether to use enumerations shouldn't even be a question. If a function supports them, use them. In new versions of software components, enumerations are often provided where there were none before. As enumerations and constants become available, make sure to change your code appropriately to use them.
Incorrect:
MsgBox "Print all documents?", 36
Correct:
MsgBox "Print all documents?", vbYesNo Or vbQuestion
One area in which constants really shine but are often underused is as references to indexes of control arrays. When you create a control array, you end up with a number of controls all with the same name. To reference a particular control, you use its shared name and its unique index. When you hard-code an index, you create a magic number—complete with all the drawbacks discussed earlier. The problem with hard-coding index references is that your code can be difficult to debug if you've referenced the wrong index. Since controls within a control array are always of the same type, you can switch indexes all day long with little chance of generating an error message because all the actions you might perform on one member can be performed on another member.
To diminish the possibility of errors when you use control arrays, you should create constants that relate to each index. For example, say you have three text boxes that store a home phone number, work phone number, and mobile phone number, respectively. You use a control array because you have some standard code that runs on the Validate event to verify that each number is indeed a valid phone number. If you hard-code indexes, you have to remember which index references which type of phone number. If you're in a hurry or you haven't had your morning Mountain Dew, you can easily confuse the numbers. However, if you assign a constant to each index and always reference a control by its constant, never by its index directly, it's easier to ensure accuracy. Control arrays can make certain development situations much easier, and they can make an application less resource-intensive. However, the more elements you create for a control array, the more likely it is that an incorrect element will be referenced in code. Constants can help reduce the chances of this happening. In general, module-level scope is best for constants that reference elements of a control array, although local scope might be appropriate in some cases. The following constants have been given the prefix txt to denote that they reference the indexes of a text box control array.
Incorrect:
txtPhone(0).TexttxtPhone(1).TexttxtPhone(2).Text
Correct:
Const c_txtHomePhone = 0Const c_txtWorkPhone = 1Const c_txtFax = 2txtPhone(c_txtHomePhone).TexttxtPhone(c_txtWorkPhone).TexttxtPhone(c_txtFax).Text
Just as it's important to use a naming convention for variables, it's important to use a naming convention for enumeration members. You don't have to use a prefix to denote the type of an enumeration member because all members are always long integers. However, you should use a unique prefix that indicates that the values are from your application or component.
You should prefix your enumeration members with an identifier because when Visual Basic encounters an enumeration member name, it might get confused if other referenced type libraries contain the same name. For example, all of Visual Basic's system constants have the prefix vb. When you encounter a constant such as vbFixedSingle, you immediately know that the constant belongs to Visual Basic's type library. Although Visual Basic uses two-character prefixes, you should use three or four, but no more than that. If you were to use two characters, you would find it difficult to come up with an identifier that isn't used by another application or vendor. For instance, my company is called Tigerpaw Software. When we declare enumeration members, we use the prefix tps, as shown in the enumeration declaration on the following page.
Public Enum tpsPrintDestination tpsScreen = 0 tpsPrinter = 1End Enum
No application is an island. Even the simplest program uses many external libraries. To confirm this, just create a new Standard EXE and then choose References from the Project menu to see all the ActiveX components being referenced. With the increasing complexity of integrated components comes the need to be more aware of the potential for collisions between components. For this reason, give your enumeration members names that make such collisions unlikely.
Incorrect:
Public Enum BackTrackItem Account = 0 ServiceOrder = 1 Quote = 2 Contact = 3 PriceBookItem = 4 PurchaseOrder = 5 Task = 6End Enum
Correct:
Public Enum BackTrackItem tpsAccount = 0 tpsServiceOrder = 1 tpsQuote = 2 tpsContact = 3 tpsPriceBookItem = 4 tpsPurchaseOrder = 5 tpsTask = 6End Enum
Also correct:
Public Enum tpsBackTrackItem tpsAccount = 0 tpsServiceOrder = 1 tpsQuote = 2 tpsContact = 3 tpsPriceBookItem = 4 tpsPurchaseOrder = 5 tpsTask = 6End Enum
Creating custom enumerations for your modules is highly encouraged, but Visual Basic has been slow to adopt them for all of its own objects. For instance, when you set the WindowState property of a form, there are only three possible values: 0 - Normal, 1 - Minimized, and 2 - Maximized. Looking in the Properties window shows you this. Each value (0, 1, and 2) has a name associated with it. These names look very much like members of an enumeration—well, in the Properties window, at least.
Although Visual Basic should use true enumerations for these properties, more often than not it doesn't. Figure 5-3 shows what the code window looks like when you attempt to change the WindowState property of a form. Notice that there is no code helper drop-down list in which you can select from a set of values.
Visual Basic doesn't have defined enumerations for most of its objects, but it does often support system constants for the values. System constants are global constants that are part of the Visual Basic type library. You don't have to define them or reference a library to use them because they're always available. However, since system constants don't appear in the code helper drop-down list, as enumerations do, many developers are unaware that these constants exist. Whenever you must type a numeric value as a parameter of a Visual Basic function or as the value of a standard Visual Basic object property, chances are good there's an associated system constant.
To determine whether a system constant exists for a property, type the property name (such as WindowState), place the cursor anywhere within the property text, and press F1. The help displayed for the property will usually include a list of any constants that are available, as shown in Figure 5-4.
To use a system constant, you simply enter it as if you were referencing a constant that you've defined. For instance, to change a form to maximized, you can use a statement such as this:
Me.WindowState = vbMaximized
One way to know whether you've typed a system constant correctly is to type it in all lowercase letters. If the constant is valid, Visual Basic converts it to its proper case. If the constant remains in all lowercase letters, you've typed the name wrong and you have to correct it. Unlike enumerations, system constants can be used anywhere in code, not just with variables defined as an enumerated type. Therefore, you must be careful not to use the wrong constant because Visual Basic can't detect this type of error. Anything you can do to eliminate magic numbers is a good thing. If an enumeration is available for a procedure, use it. If not, check to see whether a system constant is defined. If that fails, consider creating your own constant to replace the magic number.
Incorrect:
With Me .BorderStyle = 1 .WindowState = 0 .ScaleMode = 3 .DrawMode = 13End With
Correct:
With Me .BorderStyle = vbFixedSingle .WindowState = vbNormal .ScaleMode = vbPixels .DrawMode = vbCopyPenEnd With
Even developers who truly believe in enumerations sometimes miss the opportunity to use them. As you develop code, you might not always think about creating an enumeration because an enumeration might seem like overkill in certain situations. In general, whenever a procedure accepts a limited set of values, use an enumeration. For instance, if you have a procedure in which a parameter can use one of two values only, that parameter is a prime candidate for an enumeration.
Creating an enumeration for two values might seem excessive, but it's not. You still get the benefits of avoiding magic numbers, including reduced data entry and greater legibility. Also, if you decide to add members in the future, an enumeration will make it easier to do so. Whether the values are strings or numbers is irrelevant; you can benefit from using an enumeration in both situations.
Incorrect:
Public Sub ShowAVIFile(lngType As Long)
Correct:
Public Enum tpsAVIFile tpsFileCopy = 0 tpsFileDelete = 1 tpsFileDeleteToRecycle = 2 tpsFileNuke = 3 tpsFindComputer = 4 tpsFindFile = 5 tpsFileMove = 6 tpsSearch = 7End EnumPublic Sub ShowAVIFile(lngType As tpsAVIFile)
You must validate any value passed to a parameter declared as an enumerated type to ensure that it is acceptable. When a parameter is declared as an enumerated type, it's really a long integer with a fancy code helper drop-down list. While other developers should use the named enumeration members, they are free to pass the parameter any valid long integer. Unfortunately, Visual Basic does not have the capability to automatically require that parameters be valid members of the enumeration. I hope this is added someday; it would greatly reduce the amount of code you have to write when you use many different enumerations.
There are essentially two methods you can use to validate the data:
In general, unless you are validating that the value falls within an acceptable range, use the Select Case construct rather than If...End If. The Select Case construct gives you more flexibility if you need to add more values to the enumeration later.
Making assumptions is one of the leading causes of errors in code. Visual Basic won't ensure that values passed to an enumerated type actually correspond to named members within the enumeration. Never assume you have good data.
5.8.1 Always validate data by using comparisons to the named members, not to magic numbers. Refrain from using magic numbers for data validation, just as you refrain from using magic numbers elsewhere in your code.
Incorrect:
Public Enum tpsPrintDestination tpsScreen = 0 tpsPrinter = 1End EnumPublic Sub PrintReport(ByVal strFileName As String, _ ByVal lngDestination As tpsPrintDestination) '* Verify that a valid location has been specified. If lngDestination < 0 Or lngDestination > 1 Then GoTo PROC_EXIT End If '* Print the specified report. End Sub
Correct:
Public Enum tpsPrintDestination tpsScreen = 0 tpsPrinter = 1End EnumPublic Sub PrintReport(ByVal strFileName As String, _ ByVal lngDestination As tpsPrintDestination) '* Verify that a valid location has been specified. If (lngDestination <> tpsScreen) And _ (lngDestination <> tpsPrinter) Then GoTo PROC_EXIT End If '* Print the specified report. End Sub
5.8.2 Use Select Case to validate that a value is a valid member of a discrete set of values. Don't forget to include the Case Else clause to handle invalid data.
Correct:
Public Sub PrintDocument(lngCallingForm As tpsCallingForm) '* Perform necessary actions based on the calling form. Select Case lngCallingForm Case Is = tpsContactView Case Is = tpsServiceOrderView Case Is = tpsCustomerInventoryView Case Else '* The value passed as the calling form parameter '* is invalid! MsgBox "An incorrect calling form " & _ "has been specified!", vbInformation GoTo PROC_EXIT End SelectEnd Sub
loading...
loading...
loading...
Terms of Use, Copyright, and Privacy Policy
© 1997-2010 Barnesandnoble.com llc




