Part 2. Comments
...
When writing code, we all use the rules of code design. Sometimes their own rules are invented, in other cases, ready-made style guides are used. Although all C ++ programmers read in English more easily than in their native language, it is more pleasant to have a manual in the latter.
This article is a translation of part of the Google style guide in C ++ into Russian.
Original article (fork on github), updated translation .
Naming
The basic rules for coding style are naming. The appearance of the name immediately (without searching for an ad) tells us what it is: type, variable, function, constant, macro, etc. Naming rules can be arbitrary, but consistency is important, and rules must be followed.
General Naming Principles
- Use names that even people on the other team will understand.
- The name should speak of the purpose or applicability of the object.
- Do not save on the length of the name, it is better to have a longer and more understandable (even for beginners) name.
- Fewer abbreviations, especially if they are unfamiliar outside the project.
- Use only known abbreviations (does Wikipedia know about them?).
- Do not shorten the words.
In general, the name length should match the size of the scope. For example, n is a suitable name within a function of 5 lines, however, when describing a class, this can be a little short.
class MyClass { public: int CountFooErrors(const std::vector<Foo>& foos) { int n = 0; // for (const auto& foo : foos) { ... ++n; } return n; } void DoSomethingImportant() { std::string fqdn = ...; // } private: const int kMaxAllowedConnections = ...; // };
class MyClass { public: int CountFooErrors(const std::vector<Foo>& foos) { int total_number_of_foo_errors = 0; // for (int foo_index = 0; foo_index < foos.size(); ++foo_index) { // `i` ... ++total_number_of_foo_errors; } return total_number_of_foo_errors; } void DoSomethingImportant() { int cstmr_id = ...; // ( ) } private: const int kNum = ...; // };
Note that typical names are also valid: i for an iterator or counter, T for a template parameter.
In the future, when describing the rules βwordβ / βwordβ is all that is written in English without spaces, including abbreviations. In a word, the first letter can be capitalized (depending on the style: " camel case " or "Pascal case"), the remaining letters are lowercase. For example, preferably StartRpc () , preferably StartRPC () .
Template parameters also follow the rules of their categories: Type names, Variable names, etc ...
File names
File names should be written only in lowercase letters, you can use underscore ( _ ) or hyphen ( - ) to separate them. Use the separator used in the project. If there is no single approach, use "_".
Examples of suitable names:
- my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
- myusefulclass_test.cc // _unittest and _regtest are deprecated.
C ++ files should end in .cc , header should be in
.h . Files included as text must end in .inc (see also the section Independent Headers ).
Do not use names that already exist in / usr / include , such as db.h.
Try to give files specific names. For example, http_server_logs.h is better than logs.h. When files are used in pairs, it is best to give them the same name. For example, foo_bar.h and foo_bar.cc (and contain the class FooBar ).
Type names
Type names begin with a capital letter, each new word also begins with a capital letter. Underscores are not used: MyExcitingClass , MyExcitingEnum .
Names of all types β classes, structures, aliases, enumerations, template parameters β are named in the same style. Type names begin with a capital letter, each new word also begins with a capital letter. Underscores are not used. For example:
// classes and structs class UrlTable { ... class UrlTableTester { ... struct UrlTableProperties { ... // typedefs typedef hash_map<UrlTableProperties *, std::string> PropertiesMap; // using aliases using PropertiesMap = hash_map<UrlTableProperties *, std::string>; // enums enum UrlTableErrors { ...
Variable names
The names of variables (including function parameters) and data members are written in lowercase letters with an underscore between words. Members of these classes (not structures) are complemented by an underscore at the end of the name. For example: a_local_variable , a_struct_data_member , a_class_data_member_ .
Common Variable Names
For example:
std::string table_name; // OK -
std::string tableName; // -
Class data members
The members of these classes, static and non-static, are referred to as ordinary variables with the addition of an underscore at the end.
class TableInfo { ... private: std::string table_name_; // OK - static Pool<TableInfo>* pool_; // OK. };
Structure data members
Members of the structure data, static and non-static, are referred to as ordinary variables. No underscore is added to them at the end.
struct UrlTableProperties { std::string name; int num_entries; static Pool<UrlTableProperties>* pool; };
See also Structures vs Classes , which describes when to use structures, when classes.
Names of constants
Objects are declared as constexpr or const, so that the value does not change during execution. The names of the constants begin with the symbol "k", then comes the name in a mixed style (upper and lower case letters). Underscore can be used in rare cases when uppercase letters cannot be used for separation. For example:
const int kDaysInAWeek = 7; const int kAndroid8_0_0 = 24; // Android 8.0.0
All similar constant objects with a static type of storage (i.e., static or global, more details here: Storage Duration ) are also named. This convention is optional for variables in other types of storage (for example, automatic constant objects).
Function names
Common functions are named in a mixed style (uppercase and lowercase letters); variable access functions (accessor and mutator) should have a style similar to the target variable.
Usually a function name starts with a capital letter and each word in the name is capitalized.
void AddTableEntry(); void DeleteUrl(); void OpenFileOrDie();
(Similar rules apply to constants in a class or namespace area that are part of the API and should look like functions (and the fact that they are not functions is uncritical))
Accessors and mutators (get and set functions) can be named like the corresponding variables. They often correspond to real member variables, but this is not necessary. For example, int count () and void set_count (int count) .
Namespace Namespace
The namespace is called lowercase. The top-level namespace is based on the name of the project. Avoid collisions of your names and other well-known namespaces.
A top-level namespace is usually the name of a project or team (which made the code). The code should be located in a directory (or subdirectory) with a name corresponding to the namespace.
Do not forget the rule not to use abbreviations - this also applies to namespaces. The code inside is unlikely to need a namespace reference, so abbreviations are superfluous.
Avoid using known names for nested namespaces. Collisions between names can lead to surprises in the assembly. In particular, do not create nested namespaces named std . Unique project identifiers ( websearch :: index , websearch :: index_util ) are recommended instead of unsafe against collisions websearch :: util .
For internal / internal namespaces, collisions can occur when another code is added (internal helpers tend to repeat on different teams). In this case, using a file name to name a namespace helps a lot. ( websearch :: index :: frobber_internal for use in frobber.h )
Enumeration Names
Enumerations (both with scoped constraints and without unscoped) must be referred to as either constants or macros . That is: either kEnumName or ENUM_NAME .
It is preferable to name the individual values ββin the enumerator as constants. However, it is permissible to refer to as macros. The name of the UrlTableErrors (and AlternateUrlTableErrors ) enumeration itself is a type. Consequently, a mixed style is used.
enum UrlTableErrors { kOk = 0, kErrorOutOfMemory, kErrorMalformedInput, }; enum AlternateUrlTableErrors { OK = 0, OUT_OF_MEMORY = 1, MALFORMED_INPUT = 2, };
Until January 2009, the style of naming enumeration values ββwas like that of macros. This created problems with duplicate macro names and enumeration values. Applying a constant style solves the problem and it is preferable to use a constant style in the new code. However, there is no need to rewrite the old code (as long as there is no duplication problem).
Macro names
Aren't you going to define macros ? Just in case (if you are going), they should look like this:
MY_MACRO_THAT_SCARES_SMALL_CHILDREN_AND_ADULTS_ALIKE .
Please read how to define macros ; Normally, macros should not be used. However, if you absolutely need them, name them in capital letters with underscores.
#define ROUND(x) ... #define PI_ROUNDED 3.0
Naming Exceptions
If you need to name something that has analogues in existing C or C ++ code, then follow the style used in the code.
bigopen ()
function name derived from open ()
uint
definition similar to standard types
bigpos
struct or class derived from pos
sparse_hash_map
STL-like entity; follow stl style
LONGLONG_MAX
constant same as INT_MAX
Note: Links may lead to sections of the manual that have not yet been translated.