Skip to topic | Skip to bottom
Home
TModeling
TModeling.NamingConventionsr1.1 - 26 Jun 2008 - 16:51 - Main.guesttopic end

Start of topic | Skip to actions
Naming Conventions
Adapted from the book "Code Complete 2.0", chapter 11

Naming Conventions

Why Have Conventions?

Often having a convention is better than having no convention even though the convention may be totally arbitrary
  • Take more for granted, making a global decision once rather than many local decisions each time you code, this allows you to focus on the code not the naming
  • Increases Knowledge Transfer, similarities in naming makes it easer to figure out unfamilar code based on the familar conventions
  • Learn code faster, only have to learn global conventions rather than figure out that Shawn's code looks like this, Martin's code looks like that, and Jack's code looks like this...
  • Reduces Name proliferation, pointTotal vs. totalPoints, a convention says always do it one way. Code with both is very confusing and harder to maintain correctly.
  • Differentiate Special Types, quickly differentiate between constants and enumerated types, differentiate between local, class members, and global data based on naming alone

Language-Independent Conventions

  • Differentiate between variable names and routine names
  • Differentiate between classes and objects
  • Identify global variables
  • Identify member variables
  • Identify type definitions
  • Identify named constants
  • Identify enumerated types
  • Identify routine parameters (input vs. output)
  • Format names to enhance readability

Typical 'C' Conventions

  • c and ch are character variables
  • i, j, and k are loop indices and/or array indices
  • n is a number of something
  • p is a pointer
  • s is a string
  • Macros are in ALL_CAPS,
  • TypeDefs are often in ALL_CAPS as well
  • variable and routine names are all_lowercase
  • The underscore (_) character is used as a separator. letters_in_lowercase is more readable than lettersinlowercase.

Typical 'C++' Conventions

  • i, j, and k are loop indices and/or array indices
  • p is a pointer
  • Constants, Typedefs, and Macros are in ALL_CAPS
  • Class and other type names are in MixedUpperAndLowerCase().
  • Variable and function names use lowercase for the first word, with the first letter of each following word capitalized
   int variableName;
   bool routineComputesName();
  • The underscore is not used as a separator within names, except for Constants, TypeDefs, and Macros and for certain types of prefixs (globals, consts, and member fields)

TMV Conventions:

BUGBUG - This still needs to be finalized by Jack

Here is one possible suggestion. These suggestions are meant to be changed until we have the final version

All names should be meaningful, IE they refer to the problem space (what) not the solution space (how).

Class Name

Class names are Mixed uppercase and lowercase with an initial capital letter. Common classes should belong to the TMV namespace. Classes involving Streaming should be prefixed with the appropriate abbreviation (SP, SM, SL, SV). This also includes Templatized classes.
   // begin TMV namespace
   namespace TMV {

   /*--------------------------
     Class:  CommandLineParams
     ...
   --------------------------*/

   class CommandLineParams {
      ...
   };    
 
   // end TMV namespace
   }
   

Type Definitions

Type Definitions, use mixes upper and lowercase with an initial capital letter.

Enumerated Types

Enumerated Types, same as Type Definitions for actual type definition, indivual enumerations should always use all uppercase, with the use of the underscore as a seperator between words. individual entries should always be stated in plural form where that makes sense.
   // State Flags
   enum FilterState {
     FS_WRITE_CELL   = 0x0001,
     FS_COPY_COUNTS   = 0x0010,
     FS_COPY_COMMENTS   = 0x0020,
     FS_COPY_BOUNDS   = 0x0040,
     FS_DEFAULT_STATE   = (FS_WRITE_CELL | FS_COPY_COUNTS | FS_COPY_COMMENTS | FS_COPY_BOUNDS)
  };

Base Enumerated Types

Base enumerated types, same as above, but they should always be prefexed with a base menonmic for their base type stated in the singular
   enum Colors {
      COLOR_RED = 0xFF0000,
      COLOR_GREEN = 0x00FF00,
      COLOR_BLUE = 0x0000FF,
      ...
   };

