After a feeled million hours of coding in the past 16 years there have been many ways to write code in many different languages. Some seemed correct to the time they were used, some seemed to be too strict or too chaotic and I also evolved my coding style with each new line written. Now considering the results of over 5 years in professionall game development, tools and engine code as hobbyist and on small and large commercial projects up to AAA titles, there are still many ways one could write code in different languages but also in the same language on different projects in one and the same but also different companies. I mostly agree with; see some trends in C#, C++ coding guidelines that are fully worth to go for but the major difference is on the naming conventions.
Because I have currently to write my own coding guidelines (not for a special project but primary as a personal convention to refer to when coding) and seek for a way I'm happy with, I did some research on different guidelines and came up with following references:
When Epic Games write about Unreal
QuoteNaming Conventions
The first letter of each word in a name (e.g. type or variable) is capitalized, and there is usually no underscore between words. For example, Health and UPrimitiveComponent, but not lastMouseCoordinates or delta_coordinates.
Type names are prefixed with an additional upper-case letter to distinguish them from variable names. For example, FSkin is a type name, and Skin is an instance of a FSkin.
Template classes are prefixed by T.
Classes that inherit from UObject are prefixed by U.
Classes that inherit from AActor are prefixed by A.
Classes that inherit from SWidget are prefixed by S.
Classes that are abstract interfaces are prefixed by I.
Enums are prefixed by E.
Boolean variables must be prefixed by b (e.g. "bPendingDestruction", or "bHasFadedIn").
Most other classes are prefixed by F, though some subsystems use other letters.
Typedefs should be prefixed by whatever is appropriate for that type: F if it's a typedef of a struct, U if it's a typedef of a UObject etc.
A typedef of a particular template instantiation is no longer a template and should be prefixed accordingly, e.g.:
typedef TArray<FMyType> FArrayOfMyTypes;
This seems a bit confusing when seeking for some type like Animation or Skin (that are both different prefixed with A and F) but prevents various naming conflicts to types and variables when writing a function that accepts FSkin Skin as parameter for example.
Googles c++ guidelines point into a completely different direction when they write
QuoteType Names
Type names start with a capital letter and have a capital letter for each new word, with no underscores:
MyExcitingClass
,MyExcitingEnum
.The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention. Type names should start with a capital letter and have a capital letter for each new word. No underscores. For example:
// classes and structs class UrlTable { ... class UrlTableTester { ... struct UrlTableProperties { ... // typedefs typedef hash_map<UrlTableProperties *, string> PropertiesMap; // using aliases using PropertiesMap = hash_map<UrlTableProperties *, string>; // enums enum UrlTableErrors { ...
Variable Names
The names of variables (including function parameters) and data members are all lowercase, with underscores between words. Data members of classes (but not structs) additionally have trailing underscores. For instance:
a_local_variable
,a_struct_data_member
,a_class_data_member_
.Common Variable names
For example:
string table_name; // OK - uses underscore. string tablename; // OK - all lowercase.
string tableName; // Bad - mixed case.
Class Data Members
Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore.
class TableInfo { ... private: string table_name_; // OK - underscore at end. string tablename_; // OK. static Pool<TableInfo>* pool_; // OK. };
Struct Data Members
Data members of structs, both static and non-static, are named like ordinary nonmember variables. They do not have the trailing underscores that data members in classes have.
struct UrlTableProperties { string name; int num_entries; static Pool<UrlTableProperties>* pool; };
See Structs vs. Classes for a discussion of when to use a struct versus a class.
Constant Names
Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by mixed case. For example:
const int kDaysInAWeek = 7;
All such variables with static storage duration (i.e. statics and globals, see Storage Duration for details) should be named this way. This convention is optional for variables of other storage classes, e.g. automatic variables, otherwise the usual variable naming rules apply.
Function Names
Regular functions have mixed case; accessors and mutators may be named like variables.
Ordinarily, functions should start with a capital letter and have a capital letter for each new word (a.k.a. "Camel Case" or "Pascal case"). Such names should not have underscores. Prefer to capitalize acronyms as single words (i.e.
StartRpc()
, notStartRPC()
).AddTableEntry() DeleteUrl() OpenFileOrDie()
(The same naming rule applies to class- and namespace-scope constants that are exposed as part of an API and that are intended to look like functions, because the fact that they're objects rather than functions is an unimportant implementation detail.)
Accessors and mutators (get and set functions) may be named like variables. These often correspond to actual member variables, but this is not required. For example,
int count()
andvoid set_count(int count)
.Namespace Names
Namespace names are all lower-case. Top-level namespace names are based on the project name . Avoid collisions between nested namespaces and well-known top-level namespaces.The name of a top-level namespace should usually be the name of the project or team whose code is contained in that namespace. The code in that namespace should usually be in a directory whose basename matches the namespace name (or subdirectories thereof).
Keep in mind that the rule against abbreviated names applies to namespaces just as much as variable names. Code inside the namespace seldom needs to mention the namespace name, so there's usually no particular need for abbreviation anyway.
Avoid nested namespaces that match well-known top-level namespaces. Collisions between namespace names can lead to surprising build breaks because of name lookup rules. In particular, do not create any nested
std
namespaces. Prefer unique project identifiers (websearch::index
,websearch::index_util
) over collision-prone names likewebsearch::util
.For
internal
namespaces, be wary of other code being added to the sameinternal
namespace causing a collision (internal helpers within a team tend to be related and may lead to collisions). In such a situation, using the filename to make a unique internal name is helpful (websearch::index::frobber_internal
for use infrobber.h
)Enumerator Names
Enumerators (for both scoped and unscoped enums) should be named either like constants or like macros: either
kEnumName
orENUM_NAME
.Preferably, the individual enumerators should be named like constants. However, it is also acceptable to name them like macros. The enumeration name,
UrlTableErrors
(andAlternateUrlTableErrors
), is a type, and therefore mixed case.enum UrlTableErrors { kOK = 0, kErrorOutOfMemory, kErrorMalformedInput, }; enum AlternateUrlTableErrors { OK = 0, OUT_OF_MEMORY = 1, MALFORMED_INPUT = 2, };
Until January 2009, the style was to name enum values like macros. This caused problems with name collisions between enum values and macros. Hence, the change to prefer constant-style naming was put in place. New code should prefer constant-style naming if possible. However, there is no reason to change old code to use constant-style names, unless the old names are actually causing a compile-time problem.
Macro Names
You're not really going to define a macro, are you? If you do, they're like this:
MY_MACRO_THAT_SCARES_SMALL_CHILDREN
.Please see the description of macros; in general macros should not be used. However, if they are absolutely needed, then they should be named with all capitals and underscores.
#define ROUND(x) ... #define PI_ROUNDED 3.0
Exceptions to Naming Rules
If you are naming something that is analogous to an existing C or C++ entity then you can follow the existing naming convention scheme.
bigopen()
function name, follows form ofopen()
uint
typedef
bigpos
struct
orclass
, follows form ofpos
sparse_hash_map
STL-like entity; follows STL naming conventionsLONGLONG_MAX
a constant, as inINT_MAX
So they heavily make use of typos, underscores and also lower case prefixes to identify different kinds of member, static, nonstatic and function names and in the same breath except there rules for various special cases.
Some other examples from different projexts I was invovled to also use and do not use prefixing types or use underscores
class Class
{
const <type> cConstant;
const <type> Constant;
const <type> __Constant;
<type> _myClassMember;
<type> _MyClassMember;
<type> myClassmember;
<type> mMyClassMember;
<type> function(<type> parameter);
<type> Function(<type> parameter);
<type> Function(<type> aParameter);
}
class NAClass //avoid using namespaces, instead prefix anything with a 2 letter namespace like identifier
{
...
}
Dont need to mention that Visual Studio will raise a Warning/Exception that a type is named as same as a function parameter when using a class
class Container
{
private int size; //current size
public Resize(int size) //will cause compiler telling that type matches a member type
{
//do resize here
}
}
So in the end anyone does he or she thinks that it is worth to be done and so me do too. I would like to hear your opinions to why and what codings style do you prefer or are involved to in whatever way. What do you think makes a good standard especially for the most common point, Naming Convetions?
Will be corious to read your opinions