                                dUFLP/dHUNG
                     Coding Standards and Conventions
                                Version 0.7
                              April 17, 1992


dUFLP -- dBASE Users Function Library Project -- Coding Standards and
Conventions -- Based upon the HUNGARIAN / xBase Conventions by Robert A.
DiFalco. These Standards and Conventions have been defined and generally
agreed upon by several of the 'regulars' on the Borland (once Ashton-Tate)
Bulletin Board System (BORBBS (now defunct)), but are by no means a rigid 
definition.

This file contains modifications to Robert DiFalco's (CIS: 71610,1705)
HUNG standard for X-Base languages; it was developed by members of the
Ashton-Tate/Borland Bulletin Board System to be used in a user-developed
library.  Several aspects of this document have been changed, as the dUFLP
standards are more aimed at dBase than other programming languages, but
have been only slightly modified where needed, and some duplicate
definitions were removed in the variable naming practices. The original
document (HUNG14.ZIP) may be found on the CompuServe dBASE Forum.

The purpose of this document is to define some coding standards to be used
in the library for dUFLP, Please attempt to follow these standards as 
closely as possible when creating Functions and Procedures to be included 
in this library. Thank you ... (most of the text from this point on is 
DiFalco's own words)
---------------------------------------------------------------------------
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.

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 extremely long variable names.
End quote:

In dBase, 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 dBase in general heads 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 (UDF or User-Defined Functions) will be mixed case
beginning with a single Capital letter.

-------------
UDF Name Case
-------------
All User Defined Functions will be mixed case, with no underscores. The
first letter will be upper case, e.g. AllTrim.

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.

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

4. Where possible, express the function or 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

      parameters cMsg

      xSavClr = set( "ATTRIBUTES" )
      set color to rg+/r

      ? cMsg

      set color to xSavClr

   RETURN ""

dBASE native functions shall be typed in all lowercase to delineate them
from non-native functions as in the above call to set(). 


------------------
Reserved Word Case
------------------
Except for the reserved words 'FUNCTION', 'PROCEDURE', and 'RETURN', all
dBASE reserved words should be lower case.

-----------------------------
File Name and Field Name Case
-----------------------------
All reference to DOS files (e.g. .dbf, .fmt, .frg, etc.) and field
names are to be in upper case.  Underscores are allowed.

------------
Case Summary
------------
all lower                 : built-in commands and functions
mIxed, fIrst lEtTer lOWer : memvars
MiXed, First LetTer UpPer : UDFs
ALL UPPER                 : files and fields, and the commands
                            FUNCTION, PROCEDURE, and RETURN

=============================================
DBF and Field related Punctuation Conventions
=============================================
There are some rules noteworthy for DBF, NDX/MDX, 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 dBase's 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 dHUNG 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.NDX
                   HACCTS2.NDX
                   HACCTS3.NDX

   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 dHUNG 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 
   set index to HCUST1, HCUST2, HCUST3

   cLName = "DiFalco"

   seek cLName

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

   close database

RETURN ""

( 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 designed system. Variable names must give the
most amount of information possible in its name while using the minimum
number of characters possible.

All memory variables (memvars) are mixed case names, consisting of 1-10
alphanumeric characters.  The first character is always a lower case
type prefix.  Underscores are only used as scope prefixes.  Memvar names
should not repeat type prefix information.

But memvars may 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 type prefix is the first character of a variable that represents the
type the programmer intends for the variable.  Below is the list of
dBASE-specific type prefixes together with examples:

             Prefix          Type          Example
             ------          ----          -------
                a            Array         aList
                c            Character     cFName
                d            Date          dPmtDue
                f            Float         fAngle
                l            Logical       lExitMenu
                m            Menu          mMain
                n            Numeric       nHours
                p            Pad           pOpenDbf
                s            Screen        sBackgrnd
                u            popUp         uFlds
                w            Window        wError
                x            undefined     xLookUp

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

n = 0
do while n < nFldMax
   n = n + 1
   aFldName[n] = Field( n )
enddo

--------------
Scope Prefixes
--------------
In dBASE, a variable can be either local to a procedure or global to all
procedures.  This distinction is represented by the scope prefix.
Variables that are global are represented by an underscore after the
type prefix; variables that are local to a procedure have a null scope
prefix.  For example, c_DbfFile is a character variable that is global;
cDbfFile would be the same variable if it was local.

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

--------------------------------
Sample "Standard Qualifier" tags
--------------------------------
Attr - Attribute
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
Ndx  - of or pertaining to an Index ( or Mdx )
Rec  - Record Number
Ret  - Return value ( lRet = .f. )
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
   cNdxFile - 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 Designed and Well Designed 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 - could also be called nCount.
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 an underscore
                        instead of using the UpperLower combination.
SaveScreenA sSav1       No Type Prefix, needless use of characters. The
SaveScreenB sSav2       alphabetical reference is allowable though I prefer
SaveScreenC sSav3       to use a numeric reference. Use of 's' type prefix
                        removes need to use Scrn or sScreen.
ColorStr    xClr        No Type Prefix. Needless use of characters. This 
                        shows the usage of 'unknown' type with the Type Prefix
                        'x' (colors are character strings in specific
                        formats, but do not require a special type).
nRecNo      nRec        The use of "No" is redundant.
PrintReset  xPrnReset   Also could have been shortened to cPrnRst.
MessageStr  cMsg        These are starting to become obvious, don't you
                        think?

======================
Standard Header Format
======================
Below is the recommended header format to be used for procedures/functions.
This will allow the automated maintenance of library functions as well
as documenting the routine.  By using this header, it will make it
possible to create a routine either in dBASE or some other software that
can generate a library listing, giving the pertinent information. Please
also note EoF/EoP comment at the END of the function or procedure.

FUNCTION AllTrim && {ver 0.8}
*--------------------------------------------------------------------------
*-- Programmer..: HazMatZak
*-- Date........: 07/02/1991
*-- Notes.......: Used to remove leading and trailing blanks from
*--               a string.
*-- Written for.: dBASE IV, 1.1
*-- Rev. History: 05/23/1991 0.1 - Original version (CLW)
*--               06/18/1991 0.2 - Revision to modify for dHUNG
*--               06/19/1991 0.3 - Revised for ...
*--               06/24/1991 0.4 - Revised for ...
*--               06/25/1991 0.5 - Revised again by Ken Mayer
*--                                to give smaller header ...
*--               etc.
*-- Calls.......: None
*-- Called by...: Any
*-- Usage.......: AllTrim(<cArg>)
*-- Example.....: ? AllTrim("  Test string  ")
*-- Returns.....: String to be trimmed (i.e.:"Test string")
*-- Parameters..: cArg = String to be trimmed
*--------------------------------------------------------------------------
       
   parameters cArg

RETURN ltrim(rtrim(cArg))
*-- EoF: AllTrim()

-------------
Documentation
-------------
It is always a good idea to document code -- never assume you will be the
only programmer to read your code. If it is being posted on CompuServe, a
lot of people may download it. If they wish to understand what you are
doing, or use just portions of your code, it is very useful to explain in
at least some detail what your program/function/procedure is doing. We are
not going to suggest more than attempt to make the documentation neat,
concise, and to the point (don't ramble).

----------------------
dHUNG Revision History
----------------------
1991-05-23  0.1  Initial revision (clw)
1991-06-18  0.2  Revision after notations vote (clw)
1991-06-19  0.3  Memvars, Files, Fields, UDFs, Case Summary (HazMatZak)
1991-08-20  0.4  Added official header example (clw)
1991-08-26  0.5  Combined original DiFalco document (HUNG14.ZIP) with CLW's
                 dHUNG documentation, and the header information
                 (KenMayer).
1991-08-30  0.6  Minor corrections to make this dBASE specific (KenMayer).
1992-04-16  0.7  Minor corrections to make this 'Politically Correct'.
                 (Ken Mayer (KenMayer))