Local Variables

Local variables are in mixed uppercase and lowercase with an initial lowercase letter. The name should be meaningful to represent the underlying concept. The length should be between 8-20 characters. With the exception of for loop indices / array indices and for 3D positions. The underlying datatype / datastructure should not be built into the name (avoid hungarian notation)

Routine Parameters

Routine parameters are formatted the same as local variables Each routine parameter should have a comment indicating whether it is input (read only), output (write only) or both (read and write)

Routine Names

Routine names are in mixed uppercase and lowercase The first letter of the first word should be in (uppercase/lowercase)???. stand-a-lone routines involving Streaming should be prefixed with the appropriate abbreviation (SP, SM, SL, SV)

Class Member Variable

Member variables that are available to multiple routines within a class but only within the class, should be prefixed with an 'm_'.
class SP_Filter
   /*-----------------------
     Fields
   -----------------------*/
   SPreader * m_spReader;
   SPwriter * m_spWriter;

   U32 m_state;   // State Flags
   ...
}

Global Variables

Global variables are always prefixed with a 'g_' otherwise they follow the local variable naming convention.
   // Active Vertex Buffer
   static int g_activeVertexBufferAlloc = 1024;
   static TINvertex* g_activeVertexBufferNext = 0;

Constants

Named Constant variables are always prefixed with a 'c_' and then use all capitals for the entire word
   const float c_PI_OVER_12 = 0.261799387799f;

Macros

Macro names are always in all capitals
    // SORT VERTICES BY Y VALUES, breaking ties by x
    #define SWAP(a,b,t) t=a,a=b,b=t
    #define LEXGREATER(a,b) (a[1]>b[1] || (a[1] == b[1] && a[0]>b[0]))


Variable Names

Considerations in Choosing Good Variable Names

A good variable name is appropriate, readable and memorable.
  • Appropriate: A variable name should fully and accurately describe the entity which it represents.
  • Readable: A good variable name is easy to read and doesn't need to be deciphered by referring to other code.
  • Memorable: The variable name should be easy to remember because the name is similar to the underlying concept.

Bad Name Examples

   x = x - xx;
   xxx = fido + SalesTax( fido );
   x = x + LateFee( x1, x )  + xxx;
   x = x + Interest( x1, x );

Better Name Examples

   balance = balance - lastPayment;
   monthlyTotal = newPurchases + SalesTax( newPurchases );
   balance = balance + LateFee( cutomerID, balance ) + monthlyTotal;
   balance = balance + Interest( customerID, balance );

More examples of Good vs. Bad Variable Names

Purpose of Variable Good Names down Bad Names
Current date currrentDate, todaysDate cd, curr, c, x, date
Lines per page linesPerPage lpp, lines, l, x
Running total of checks runningTotal, checkTotal written, ct, checks, CHK_TTL, x, x1
Velocity of a train velocity, trainVelocity, velocityInMPH velt, v, tv, x, train

Note: Don't be afraid to use obvious words. The names currentDate and todaysDate are good names because they fully and accurately describe the idea of "current date". Programmers sometimes overlook using the ordinary words, which is often the easiest naming solution.

Problem Orientation

A good mnmonic name speaks to the problem rather than the solution. A good name tends to express the what more than the how.
   EmployeeRecord * inputRecord;    // Solution Space oriented (how we implement using computer programming)
vs.
   EmployeeRecord * currEmployee;   // Problem space oriented (we are working with employees not inputRecords)

Name Length

The optimum length for variables names is between 8 and 20 characters long. Short names tend to be too terse and not descriptive. longer names tend to take too long to type and also tend to cause layout problems which visually confuses the underlying logical structure.

Too Long:
   numberOfPeopleOnTheUSAOlympicTeam
   numberOfSeatsInTheStadium
   maximumNumberOfPOintsInModernOlympics

