Neil Obremski's Coding Convention
Last Updated: 31 MAR 2001
Contents: Introduction
Variable Notation
Function Notation
Source Files
Comments


Introduction: I clipped this out of the Seed Engine specification. Not only was it taking up space, but these are conventions that I stick to for almost any project in any language, not just the Seed Engine.

Because of minor differences in languages, some things are altered slightly. There are two instances where changes occur: commments and special casing since some languages are case insensitive (like BASIC) and do not always preserve it. Luckily, I do most of my coding in C, C++, JavaScript, or PHP which are all a lot alike in terms of source code.

This doesn't yet include the following things:

  • macro naming convention
  • standardized object comment
I haven't completely combed this to remove mentions of the Seed Engine, so dismiss them as you see them.


Variable Notation: To name variables, I use what I call Bastardized Hungarian Notation; compliments to my friend Dave M., whom I worked with at Microsoft, for the name. Hungarian Notation is a way to label variables so that their type and purpose is contained in within their name. It makes it easy when looking at code to already know what a variable is or what it's supposed to be doing without searching for the declaration or places it's used.

I'm not the only one who uses a slaughtered version of the true Hungarian Notation, because it (IMHO) is a complete bitch and waste of time. It requires you to tack on an extra four or more characters and the result is far more detailed than I require. Plus the type is usually bound to the name so if you need to change the type (and keep the purpose the same) you have to change the name as well. My version adds only a small prefix, usually one character, to the name. The prefix is all lower-case and then the rest of the name is intelligently capitalized.

There are three levels of prefix and they determine the order in which they are used, not necessarily what they are for. The first level of prefix is for the scope of the variable. This added if the scope is static or global. Unlike other notations, I do not add a prefix to member variables of any object (or class), since members already (under my standards) have to be preceded by a pointer to the current object ('this' in C++ and 'pThis' in C). Level one prefixes are also dependent on the implementation they are used in. Lastly, this prefix is used in local, member, and parameter values when they are constant. Global and static constants are considered high-level macros and not noted in the same way.

prefixmeaning
g_global
s_static
c_constant local/member/parameter

The second level of prefix is what the value of the variable is: address of another variable, array of variables, or an actual value. If this represents an address and it is to an object variable then this prefix becomes third level.

prefixmeaning
ppointer
aarray

Lastly below are the third level prefixes. These signify the variable type:

prefixmeaning
ppointer
oobject
iinteger (whole number)
nreal number (floating point)
ppointer
fflag (true/false)
sstring
csingle character
aarray

My reasoning was to keep it fast, simple, and independent of the variable's actual type. Rather, I use it mainly as a reference in how the variable should be used and what kind of data it contains. For example, if I use a char for counting rather than storing an ASCII character, I will prefix it with i; because I'm using it as a whole number. Likewise, if I was using an unsigned short to store a Unicode character, I would prefix it with c.

Some variables I consider almost globally understood just by their names. So these variables I keep all lower-case and I don't add a prefix. There may be more than what I list here, but ...

namemeaning
iindex/integer variable
x,y,zcoordinates
j,klooping index (if 'i' is taken)
rs[pointer to] RecordSet object

I must admit that since starting this convention it has been a lot less painful to come back to months-old code and stir it up. Previously, I really only had the third-level prefixes worked out and that's all I used. Pointers and arrays were part of that list and I rarely had globals or statics. But as I used it more and more, I realized I'd need to seperate simply pointers from pointers to some type of variable.

Another advantage of using this notation is that you are almost always guaranteed not to conflict with global variables from other libraries.


Function Notation: I use two different styles of function styling depending on circumstance. For functions that affect properties of an object, I have recently adopted actionName. In this setup the action is what is happening and the Name is what is being affected. Typically the action will be one of the following:

actionmeaning
getreturns value of property
setsets the value of property
clr/resetclears the property to it's default value

Each "word" in the function name is intelligently capitalized. Functions that are more process than property do not prepend a lower-case action name. When building member functions in C, they are always preceded by the lower-cased object name, or an abbreviated version of it, followed by an underscore and then using the notation I have previously described:

obj_getValue()

I keep the beginning words lower-cased, because I like the visual emphasis on the function, not the object or action. That is secondary.


Source Files: All source files are written to be readable at 78 columns with 4-space tabs. Lines longer than 78 columns are assumed to be intelligently word-wrapped (as done with TextPad or not at all.

The document always contains a block comment acting as a header. It looks like so:

/*************************************************************[viewing notes]*

    [dir/file.ext] Title and/or Summary
    By Original Author

    Extra information: additional contributes, legal disclaimer, notes,
    history, contact info, etc.

*****************************************************************************/

Comment Convention: My commenting convention is designed so that languages with either single-line or block comments are usable without a lot of modification. Mostly it caters to C++ and JavaScript where I originated it.

The different comments I used can be broken down into the following types:
Scrap Comments:

There are some comments that follow no pattern and are extremely scattered. You'll usually find them for one of two reasons:
  1. to "de-activate" some code
  2. make a note of something that needs to be changed
Major Comments:

These come at points in the code where things really need to be explained. Major comments are just huge blocks with lots of text. One major comment you already know of is at the beginning of each file (see Document Convention).

Major comments are just surrounded by two horizontal lines made of asterisks (to go along with C's block identifiers /* and */):

/*****************************************************************************

    text

*****************************************************************************/
Minor Comments:

Usually next to variable declarations, they are always aligned to the right of the code. They can start at any tab stop, but they almost always line up with others around them. If more space is needed, a blank code line is made followed by the additonal commenting:

some code;                                  // blah blah blah blah blah ...
                                            // ... blah blah blah blah     
In C, there is no single-line comment. In this case, the end comment symbol is placed to end exactly at column 78 (this works out perfectly with four-space tabs):

                                                                     column 78
                                                                             |
                                                                             V
some code;                                  /* blah blah blah blah blah ... */
                                            /* ... blah blah blah blah      */

Section Comments:

Section comments are used to split code into sections. A section is a line or more of code that can be summed up in one comment. These are sectioned out to quickly "flip" to particular parts of the code. These use a title space, flush left, surrounded by a line of either dashes (minus signs) or underscores:

//_[title and/or summary]_____________________________________________________
In C:

/*_[title and/or summary]___________________________________________________*/
If a description is needed, it appears below this. The line does not end with */ and the left edge is bordered using '//'; except the last line which ends the block comment:

//_[title and/or summary]_____________________________________________________
//
// description
//
And in C:

/*_[title and/or summary]_____________________________________________________
//
// description
*/
Sometimes there is a vertical space between the title line and the first line of the description to match the trailing one at the end. This is simply for aesthetic reasons and I don't always do it. These comments are always on the same starting column as the current block of code. The first two indentations from the far left edge use underscores, while anything beyond that use dashes. This allows quick identification of major versus minor sections.

Function Comments:

When, in the code, the implementation (not declaration) of a function occurs, there will be a function comment. This is just a Section Comment with additional restrictions. It follows this syntax:


//_[object::function]__________________________________________(contributors)_
//
// DESCRIPTION:
//  summary of function
//
// PARAMETERS:
//  name .................. description of parameter
//
// RETURN VALUE (type):
//  description of return value or just "See description"
//
If contributors is blank then it is assumed that the original author (as mentioned in the document header) wrote and has completely maintained the function.