-----------------------------------
                 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