Too Short:
   n, np, ntm
   n, ns, nsisd,
   m, mp, max, points

About Right:
   numTeamMembers, teamMemberCount
   numSeatsInStadium, seatCount
   teamPointsMax, pointsRecord

Effect of Scope

Very Short variable names are not always bad. When you give a short a variable a short name like i, it implies that the variable is a temporary value with a limited scope of operation, IE a loop, a few lines of code, one short routine, etc. When you name a variable i, you are saying it's a run-of-the-mill loop counter or array index, and doesn't have any other significance outside the few lines of code in which it is used. Global variables on the other hand should have have good descriptive names as their scope is an entire collection of routines in a file or even the whole program.

Hungarian Notation

A prefixing strategy that used to be very popular at Microsoft and other companies for embedding the data type into the variable name using short terse lowercase prefixes. This approach is no longer needed or useful, pick meaningful names instead.
   // Hungarian Notation
   BTYE byCountBytes;      // 'by' is abbreviation for bytes
   bool bDone;             // 'b' is abbreviation for boolean
   LPTSTR * pszStringPtr;  // 'psz' is abbreviation for 'pointer to a null terminated string'

vs.
   // Normal Style
   BYTE countBytes;
   bool done;
   LPTSTR * stringPtr;

Note: Shawn because of his many years at Microsoft using Hungarian notation, will have problems breaking away from this idiom when programming.

Special Variable Types

One useful remnant from Hungarian notation is the idea of differentiating variable names that are global, constant or member fields (belong to a class interface) from normal variables. This makes it easier to quickly determine their special nature.

Solution #1: Use prefixs to differentiate (Hungarian Notation remnant)

   // Prefix Global variables with 'g_'
   int g_FileReadCount;      // Global Variable for tracking Reads from a File

   // Prefix Constant variables with 'c_'
   float c_PI_OVER_12 = 0.261799387799f;  // Constant representing PI / 12

   // Prefix Class member variables with 'm_'
class CoolStuff {
   int m_classID;         // Unique ID for this instance of the class
   ...
};

Solution #2: Use namespaces (and access rules) to differentiate

   // Declaring global variable
   namespace FileIOSubsytem {
      int FileReadCount;
   }

   // Declaring Constant variable
   namespace MathConstants {
       float PI_OVER_12 = 0.261799387799f;  // Constant representing PI / 12
   }

   // Declaring Class Variables
   class CoolStuff {
      int classID;         // Unique ID for this instance of the class
      ...
   };
      

   // Refering to variables
   FileIOSubsystem::FileReadCount++;

   float calcVal = x * MathConstants::PI_OVER_12;

   return this->m_classID;

   Note:  In solution #2, class member fields should always be accessed via the 'this->' construct to make the member relationship explicit.

Value Qualifiers in Variable Names

Many programs have variables that represent computed values: totals, averages, maximums, etc. If you modify a name with a qualifier like Total, Sum, Average, Max, Min, Record, String, Pointer, etc put the modifier at the end of the name for all variables (post-order) or at the beginning of the name for all variables (pre-order).

   // Post-Order
   int revenueTotal;
   int revenueAverage;
   int revenueMax;

   // Pre-Order
   int totalRevenue;
   int averageRevenue;
   int maxRevenue;

Special Case: The num qualifier by convention and long usage has a special meaning to many industry programmers. Used in pre-order, it refers to a total, used in post-order it refers to an index.

   int numCustomers;   // Total Customers
vs.
   int customerNum;    // number of current customer

Tips:

  • Stay consistent. pick one naming scheme and stick to it throughout your code.
  • Do not use similar names in the same local scope. For Example: Don't use both revenueTotal and totalRevenue in the same routine.
  • Be aware of the special conventions for the num qualifier.

Naming Loop Indices

