----------------------------------- 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( , ) --> 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( , ) --> 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 against the string "EDIT". We know 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 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