가장 중요한 일관적인 규칙은 naming 정책들이다. name의 스타일은 즉시 entity를 어떻게 명명할 것이지를 알려준다: type, variable, function, constant, macro, 등등., entity의 선언을 검색하도록 요구하지 않고. 우리의 뇌에서 pattern-matching engine은 name rule에서 크게 의존한다.
naming에 관한 style rule은 꽤 임의적이지만, 이 부분에서 개인적인 선호보다는 일관성이 더 중요하며 합리적이라고 생각하든 그렇지 않든, rule은 rule이다.
nameㄱ rule의 목적에서 "word"는 내부 space 없이 영어로 작성된 어떤 것이다. 각 word는 words간 underscores(" snake case")로 모두 소문자이거나 각 word의 첫 번째 글자를 대분자로한 misxed case ("camelCase" or "PascalCase")가 있다.
Choosing Names
소유자보다 다른 팀의 누군가, 새로운 reader가 목적 또는 의도를 이해할 수 있는 이름으로 짓는다. 가로 길이 절약을 걱정하는 것보다 새로운 reader가 코드를 즉시 이해할 수 있도록 하는 것이 훨씬 더 중요하다.
이름이 사용되는 곳에서 context를 고려하자. 이름은 심지어 사용 가능하도록 만드는 코드로부터 멀리 사용될 지라도 설명할 수 있어야만
한다. 일반적으로, 이것은 descriptiveness는 이름이 보일 수 있는 범위에 비례함을 의미한다. header에 선언된 free function는 아마 header의 library를 언금해야만 하지만, local variable는 내부에서 무슨 역할을 하는지 않아야한다.
프로젝트 외부의 어떤 사람이 모를 수도 있는 약어(abbrevaiations)의 사용을 최소화하자. 단어 내부에서 글자를 삭제하는 약어를 만들지 말자. 약어가 사용될 때 하나의 "workd"를 대문자화 하는 것을 선호하자, e.g., StartRPC()보다 StartRpc(). thumb rule처럼, Wikipedia에 존재하는 약어는 괜찮다. loop indev의 i나 template parameter의 T 같은 특정 universally-known 약어도 괜찮다.
가장 자주 볼 수 있는 이름은 대부분의 이름 같지 않다; 적은 수의 "vocabulary" names는 너무 넓게 재사용되어 항상 context에서 존재한다. 이러한 이름들은 짧은 경향이 있거나, 약어와 전체 의미는 정의와 이름 내부에서 단어의 단순한 comment보다 명시적인 long-form 문서에서 비롯된다. E.g, absl::Status는 전용 devguide page를 가지고 있고 적절한 사용을 문서화한다. 아마 새로운 vocabulary 이름을 더 자주 정의하지는 않겠지만 만약 그런다면, 선택된 이름이 널리 사용될 때 잘 동작하는지 추가 디자인 리뷰를 받아보자.
class MyClass {
public:
int CountFooErrors(const std::vector<Foo>& foos) {
int n = 0; // Clear meaning given limited scope and context
for (const auto& foo : foos) {
// ...
++n;
}
return n;
}
// Function comment doesn't need to explain that this returns non-OK on
// failure as that is implied by the 'absl::Status' return type, but it
// might document behavior for some specific codes.
absl::Status DoSomethingImportant() {
std::string fqdn = ...; // Well-knwon abbreviation for Fully Qualified Domain Name
return absl::OkStatus();
}
private:
const int kMaxAllowedConnections = ...; // Clear meaning within context
};
class MyClass {
public:
int CountFooErrors(const std::vector<Foo>& foos) {
int total_number_of_foo_errors = 0; // Overly verbose given limited scope and context
for (int foo_index = 0; foo_index < foos.size(); ++foo_index) { // Use idiomativ `i`
...
++total_number_of_foo_errors;
}
return total_number_of_foo_errors;
}
// A return type with a generic name is unclear without widespread education.
Result DoSomethingImportant() {
int cstmr_id = ...; // Deletes internal letters
}
private:
const int kNum = ...; // Unclear meaning within broad scope
}
File Names
Filenames은 모두 소문자로 해야만 하고 underscores(_) 또는 dahses (-)를 포함해야만 한다. 프로젝트에서 사용되는 관습을 따르자. 만약 일관된 local pattern이 없다면, "_"를 선호한다.
허용하는 file name 예시:
- my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
- myusefulclass_test.cc // _unittest and _regtest are deprecated.
C++ files는 .cc filename extentsion을 가지며, header files는 .h extension을 가져야만 한다. 텍스적으로 특정 지점에서 포함되는 것에 의존하는 파일은 .inc로 끝나야만 한다 (see also section on self-contained headers).
db.h 같은 /usr/include에 이미 존재하는 filename를 사용하지 않는다.
일반적으로, filename을 매우 구체적으로 만든다. 예를 들어, logs.h 보다 http_server_logs.h를 사용한다. 매우 일반적인 경우는 호출되는 foo_bar.h와 foo_bar.cc 두 파일로 FooBar를 호출하는 class를 정의하는 것이다.
Type Names
type names은 대분자로 시작하며 각 새로운 단어마다 underscore 없이 대문자를 가진다: MyExcitingClass, MyExcitingEnum. 모든 type 이름은 - classes, structure, type aliases, enums, type template parameters - 같은 이름 관습을 가진다. 예를 들어,
// classes and structs
class UrlTable { ...
class UrlTableTest { ...
struct UrlTableProperties { ...
// typedefs
typedef hash_map<UrlTableProperties*, std::string> PropertisMap;
// using aliases
using PropertiesMap = hash_map<UrlTableProperties *, std::string>;
// enums
enum class UrlTableError { ...
Concept Names
Concept name은 type names과 같은 rule를 따른다.
Variable Names
variable(function parameter를 포함해)과 data member의 이름은 snake_case (단어 간 underscore를 가진 모두 소문자)이다. class 의 data menber(struct가 아닌) 추가로 뒤에 underscores를 가진다. 예를 들어: a_local_variable, a_struct _data_member, a_class_data_member_.
Common Variable names
예를 들어:
std::string table_name; // OK - snake_case.
std::string tableName; // Bad - mixed case.
Class Data Member
static과 non-static 모두 class의 data member는 nonmember variable과 동일하게 이름을 짓지만 뒤에 underscore를 가진다. static constant class member는 예외인데, naming constant의 규칙을 따라야만 한다.
class TableInfo {
public:
...
static const int kTableVersion = 3; // OK - constant naming.
...
private:
std::string table_name_; // OK - underscore at end.
static Pool<TableInfo>* pool_; // OK.
};
Struct Data Members
static과 non-static 모두 structs의 data members는 nonmember variable과 동일하게 이름 짓는다. class의 data member의 끝에 underscore을 가지지 않는다.
struct UrlTableProperties {
std::string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
Constant Names
constexpr 또는 const로 선언된 variable과 프로그램의 실행시간동안 고정된 값은 mixed case와 함께 "k"를 앞에 뭍인다. underscore는 분리를 위해 사용될 수 없는 대문자 위치에 흔치 않은 경우 분리하도록 사용할 수 있다. 예를 들어:
const int kDaysInAWeek = 7;
const int kAndroid8_0_0 = 24; // Android 8.0.0
static storage duration인 모든 variable는 (i.e., statics and globals, See Storage Duration for details) 이 방식으로 명명되어야 하며, static constant class data member와 template의 다른 instantiations가 다른 값을 가지는 template를 포함한다. 이러한 convention은 다른 storage class의 variable을 위한 옵션이며, e.g., automatic variables; 그렇지 않으면 대부분 variable naming rules를 적용한다. 예를 들어:
void ComputeFoo(absl::string_view suffix) {
// Either of these is acceptable.
const absl::string_view kPrefix = "prefix";
const absl::string_view prefix = "prefix";
...
}
void ComputeFoo(absl::string_view suffix) {
// Bad - different invocations of ComputeFoo give kCombined different values.
const std::string kCombined = absl::StrCat(kPrefix, suffix);
...
}
Function Names
일반적인 functions은 mixed case를 가진다; accessors와 mutator는 variables과 동일한 이름을 가진다.
functions은 대문자로 시작해야만 하고 새로운 다언마다 대문자를 가져야한다.
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
(같은 naming rule은 class- 그리고 API에 노출된 부분의 namespace-scope constants 그리고 함수 처럼 보이도록 의도된 것에 적용되며, function보다 object라는 사실은 중요하지 않은 implementation detail이기 때문이다)
Accessor와 mutators (get and set function)도 variable 같은 이름을 가질 수 있다. 이들은 주로 실제 member variable과 일치하지만 필수는 아니다. 예를 들어, int count()와 void set_count(int count).
Namespace Names
namespace 이름은 snake_case이다.
namespace 이름을 선택할 때, 이름은 unqualified aliases가 일반적으로 금지되기 때문에, namespace 외부에서 header 에 사용될 때 완전히 자격이되어야만 한다.
Top-level namesapce는 global하게 유일하고 인식할 수 있어야만 하기에 각각은 single project 또는 team에서 소유되어야만 하며 project 또는 team의 이름에 근거한 이름이어야만 한다. 주로, namespace에서 모든 코드는 namespace로 같은 이름의 하나 이상의 디렉터리 하위에 있어야만 한다.
nested namespace는 well-known top-level namespace의 이름을 피해야만 하며 특히 std와 absl 같은 이름은 피해야하는데, C++에서, nested namespace는 다른 namespace에서 이름 충돌을 보호해주지 못하기 때문이다.
Enumerator Names
enumerator(scoped and unscoped enums 모두)는 constant와 동일한, macors가 아닌 이름을 사용해야하만 한다. 즉, ENUM_NAME이 아닌 kEnumName을 사용한다.
enum class UrlTableError {
kOk = 0,
kOutOfMemory,
kMalformedInput,
};
enum class AlternateUrlTableError { // x
OK = 0,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2,
};
2009년 1월 까지, macros 처럼 enum 값을 명명하는 style이었다. 이는 enum values와 macro 간 충돌 문제를 야기한다. 그러므로 constant-style naming으로의 변경은 지정했다. 새로운 코드는 const-style naming을 사용해야만 한다.
Template Parameter Names
Template parameters는 category의 naming style를 따라야만 한다: type template parameter는 naming type rule를 따라야만 하며 non-type template parameters는 naming variable 또는 constant rule를 따라야만 한다.
Macro Names
macro를 정의하려고 하지 말자. 만약 그런다면 다음처럼 한다: MY_MACRO_THAT_SCARES_SMALL_CHILDREN_AND_ADULTS_ALIKE.
macro의 설명을 보자; 일반적인 macro에서는 사용되지 않는다. 하지만, 만약 절대적으로 필요하다면, 모두 project-specific prfix와 함께 대문자와 underscore로 명명해야만 한다.
#define MYPROJECT_ROUND(x) ...
Aliases
alias의 이름은 원래 이름이 나타나는 곳보다 정의되는 곳의 context에 적용되는 다른 새로운 이름과 같은 원리를 따른다.
Exceptions to Naming Rules
만약 기존의 C 또는 C++ entity의 아날로그적인 어떤 것을 명명한다면 기존 네이밍 관습을 따를 수 있다.
- bigopen() : function name, follows form of open()
- uint : typedef
- bigpos : struct or class, follow form of pos
- sparse_hash_map : STL-like entity; follows STL naming conventions
- LONGLONG_MAX : a constant, as in INT_MAX
'C++ > Google C++ Style Guide' 카테고리의 다른 글
| Exceptions to the Rules (0) | 2025.06.25 |
|---|---|
| Comments (2) | 2025.06.22 |
| Other C++ Features (0) | 2025.05.26 |
| Google-Specific Magic (0) | 2025.05.26 |
| Functions (1) | 2025.05.25 |