By longstanding convention, The names i, j, and k by are customary for loop indices. Feel free to use them for short loops. However, if the loop is longer than a few lines, or is a deeply nested set of loops, you are better off giving the index a more meaningful name.

Pros (with i,j,k):

  • Long standing convention, other programmers should immediately know you are using temporary loop variables
  • Simple, easy to remember, and quick to type
Cons (with i,j,k):
  • Cross-Talk: it's easy to forget which is which, typing i when you meant j and vice versa
  • Re-use: it's all to easy to re-use i,j,k for other purposes in the parent routine, breaking the convention and making your code harder to figure out, did you mean i as loop index or i as max item.

   // Acceptable
   for (i = 0; i < teamCount; i++) {
      for (j = 0; j < eventCount( i ); j++) {
         score[i][j] = 0;      
   }

   // More Readable and maintainable (but takes longer to type)
   for (teamIndex = 0; teamIndex < teamCount; teamIndex++) {
      for (eventIndex = 0; eventIndex < eventCount( eventIndex ); eventIndex++) {
         score[teamIndex][eventIndex] = 0;
   }

Naming Status Variables

Status variables describe the state of your program. Remember you are trying to capture what you are doing not how you are doing it.
  • Avoid cryptic names, it makes it hard to read and understand
  • Think of a better name than flag or state for status variables
  • Avoid magic number literals (or magic number strings)
  • Use meaningful names that describe what not how
  • Refactor cryptic names for better names and/or wrap status variables inside meaningfully named short accessor routines instead.

   // Cryptic
   if ( flag ) ...
   if ( statusFlag & 0x0F ) ...
   if ( printFlag == 16 ) ...
   if ( stateFlag == 0) ...
   
   flag = 0x1;
   statusFlag = 0x80;
   printFlag = 16;
   stateFlag = 0;

vs.
 
   // Better
   if ( dataReady ) ...
   if ( characterType & PRINTABLE_CHAR ) ...
   if ( reportType == REPORT_TYPE_ANNUAL ) ...
   if ( RecalcNeeded() ) ...

   dataReady = true;
   characterType = CONTROL_CHAR;
   reportType = REPORT_TYPE_ANNUAL;
   RecalcNeededOff();
   

Naming Temporary Variables

Temporary variables are used to hold intermediate results of calculations, temporary place holders, and to track housekeeping values. Be carefuly when giving variables obvious "temporary" names. Naming a variable "temp" may be a sign that you don't fully understand the problem space, you are trying to solve.
   temp = sqrt( b^2 - 4*a*c );
vs.
   discriminant = sqrt( b^2 - 4*a*c );

Naming Boolean Variables

Keep typical boolean names in mind (done, error, found, success)

  • done, use done to indicate when an ongoing operation is done, set it to false to begin with, set it to true when completed
  • error, use error to indicate an error (of some sort) has occurred, set the variable to false to begin with, set it to true if an error occurs
  • found, use found to indicate whether a value has been found. Set found to false to begin with, set it to true once the value has been found.
  • success or ok, use success or ok to indicate whether an operation succeeded (or failed). set the variable to false if the operation failed, set it to true if the operation succeeded.

Give Boolean variables names that imply true or false

   // Unclear names
   status, sourceFile, condition

   // Better names
   done, found, statusOK
   isDone, isComplete, preambleRead, recalcNeeded,
   sourceFileAvailable, sourceFileFound

Use positive boolean variable names

  • Negative names like notFound, notDone, and notSuccessful are hard to read when they are negated (double negation)

Naming Enumerated Types

  • Group Prefix, Make sure that it's clear that all members of the enumerated type are part of the same group by using a group prefix, COLOR_, PLANET_, MONTH_, FS_, etc.
  • Type Definition, The underlying enumeration type should be treated as any other type definition
  • Member Fields, The enumerated member fields should be differentiated from other variable names via a naming convention (For Instance, All capitals).
   enum FilterState {
     FS_WRITE_CELL = 0x0001,
     FS_COPY_COUNTS = 0x0010,
     FS_COPY_COMMENTS = 0x0020,
     FS_COPY_BOUNDS = 0x0040,
     FS_DEFAULT_STATE = (FS_WRITE_CELL | FS_COPY_COUNTS | FS_COPY_COMMENTS | FS_COPY_BOUNDS)
  };

Naming Constants

Name the abstract entity the constant represents, not the specific number the constant refers to. FIVE would be a bad constant name. MAX_PASSES_NEEDED would be a good constant name.


Creating Readable Short Names

  • Eliminate needless words
  • Use shorter words which are synomyns to the original words
  • Abbreviate (see below)

Abbreviation Guidelines

  • Use standard abbreviations (common use in your field and/or are listed in a dictionary)
  • Remove all nonleading vowels (computer -> cmptr, screen -> scrn, integer -> intgr, etc.)
  • Remove articles: and, or, the, etc.
  • Use the first letter or first few letters of each word
  • Truncate consistently after the first, second, or third letter of each word
  • Keep the first and last letters of each word
  • Use every significant word in the name (up to 3 words)
  • Remove useless suffixes (ing, ed, etc.)
  • Keep the most noticeable sound in each syllable
  • Be sure your abbreviation doesn't change the meaning of the variable
  • Double check that your new abbreviation is not synonomous with obscene or vulgar language
  • Do NOT use phonetic abbreviations (ILV2SK8)
  • Iterate throught the above techniques until you get a variable name that is between 8-20 characters and still somewhat readable

More Notes on Abbreviations

  • Don't abbreviate by removing one character from a word (Jun for June, or Jul for July)
  • Abbreviate consistently (num or no for number but not both)
  • Create names that you can prounce
  • Avoid combinations that result in misreading or mispronunciation (is 'frd' equavalent 'fired', or 'Full Revenue Disbursal')
  • Use a thesaurus to help resolve naming collisions among words with similar abbreviations
  • Document extremely short and/or cryptic names with a glossary in the file header

   /*---------------------------------------------
     Variable      Meaning
     --------      -------
     xPos          x-coordinate position
     NDSCMP        Needs Computing
     PTGTTL        Point Grand Total
     PTVLMX        Point Value Maximum
     ...
   ---------------------------------------------*/
  • Consider creating a project-level "Standard Abbreviations" document
  • Names matter more to future readers of the code than to the writer.


Kinds of Names to avoid

  • Avoid misleading names or abbreviations
   #define FALSE 1   
  • Avoid names with obscene, vulgar, or unintentionally humorous connotations.
  • Avoid collections of names with similar meanings (input & inputValue, recordNum and numRecords, etc.)
  • Avoid variables with different meanings but similar names (clientRecs & clientReps) vs (clientRecords & clientReports)
  • Avoid names that sound similar (wrap vs. rap)
  • Avoid numerals in names (file1, file2, etc.)
  • Avoid misspelled words in names
  • Avoid words that are easily misspelled in english (reciept vs. receipt)
  • Don't differentiate variable names solely by capitalization (VPN vs. vpn vs. vPN)
  • Avoid using reserved keywords, standard types, variables, and routines (if necessary, use namespaces to resolve unexpected collisions)
#undefine __FILE__
   int __FILE__;          // Mis-use of Standard Macro name in C/C++
   int then = 0;          // Confusing variable name
   if (__FILE__ == then) {
      then = 1;
   } else {
      then = 2;
   }
  • Don't use names that have nothing to do with the problem space
   // Compute 1-Ring 
   int shrek = 23;
   float donkey = 46.0;
   ...
  • Avoid names that contain hard-to-read characters (the letter 'l' vs. the digit '1', The letter 'O' vs. the digit '0', etc, don't use both in the same name)

-- ShawnDB - 19 Jun 2008
to top


You are here: TModeling > Software > CodeGuide > StyleGuide > NamingConventions

to top

Copyright © 1999-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback