PowerBASIC Naming Conventions |
Hungarian Notation, albeit largely misunderstood and frequently misapplied,
was all the rage for quite some time. It features a lowercase
type-identifier prefix for a variable name
(lpstHungarianVariable
). LowerCamelCase features capitalization
of words inside the var name (thisIsLowerCamelCase
), and UpperCamelCase
(aka PascalCase) capitalizes the first word as well
(ThisIsPascalCase
). Other protocols have sprung up, including the
vomitous StudlyCase, which permits an indiscriminate mixture
(sTuDlycAsetExTloOksLiKetHiS
).
I personally loathe the look and feel of Hungarian Notation. The very act of reading the code turns my brain a dull brown. Unfortunately, all of the helpful .INC files bundled with PowerBASIC are riddled with it; so when I must consult one of those references, I make sure to have my antacid tablets handy. Nowadays, hungArianNotation is officially discouraged for use in the .NET world. The important message here, though, is that if any one method were clearly superior, there would not be such controversy.
Hungarian Notation and its derivatives admittedly can be useful in a production environment, where there must be a consensus understanding among the project programmers. Many coders, however, are of the opinion that if a variable name is sufficiently descriptive, then it doesn't need any help; I am in that camp. Since I don't work for The Man, the only programmer I need to please is myself. I trust that there are other PowerBASIC aficionados working solo as well, who don't need incessant reminders as to what a certain variable is doing. We created them, and we usually know why.
That having been said, sometimes months or even years do pass by without perusing
a certain piece of code, and one cannot be expected to remember everything; so some
sort of sensible naming protocols are in order. My preferences most closely
resemble PascalCase, but with variations. To me, beginning a variable name with
a lowercase letter is an unnatural act, analogous to going outside wearing a sport
coat and tie, but no pants — something just isn't right. On top of
that, I'm not a fan of underscores either; so I avoid them except for one specific
purpose. In the GW-BASIC days, periods could be used to delimit variable
names; but now they can be applied only in User Defined Types, which actually is a
good recommendation for using those constructs.
I would share some general guidelines that work for me, and perhaps a couple of
these ideas will interest you as well. It is a hybrid system that strives to
make variable names as self-explanatory as can reasonably be accomplished
without making them too long or ugly. Some capitalization is employed
dynamically — that is, not according to a hard-and-fast rule,
but determined by the logic of the situation, and always with both the readability
and specific function of the code in mind. Sometimes a name will be prefixed
with identifying caps, sometimes there will be a suffix, and occasionally a
middle-fix is most useful. The included examples will explain.
For lack of a better name, I could call my system LogicalCase. If that seems pretentious, how about MeaningfulCaps? Or perhaps DynamicCase? I like that last one; it sounds better than Mullerian Notation.
FUNCTIONS and SUBS Setup() ValidateUser() GetMonthlyTotal()
Subroutines tend to be named with verbs; that way, they read like English
in the code without the use of the optional CALL keyword.
I do use CALL with Subs named as nouns, such as ProgramSetup.
Functions themselves tend to be called in-line, making them more or less
self-evidencing as well.
For multiple-word SUB names, middle-fixing can be the most useful option:
ReadONEname ReadALLnames GetBINfromDATA GetDATAfromBIN
By concentrating on the caps, one almost doesn't even need to read the rest.
STRING VARS A$ Event$ CurrentUser$ Month$()
Although such usage is optional, all string variables are suffixed with a dollar
sign ($), making their type self-documenting. If there is no dollar
sign, then it is not a string variable. BASIC users are ahead of the game in this
regard.
LABELS Skip_Loop: Start_: Re_Do:
All labels, and only labels, contain an underscore character, making them
self-documenting as well.
FLAGS BadFileF ValidDateF MissingF ColorPrintingF
I use a lot of Boolean flags, mostly global, because they are so bloody useful.
Most are postfixed with an F, which is reserved for flags.
There are a few self-evident exceptions:
Yes No True False ESC
COLORS FGDc BKGDc TEXTc LINEc
I have gotten into the habit of using all uppercase for these and certain other
variable classes. In these cases, the trailing type-suffix stands out
for what it is as a lowercase letter. Reversing the cases also could work,
if one preferred these:
FgdC BkgdC TextC LineC
FONTS and POINT SIZES FTdata$ FTinfo$ PSevent$ PSdate$
These are prefixed with the obvious mnemonic. One might prefer to postfix these names, but I think they are more readable this way.
SCREEN COORDINATES BoxX BoxY BoxW BoxH
In the context of screen formatting, certain variable names always reference specific things:
X column
Y row
W width
H height
Some other standard PREfixes
TM Timer function
FN Function call, which could be a macro
PTR Pointer
Some other standard PostFIXES
X Bit array of binary data
CT Item or loop counter
OPT Option of some kind
L,R Left, Right
Some other standard Either-OR
TOT Totals
ScoreTOT TOTstudies
MAX,MIN Maximum or minimum value
MINlevel DataMAXvalue
Using very short variable names is highly useful; a good idea, however, is to tend to employ any particular one in a very limited number of contexts, so that it can be easily recognized as such.
SOME SHORT NAMES
A$,AA$ Workhorse characters, Text input
C Color
E Error processing
F$,FF$ File I/O
J,K,JJ,KK ForLoop counters
L,R Left & Right
M,M1,M2 Margin tabs
N Number
P Pointer, screen Position
Q$ String manipulation
R Random, Row
T,TT,TOT Time, Total
W,H,WW,HH Width & Height
X,Y Printer/Screen coordinates, Formulas
ZM Formulas
OP Option
RW,CM Row & Column
XX,YYM Printer/Screen coordinates
I also never pass a single-letter variable as a parameter. They always are treated as local variables, even though they now can be defined as globals safely (and most conveniently).
Adopt your own rules!