Changes between Version 3 and Version 4 of CppCodingStandards


Ignore:
Timestamp:
Jul 21, 2009, 4:11:44 PM (10 years ago)
Author:
dtodd
Comment:

began the process of adding in detailed specs...

Legend:

Unmodified
Added
Removed
Modified
  • CppCodingStandards

    v3 v4  
    11= C++ Coding Standards =
    22
     3
    34== Overview ==
    45
    56Below I will describes in Gory detail suggested guidelines for C++ code.  These rules apply to new code: new files, new modules, new projects.
    67
    7 When editing an older file to fix a minor bug, etc, I think it's prudent to make small changes to the source. In this case, it will be best for readability if you use the standard that was there previously.  Than includes following the established indentation, placement of curly brackets "{}", naming conventions, etc.
     8When editing an older file to fix a minor bug, etc, I think it's prudent to make as small a change as possible to the source. In this case, it will be best for readability if you use the standard that was there previously.  Than includes following the established indentation, placement of curly brackets "{}", naming conventions, etc.
    89
    910Obviously if the code requires a complete rewrite, then use the suggested coding standards listed below.
    1011
    11 Here are some resources and books I like for learning C++, coding standards, and general conventions for C++.  As of this writing (July 2009) C++ is scheduled for a major revision (http://en.wikipedia.org/wiki/C%2B%2B0x), and I imagine many new books will come out and make some of my original suggestions obsolete:
     12Here are some resources, and books that I like for learning about C++, coding standards, and general conventions for C++.  As of this writing (July 2009) C++ is scheduled for a major revision (http://en.wikipedia.org/wiki/C%2B%2B0x), and I imagine many new books will come out and make some of my original suggestions obsolete:
    1213
    1314== Resources ==
     
    1819
    1920Coding Standards
    20   * Used as the main source for those listed below: http://www.possibility.com/Cpp/CppCodingStandard.html
     21  * Used as a resource for coding standards listed below: http://www.possibility.com/Cpp/CppCodingStandard.html
    2122  * Looks useful as a secondary source: http://geosoft.no/development/cppstyle.html
    2223
    2324== Good Books ==
     25
     26There are many, and what you like depends on your learning style.  Here are some of my favorites.
    2427
    2528__Intermediate and Advanced__
     
    4750== Proposed Standard ==
    4851
    49 
    50 
     52As mentioned above, some of this was borrowed from, http://www.possibility.com/Cpp/CppCodingStandard.html, with permission as outlined here: "Using this Standard - If you want to make a local copy of this standard and use it as your own you are perfectly free to do so. That's why I made it! If you find any errors or make any improvements please let me know at tmh@possibility.com."  See also http://www.possibility.com/Tmh and http://www.possibility.com/epowiki/Wiki.jsp.
     53
     54However, as this is a new gamma standard, if you have any immediate issues, send an email to david.todd@va.gov or whoever is managing this standard.
     55
     56=== Introduction ===
     57
     58Standardization is Important. It helps if the standard annoys everyone in some way, so that all members of the team feel they are on the same playing field.
     59
     60==== Good Things about a Standard ====
     61
     62When a project tries to adhere to common standards a few good things happen:
     63  * Programmers can go into any code and figure out what's going on.
     64  * New people can get up to speed quickly.
     65  * People new to C++ are spared the need to develop a personal style and defend it to the death.
     66  * People new to C++ are spared making the same mistakes over and over again.
     67  * People make fewer mistakes in consistent environments.
     68  * Programmers have a common enemy - yes, the standard.
     69
     70==== Bad Points about Having a Standard ====
     71
     72Now the bad:
     73  * The standard is usually stupid because it was "obviously made by someone who doesn't understand C++".
     74  * The standard is usually stupid because it's "not what I do".
     75  * Standards reduce creativity.
     76  * Standards are unnecessary as long as people are consistent.
     77  * Standards enforce too much structure.
     78  * Why bother, people ignore standards anyway.
     79  * Standards can be used as a reason for NIH syndrome(not invented here), because the new/borrowed code won't follow the standard.
     80
     81=== NAMES - General Discussion ===
     82
     83''Using appropriate names for the purpose at hand.''
     84
     85'''Good names are the heart of clear programming!!'''
     86
     87In ancient times people believed that knowing someone's ''true'' name gave them magical power over that person. If you can think up the true name for something, you can give yourself, and the people who read your code, power over the domain.
     88
     89A name is the result of a long deep thought process (or should be) about the ecology it which it lives. Only a programmer who understands the system as a whole can create a name that "fits" with the system.
     90
     91If the name is appropriate everything fits together naturally, relationships are clear, meaning is derived and derivable, and reasoning from common human expectations works as is desired.
     92
     93If you find that all your names look like ''Thing'' and ''Do_It'', then you should probably revisit your design.
     94
     95==== Class Names ====
     96
     97  * Name the class after what it is. If you can't think of what it is, then that's a clue you have not thought through the design well enough. Avoid vague and generic names unless the concept is really vague and generic, which should only be true for abstract classes.  i.e. a Typewriter should be called a Typewriter and not a PushKeyInputSystem.
     98  * Compound names of over three words are a clue that your design may be confusing various entities in your system. Revisit your design. Consider trying a CRC card session to see if your objects have more responsibilities than they should.
     99  * Try to avoid the temptation of bringing the name of the parent class into the derived class's name. A class should stand on its own. It doesn't matter what it derives from.  Only possible exceptions would be abstact class names, like "GroundTransport" (e.g. ChevyMalibu derives from GeneralMotorsCars derives from Automobile derives from GroundTransport derives from Transport... remember it's just an example!).  Of course if you're doing this, you better have a good reason to justify the added complexity of all the abstract classes!
     100  * Suffixes are sometimes helpful. For example, if your system uses agents, then naming an object DownloadAgent conveys real information.
     101
     102
     103==== Method and Function Names ====
     104
     105  * Usually every method and function performs an action, so the name should make clear what it does: CheckForErrors() instead of ErrorCheck(), DumpDataToFile() instead of DataFile(). This will also make functions and data objects more distinguishable.
     106Classes are often nouns. By making function names verbs and following other naming conventions programs can be read more naturally.
     107
     108  * Suffixes are sometimes useful:
     109    * Max - to mean the maximum value something can have.
     110    * Cnt - the current count of a running count variable.
     111    * Key - key value
     112    * (For example: RetryMax to mean the maximum number of retries, RetryCnt to mean the current retry count.)
     113
     114  * Prefixes are sometimes useful:
     115    * Is - to ask a question about something. Whenever someone sees Is they will know it's a question.
     116    * Get - get a value.
     117    * Set - set a value.
     118    * (For example: IsHitRetryLimit, or GetValueCnt.)
     119
     120
     121==== Include Units in Names when Appropriate ====
     122If a variable represents time, weight, or some other unit then include the unit in the name so developers can more easily spot problems, and also know what values to use as input.
     123
     124For example:
     125{{{
     126uint32 m_TimeoutMsecs;
     127uint32 m_MyWeightLbs;
     128}}}
     129
     130Better yet, is to make a variable into a class so bad conversions can be caught. (:Example:?)
     131
     132
     133===== No All Upper Case Abbreviations ====
     134
     135  * When confronted with a situation where you could use an all upper case abbreviation, don't.  Instead use an initial upper case letter followed by all lower case letters.
     136
     137__Justification__
     138
     139  * People seem to have very different intuitions, when making names containing abbreviations. It's best to settle on one strategy so the names are absolutely predictable.
     140
     141Take for example NetworkABCKey. Notice how the C from ABC and K from key can be confused. Some people don't mind this, and others just hate it, so you'll find different policies in different code and then you never know what to call something.
     142
     143Example:
     144{{{
     145   class FluidOz             // NOT FluidOZ
     146   class NetworkAbcKey       // NOT NetworkABCKey
     147}}}
     148
     149
     150''':Continue Editing Here: - DCT'''
     151
     152
     153=== Names - In Detail ===
     154
     155==== Class Names ====
     156•       Use upper case letters as word separators, lower case for the rest of a word
     157•       First character in a name is upper case
     158•       No underbars ('_')
     159Justification
     160•       Of all the different naming strategies many people found this one the best compromise.
     161Example
     162   class NameOneTwo
     163 
     164   class Name
     165
     166
     167==== Class Library Names ====
     168•       Now that name spaces are becoming more widely implemented, name spaces should be used to prevent class name conflicts among libraries from different vendors and groups.
     169•       When not using name spaces, it's common to prevent class name clashes by prefixing class names with a unique string. Two characters is sufficient, but a longer length is fine.
     170Example
     171John Johnson's complete data structure library could use JJ as a prefix, so classes would be:
     172 
     173   class JjLinkList
     174   {
     175   }
     176
     177
     178=== Method Names ===
     179•       Use the same rule as for class names.
     180Justification
     181•       Of all the different naming strategies many people found this one the best compromise.
     182Example
     183   class NameOneTwo
     184   {
     185   public:
     186      int                   DoIt();
     187      void                  HandleError();
     188   }
     189
     190
     191==== Class Attribute Names ====
     192•       Attribute names should be prepended with the character 'm'.
     193•       After the 'm' use the same rules as for class names.
     194•       'm' always precedes other name modifiers like 'p' for pointer.
     195Justification
     196•       Prepending 'm' prevents any conflict with method names. Often your methods and attribute names will be similar, especially for accessors.
     197Example
     198   class NameOneTwo
     199   {
     200   public:
     201      int                   VarAbc();
     202      int                   ErrorNumber();
     203   private:
     204      int                   m_VarAbc;
     205      int                   m_ErrorNumber;
     206      String*               m_pName;
     207   }
     208
     209The original spec had mTimoutMsecs, but I think that m_TimeoutMsecs is more clear as the m is separated from the "TimeoutMsecs".  My only reservation is that it's harder to type, but usually worth the extra effort.
     210
     211
     212==== Method Argument Names ====
     213•       The first character should be lower case.
     214•       All word beginnings after the first letter should be upper case as with class names.
     215Justification
     216•       You can always tell which variables are passed in variables.
     217•       You can use names similar to class names without conflicting with class names.
     218Example
     219   class NameOneTwo
     220   {
     221   public:
     222      int  StartYourEngines(Engine& rSomeEngine,
     223                            Engine& rAnotherEngine);
     224   }
     225
     226
     227==== Variable Names on the Stack ====
     228
     229i.e. Automatic variables.
     230
     231•       use all lower case letters
     232•       use '_' as the word separator.
     233Justification
     234•       With this approach the scope of the variable is clear in the code.
     235•       Now all variables look different and are identifiable in the code.
     236Example
     237   int
     238   NameOneTwo::HandleError(int errorNumber)
     239   {
     240      int            error= OsErr();
     241      Time           time_of_error;
     242      ErrorProcessor error_processor;
     243      Time*          p_out_of_time= 0;
     244   }
     245
     246The standard pointer notation is not entirely satisfactory because it doesn't look quite right, but it is consistent.
     247
     248How do you handle statics? There's never a reason to have a static local to a function so there's no reason to invent a syntax for it. But like for most absolute rules, there is an exception, that is when making singletons. Use a "s_" prefix in this case. Take a look at Singleton Pattern for more details.
     249
     250
     251==== Pointer Variables ====
     252•       pointers should be prepended by a 'p' in most cases
     253•       place the * close to the pointer type not the variable name
     254
     255Justification
     256•       The idea is that the difference between a pointer, object, and a reference to an object is important for understanding the code, especially in C++ where -> can be overloaded, and casting and copy semantics are important.
     257
     258•       Pointers really are a change of type so the * belongs near the type. One reservation with this policy relates to declaring multiple variables with the same type on the same line. In C++ the pointer modifier only applies to the closest variable, not all of them, which can be very confusing, especially for newbies. You want to have one declaration per line anyway so you can document each variable.
     259
     260Example
     261  String* pName= new String;
     262
     263  String* pName, name, address; // note, only pName is a pointer.
     264
     265
     266==== Reference Variables and Functions Returning References ====
     267•       References should be prepended with 'r'.
     268Justification
     269•       The difference between variable types is clarified.
     270•       It establishes the difference between a method returning a modifiable object and the same method name returning a non-modifiable object.
     271Example
     272   class Test
     273   {
     274   public:
     275      void               DoSomething(StatusInfo& rStatus);
     276
     277      StatusInfo&        rStatus();
     278      const StatusInfo&  Status() const;
     279
     280   private:
     281      StatusInfo&        mrStatus;
     282   }
     283
     284
     285==== Global Variables ====
     286•       Global variables should be prepended with a 'g'.
     287Justification
     288•       It's important to know the scope of a variable.
     289Example
     290    Logger  gLog;
     291    Logger* gpLog;
     292
     293
     294==== Global Constants ====
     295•       Global constants should be all caps with '_' separators.
     296Justification
     297It's tradition for global constants to named this way. You must be careful to not conflict with other global #defines and enum labels.
     298Example
     299    const int A_GLOBAL_CONSTANT= 5;
     300
     301
     302==== Static Variables ====
     303•       Static variables may be prepended with 's'.
     304Justification
     305•       It's important to know the scope of a variable.
     306Example
     307   class Test
     308   {
     309   public:
     310   private:
     311      static StatusInfo msStatus;
     312   }
     313
     314
     315==== Type Names ====
     316•       When possible for types based on native types make a typedef.
     317•       Typedef names should use the same naming policy as for a class with the word Type appended.
     318Justification
     319•       Of all the different naming strategies many people found this one the best compromise.
     320•       Types are things so should use upper case letters. Type is appended to make it clear this is not a class.
     321Example
     322   typedef uint16  ModuleType;
     323   typedef uint32  SystemType;
     324
     325
     326==== Enum Names ====
     327Labels All Upper Case with '_' Word Separators
     328This is the standard rule for enum labels.
     329Example
     330   enum PinStateType
     331   {
     332      PIN_OFF,
     333      PIN_ON
     334   };
     335
     336==== Enums as Constants without Class Scoping ====
     337Sometimes people use enums as constants. When an enum is not embedded in a class, make sure you use some sort of differentiating name before the label so as to prevent name clashes.
     338Example
     339   enum PinStateType            If PIN was not prepended a conflict
     340   {                            would occur as OFF and ON are probably
     341      PIN_OFF,                  already defined.
     342      PIN_ON
     343   };
     344
     345==== Enums with Class Scoping ====
     346
     347Just name the enum items what you wish and always qualify with the class name: Aclass::PIN_OFF.
     348Make a Label for an Error State
     349It's often useful to be able to say an enum is not in any of its valid states. Make a label for an uninitialized or error state. Make it the first label if possible.
     350Example
     351enum { STATE_ERR,  STATE_OPEN, STATE_RUNNING, STATE_DYING};
     352
     353==== #define and Macro Names ====
     354•       Put #defines and macros in all upper using '_' separators.
     355Justification
     356This makes it very clear that the value is not alterable and in the case of macros, makes it clear that you are using a construct that requires care.
     357Some subtle errors can occur when macro names and enum labels use the same name.
     358Example
     359#define MAX(a,b) blah
     360#define IS_ERR(err) blah
     361
     362
     363==== C Function Names ====
     364•       In a C++ project there should be very few C functions.
     365•       For C functions use the GNU convention of all lower case letters with '_' as the word delimiter.
     366Justification
     367•       It makes C functions very different from any C++ related names.
     368Example
     369   int
     370   some_bloody_function()
     371   {
     372   }
     373
     374
     375==== C++ File Extensions ====
     376In short: Use the .h extension for header files and .cc for source files.
     377For some reason an odd split occurred in early C++ compilers around what C++ source files should be called. C header files always use the .h and C source files always use the .c extension. What should we use for C++?
     378
     379The short answer is as long as everyone on your project agrees it doesn't really matter. The build environment should be able to invoke the right compiler for any extension.
     380
     381Historically speaking here have been the options:
     382•       Header Files: .h, .hh, .hpp
     383•       Source Files: .C, .cpp, .cc
     384
     385==== Header File Extension Discussion ====
     386Using .hh extension is not widely popular but makes a certain kind of sense. C header files use .h file extension and C++ based header files use .hh file extension. The problem is if we consider a header file an interface to a service then we can have a C interface to a service and C++ interface to the service in the same file. Using preprocessor directives this is possible and common. The recommendation is to stick with using the .h extension.
     387 
     388==== Source File Extension Discussion ====
     389The problem with the .C extension is that it is indistinguishable from the .c extensions in operating systems that aren't case sensitive. Yes, this is a UNIX vs. windows issue. Since it is a simple step aiding portability we won't use the .C extension. The .cpp extension is a little wordy. So the .cc extension wins by default.
     390
     391
     392
     393