                  -----------------------------------
                  xBase Identifier Naming Conventions

                                 -or-

                              H  U  N  G
                   Hungarian types without the arian
                  -----------------------------------
                  Robert A. DiFalco        71610,1705
                  -----------------------------------
                  Revision                       1.02
                  -----------------------------------


Let me start off by stating that these are only my opinions on naming
conventions for xBase programming. In my opinion these methods are
extensible to C, ASM, BASIC and just about any other programming
language. It looks very similar to Hungarian notation as outlined by
Charles Simonyi of Microsoft Corporation. Don't be fooled, however, this is
much different. I find it more intuitive and logical though that may
pertain only to my thinking. Also, this naming convention was not
thought up by myself but rather is a bastardization of the Clipper
recomended naming conventions and conventions used by many of the
programmers I know. Charles Simonyi's original paper can be found in MSSYS
forum on CIS in library 10 under the name of HNGRN.ZIP and should be read
for reference.


These conventions take in the same factors as outlined by Charles Simonyi
for creating names in a program. The factors listed below are directly
quoted from his monograph.

Begin quote:

1. Mnemonic value   - so that the programmer can remember the name.

2. Suggestive value - so that others can read the code easily.

3. "Consistency"    - this is often viewed as an aesthetic idea, yet it
                      also has to do with the information efficiency of the
                      program text. Roughly speaking, we want similar names
                      for similar quantities.

4. Speed of decision- we cannot spend too much time pondering the name of a
                      single quantity, nor is there time for typing and
                      editing extremly long variable names.

End quote:

In xBase, our variable names have even a more pressing reason for short
identifiers since we only have 10 characters to work with. To alleviate
using needless characters, we will use lowerUpper combinations instead of
dividing underscores.


Procedure/Function Naming conventions
=====================================
Procedures and Functions will be heretofore called "Functions". Function
names will not be "typed" as variables. As xBase and languages in general
head towards object oriented approaches it is important to allow our
Functions to return multiple types. This negates the approach of typing
Functions by return variable type. Instead we will apply a "loose" set of
rules to Functions. Native language functions will be in all lowercase
while 3rd party or "home grown" functions will be mixed case beginning
with a single Capital letter.

1. Functions will start with a capital letter followed by lower case
   letters thus distinguishing them from variables. If the Function name
   can be better expressed by two or three identifiers an UpperLower
   combination will be used rather than underscores to delimit identifiers.
   Consider the following Examples:

   ClrSet()    - Sets colors
   SaveGets()  - Saves active get list
   PrnScr()    - Prints the screen
   GetPass()   - Gets a password
   Choose()    - Menu of items to "choose" from

2. Conversion Functions will start with the value they take and end with
   converted value separated by the number 2. Some examples would be as
   follows:

   Str2Arr()  - Changes a string to an array.
   Hex2Dec()  - Changes a Hex string into a decimal numeric.
   Clr2Attr() - Changes a color string to an integer attribute.
   Dbf2Arr()  - Loads a DBF into an array.

3. Where possible, use standard qualifiers as outlined in the section
   dedicated to "Variable Naming Conventions". A few examples follow.

   Clr  - Color
   Scr  - Screen
   Crs  - Cursor
   Max  - Maximum value
   Min  - Minimum value
   Str  - String
   Fld  - Field
   Prn  - Print

4. Where possible, express the @function of procedure in less than three
   qualifiers ( names ). Refer to the examples given for Rule 1.

5. The keywords PROCEDURE, FUNCTION and RETURN shall be in all uppercase.

   FUNCTION SayStr( cMsg, cClr )
      local cSavClr := setcolor( cClr )

      ? cMsg
      setcolor( cSavClr )

   RETURN NIL

Language native functions shall be typed in all lowercase to delineate them
from non-native functions as in the above call to setcolor(). The exception
to this is Object oriented export instance variables which will employ the
lowerUpper notation standard as used by OOP languages such as SmallTalk.

oBrowse:addColumn( oColumn )
        ^  ^
        |  Upper case First letter
        Lower case first tag name


DBF and Field related Punctuation Conventions
=============================================
There are some rules noteworthy for DBF, NTX, ALIAS and FIELD operations to
delineate them from Functions and Variables. FIELD names will NOT be typed
by a lowercase type identifier as with Variables.

1. Database and Index files, as well as Field names will always be expressed
   in capital letters. As xBase languages main point of existence is the
   manipulation of DataFiles, this will make them stand out against
   variables and other qualifiers.

2. Where possible they will use the same standard qualifiers used for
   Variables and Functions. See the examples for Rule 3 of
   "Procedure/Function Naming Conventions".

3. Fields will be referenced by an ALIAS. Consider the following.

   HACCT->ACCNUM
   HCONST->PASSWORD
   HCONST->COMPANY

4. Variables referencing Fields will have the same name as the Field with
   the addition of the HUNG type prefix.

   cFName   := HCUST->FNAME
   cLName   := HCUST->LNAME
   cAddr    := HCUST->ADDR
   nAge     := HCUST->AGE
   lActive  := HCUST->ACTIVE
   nBalance := HLOAN->BALANCE

   ( Please note that the storage operators ( "=" ) are lined up for easy
     reading giving a table appearance. )

5. With regard to DBF file names, data, index or otherwise they should
   all begin with a common prefix and that prefix is similar to the
   name.

   This insures that I have few naming conflicts with other systems
   that may reside on the computer and just about guarantees I can
   separate my files out if they get placed into a common subdirectory.

6. Index filenames should reflect the file that they belong to but
   should not attempt to indicate what the index expression is.  A
   much cleaner routine results when index files are simply numbered.

   HACCTS.DBF ---> HACCTS1.NTX
                   HACCTS2.NTX
                   HACCTS3.NTX

   Internally the only information I am required to keep is the index key
   in an array and all indexes can be rebuilt in the order of their
   respective suffix number.


Command Punctuation Conventions
===============================
This area of my HUNG naming conventions will probably meet with the most
opposition. User Defined Commands will use descriptive names as outlined in
"Procedure/Function Naming Conventions".  User Defined or not, Commands
will have one Rule.

1. All Commands will be typed with lower case letters.

The reasons for this are simple. This will delineate commands from
variables, functions and DBF elements. Consider the following examples.

FUNCTION CmdExample

   use HCUST new
   set index to HCUST1, HCUST2, HCUST3

   cLName := "DiFalco"

   seek cLName

   HCUST->AGE    := 28
   HCUST->ACTIVE := .t.
   HCUST->LNAME  := cLName

   close HCUST

RETURN NIL

( Please take note that in replace statements we also line up the "with"
  portion of the command as we do storage operators. )


Variable Naming Conventions
===========================
This is the heart of a well HUNG system. Variable names must give the
most amount of information possible in its name while using the minimum
number of characters possible.

Variables will have one mandatory character, the "Type Prefix". But will
usually have a combination of tags that will in most cases appear in this
order.

1. A single lower case variable defining its type as returned by a Type()
   function called a "Type Prefix".

2. An Optional state called a "State Qualifier"

3. A "Standard Qualifier Tag".

4. An Optional "Pointer Reference".


Type Prefixes
-------------
a  - Array
b  - Code Block
c  - Character
d  - Date
h  - Handle
l  - Logical
n  - Numeric ( nX is optional where X is the number of decimal places )
o  - Object
v  - having a Variable type as in a macro or changing value

For temporary variables of distinct type or pointers this single prefix can
be used by itself. Consider this example.

for n := 1 to nFldMax
   aFldName % [n] := Field( n )
next


Sample "State Qualifiers"
-------------------------
New  - a New state
Sav  - a Saved state
Tem  - a Temporary state


Sample "Standard Qualifier" tags
--------------------------------
Attr - Attribute
Ar   - Array
Clr  - Color
Crs  - Cursor
Dbf  - of or pertaining to a DBF
F    - First as in cFName
File - Any type of file
Fld  - Field
L    - Last as in cLName
Msg  - Message
Name - a name
Ntx  - of or pertaining to an Index ( or Idx|Mdx|Ndx etc. )
Rec  - Record Number
Ret  - Return value ( lRet := .f. )
Scr  - Screen
Str  - String
T    - Top
L    - Left
B    - Bottom
R    - Right
Row  - Row
Col  - Column
X    - Row
Y    - Column

Please note that Standard Qualifiers can be used in combinations as in the
following examples.

   nTRow    - Top Row
   cFName   - First name
   cDbfFile - a Database file
   cNtxFile - an Index File

Sample "Pointer References"
---------------------------
1,2,3 - State pointer references as in cSavClr1, cSavClr2, etc.
Max   - Strict upper limit as in nFldMax, maximum number of Fields
Min   - Strict lower limit as in nRecMin, minimum number of Records


These lists are to serve as samples and building blocks. They can and
should be added to. Lets look at a few examples of the conventions at work.
This should dispel the myth that notation conventions cannot be applied to
variables with a 10 character maximum length.


Poorly HUNG and well HUNG Examples
----------------------------------

WRONG       RIGHT       WHY
==========  ==========  ===============================================
nFldNum     nFld        Number is indicated by the Type Prefix making the
                        word Num redundant and a needless use of character
                        space.
Count       n           n serves as a temporary count index. Count has no
                        Type Prefix.
Last_Name   cLName      This is one of the most horrendous mistakes. First
                        we do not specify the variable type. Second we
                        needlessly spell out LAST and worst of all we use
                        up a precious character by using and underscore
                        instead of using the upperLower combination.
SaveScreenA cSavScr1    No Type Prefix, needless use of characters. The
SaveScreenB cSavScr2    alphabetical reference is allowable though I prefer
SaveScreenC cSavScr3    to use a numeric reference.

ColorStr    cClr        No Type Prefix. Needless use of characters. Colors
                        are indicated as a string by the Type Prefix.
nRecNo      nRec        The use of "No" is redundant.

PrintReset  cPrnReset   Also could have been shortened to cPrnRst.

MessageStr  cMsg        These are starting to become obvious, don't you
                        think?


Lets take a look at how a function can be rewritten using the HUNG
conventions for xBase. Examine this Function closely. Variables, Commands
and Function name do not conform to "Well Hung" coding techniques. This
Function has been written in Clipper and is actually a Sample program
slightly modified. Those of you that do not understand Clipper should still
be able to see the benefits.


/***
*  LISTASARRY( <list_str>, <delimiter> ) --> str_array
*  Convert a delimited string to an array
*
*/
FUNCTION LISTASARRAY( list_str, delimiter )
   LOCAL position
   LOCAL str_array := {}         // Define an empty array to return

   IF delimiter = NIL
      delimiter := ","
   ENDIF
   DO WHILE !EMPTY(position := AT(delimiter, list_str))
      * ..... Add a new element
      AADD(str_array, SUBSTR(list_str, 1, position - 1))
      list_str := SUBSTR(list_str, position + 1)
   ENDDO
   AADD( str_array, list_str )   // Add final element
   RETURN str_array              // Return the array


Now take a look at the properely formatted equivelant.

/***
*  Str2Arr( <cStr>, <cDelim> ) --> aRet
*  Convert a delimited string to an array
*
*/
FUNCTION Str2Arr( cStr, cDelim )
   local nPos
   local aRet := {}     // Define an empty array
                        // fill and return.
   if cDelim == NIL
      cDelim := ","
   endif

   do while !empty( nPos := at( cDelim, cStr ) )
      * ..... Add a new element
      aadd( aRet, substr( cStr, 1, nPos - 1 ) )
      cStr := substr( cStr, nPos + 1 )

   enddo

   aadd( aRet, cStr )   // Add final element

RETURN aRet             // Return the array


DEBUGGING EXAMPLES
==================
Hung Notation allows us to readily see errors in our routines that might
otherwise take quite a bit of hunting around.

Why does this snippet of code bomb?

* Begin Fragment

IF type == "EDIT"
   LOOP
ENDIF

DO WHILE MONTH == 9

* End Fragment

Are you able to tell me? Ofcourse not, we are not given enough information.
If we had used Hung Notation, however, the error would have been obvious.

* Begin Fragment

if nType == "EDIT"
   loop
endif

do while cMonth == 9

* End Fragment

Ahh, now we are getting somewhere. The program has TWO errors. It is trying
to evaluate the numeric <nType> against the string "EDIT". We know <nType>
is a numeric because of its Type Prefix. Look a little farther and we can
see the exact reverse of the error with the character <cMonth> being
evaluated against a numeric constant 9.


This paper is by no means comprehensive but should still be able to guide
a programmer towards a standard Typing Convention for xBase. I realize that
this is not for everyone but find it to be a productive method for myself.
If you have any questions or additions please respond to me on the DBA
forum at my COMPUSERVE ID# listed at the top of these Txt file.


Robert A. Difalco
Fresh Technologies

Special Thanks to Tom Leylan and Matt Maier


Revision History:

11/30/90  1.00  Original Draft
12/05/90  1.01  Changed Database Standards
12/10/90  1.02  Added some Clipper specific examples
12/13/90  1.03  Added special handling for exported instance variables


