Naming

명명(naming) 및 주석(comment)을 포함한 모든 코드에서 포괄적인 언어를 사용하고 다른 프로그래머가 무례하거나 불쾌하다고 생각할 수 있는 용어는 사용하지 않는다.

  • such as "master" and "slave", "blacklist" and "whitelist", or "redline”

마찬가지로, 특정 사람을 언급하지 않는 한 중립적인 언어를 사용한다.

  • such as "they"/"they"/"their", "it"/"its"

General Naming Rules

가독성을 최우선으로, 이름은 명확해야하고 줄임말(프로젝트 외부에서 알기 어려운 약어)은 피한다.

  • 단어 내부에서 글자를 삭제하여 축약하는 방식은 사용하지 않음 (cstmr_id ❌ , customer_id ✅)
  • 해당 약어가 위키피디아에 있다면 사용해도 괜찮음

짧은 코드 범위에서는 n, i 같은 이름이 괜찮지만, 클래스 범위에서는 더 구체적인 이름을 사용해야 한다.

  • 짧은 코드 = 5줄 함수
  • kMaxAllowedConnections ✅, kNum ❌

대문자 약어는 하나의 단어처럼 사용

  • StartRpc() ✅, StartRPC() ❌

File Names

모두 소문자여야 하며 밑줄(_) 또는 대시(-)를 포함할 수 있다.

  • 프로젝트에서 사용하는 규칙이 우선이며, 규칙이 없다면 밑줄을 선호한다.
my_useful_class.cc
my-useful-class.cc
myusefulclass.cc
myusefulclass_test.cc // _unittest and _regtest are deprecated.

 

파일 확장자 규칙을 따른다.

파일 유형 확장자 설명
소스 파일 .cc C++ 소스 코드 파일
헤더 파일 .h C++ 헤더 파일
포함 전용 파일 .inc 특정 위치에서 포함되는 파일

 

고유하면서 구체적인 파일명을 사용하고 시스템 헤더 파일과 이름 충돌을 피한다. (db.h, string.h)

  • 너무 일반적이지 않고 구체적인 의미를 담아야한다.
  • 좋은 예시 vs 나쁜 예시
logs.h               ❌ (너무 일반적)
http_server_logs.h   ✅ (더 구체적인 의미 전달)
foo_bar.h            ✅ (FooBar 클래스를 정의하는 파일)
foo_bar.cc           ✅ (FooBar 클래스의 구현 파일)

Type Names

항상 대문자로 시작하고, 단어 사이에 _ (언더스코어)를 사용하지 않는다.

새로운 단어의 시작은 대문자로 구분한다(PascalCase)

모든 타입(Class, Struct, Type Alias, Enum, Template parameters)에 동일한 규칙을 적용한다.

// 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 class UrlTableError { ...

Variable Names

변수 및 함수 매개변수는 snake_case (소문자 + 언더스코어) 형식을 사용한다.

std::string table_name;  // ✅ 올바른 변수명
int max_value;  // ✅ 올바른 변수명
void process_data(int input_value) { ... }  // ✅ 함수 매개변수도 snake_case 사용

std::string tableName;  // ❌ camelCase 사용 금지
std::string TableName;  // ❌ PascalCase 사용 금지
void ProcessData(int InputValue) { ... }  // ❌ 변수명에 대문자 사용 금지

Class의 데이터 멤버는 snake_case_ (언더스코어로 끝나도록) 형식을 사용한다.

class TableInfo {
 private:
  std::string table_name_;  // ✅ 클래스 데이터 멤버는 _로 끝남
  int record_count_;  // ✅ 클래스 내부 변수는 _로 끝남
  static Pool<TableInfo>* pool_;  // ✅ 정적 변수도 동일한 규칙 적용
};

class TableInfo {
 private:
  std::string tableName;  // ❌ camelCase 사용 금지
  int recordCount;  // ❌ camelCase 사용 금지
  static Pool<TableInfo>* Pool;  // ❌ PascalCase 사용 금지
};

Struct 의 데이터 멤버는 일반 변수처럼 snake_case를 사용한다.

struct UrlTableProperties {
  std::string name;  // ✅ 일반 변수처럼 snake_case 사용
  int num_entries;  // ✅ 정수형 변수도 snake_case 사용
  static Pool<UrlTableProperties>* pool;  // ✅ 정적 변수도 동일한 규칙 적용
};

struct UrlTableProperties {
  std::string name_;  // ❌ 구조체에서는 `_`를 붙이지 않음
  int numEntries;  // ❌ camelCase 사용 금지
  static Pool<UrlTableProperties>* Pool_;  // ❌ PascalCase 및 `_` 사용 금지
};

Constant Names

constexpr 또는 const 변수는 k로 시작해야하며, 다음 단어부터는 CamelCase를 적용한다. (kCamelCase)

단어 구분이 어려운 경우에만 _(언더스코어)를 사용한다.

const int kDaysInAWeek = 7;  // ✅ 'k'로 시작, CamelCase 사용
constexpr double kPi = 3.14159;  // ✅ 'k' 사용, 프로그램 실행 중 변하지 않음
const int kAndroid8_0_0 = 24;  // ✅ 언더스코어 사용 (숫자 구분이 어려운 경우)

template <typename T>
constexpr int kMaxBufferSize = 1024;  // ✅ 템플릿 변수지만, 모든 인스턴스에서 상수로 유지됨

지역 변수의 경우에는 적용할 필요가 없다.

void ComputeFoo(absl::string_view suffix) {
  const absl::string_view kPrefix = "prefix";  // ✅ 사용 가능 (지역 변수지만, 프로그램 실행 중 변하지 않음)
  const absl::string_view prefix = "prefix";  // ✅ 일반적인 네이밍도 허용됨
}

void ComputeFoo(absl::string_view suffix) {
  const std::string kCombined = absl::StrCat(kPrefix, suffix);  // ❌ 잘못된 예제

Function Names

일반적인 함수는 PascalCase 를 사용해야 한다.

void AddTableEntry();  // ✅ 올바른 예시
void DeleteUrl();  // ✅ 올바른 예시
void OpenFileOrDie();  // ✅ 올바른 예시

void add_table_entry();  // ❌ 함수는 PascalCase를 사용해야 함
void delete_url();  // ❌ 함수 이름을 소문자로 작성하면 안 됨

단, getter와 setter의 경우에는 변수처럼 snake_case 를 사용한다.

class Counter {
 public:
  int count() const { return count_; }  // ✅ 변수처럼 `snake_case` 스타일 사용 가능
  void set_count(int count) { count_ = count; }  // ✅ setter도 변수 스타일 허용

 private:
  int count_;
};

Namespace Names

소문자로 작성하며, 단어 사이에는 _(언더스코어)를 사용한다.

최상위 네임스페이스는 프로젝트 또는 팀 이름을 반영해야한다.

namespace websearch {  // ✅ 프로젝트 이름을 최상위 네임스페이스로 사용
namespace index_util {  // ✅ 단어 구분 시 언더스코어 사용
void BuildIndex();
}  // namespace index_util
}  // namespace websearch

namespace WebSearch {  // ❌ 대문자로 시작하면 안 됨
namespace IndexUtil {  // ❌ CamelCase 사용 금지
void BuildIndex();
}  // namespace IndexUtil
}  // namespace WebSearch

잘 알려진 최상위 네임스페이스(std, boost 등)와 충돌하지 않도록 해야한다.

네임스페이스 이름을 축약하면 안된다.

namespace websearch {  // ✅ 최상위 네임스페이스 = 프로젝트 이름
namespace index {  // ✅ 서브 네임스페이스 (구체적인 역할을 반영)
void BuildIndex();
}  // namespace index
}  // namespace websearch

namespace util {  // ❌ "util"은 너무 일반적이며 충돌 가능성이 높음
namespace index {
void BuildIndex();
}  // namespace index
}  // namespace util

Enumerator Names

모든 열거형(enum) 값은 kCamelCase 스타일을 사용해야 한다.

enum class UrlTableError {
  kOk = 0,             // ✅ 올바른 네이밍
  kOutOfMemory,        // ✅ CamelCase + k 접두사
  kMalformedInput,     // ✅ CamelCase + k 접두사
};

enum class AlternateUrlTableError {
  OK = 0,              // ❌ 매크로처럼 작성하면 안 됨
  OUT_OF_MEMORY = 1,   
  MALFORMED_INPUT = 2, 
};

Macro Names

매크로는 가급적 사용하지 않는다. 꼭 필요한 경우 SCREAMING_SNAKE_CASE(대문자+ _ )를 사용한다.

매크로 이름에는 프로젝트 접두사(prefix)를 포함한다.

#define MYPROJECT_ROUND(x) ((x) + 0.5)  // ✅ 프로젝트 접두사 포함
#define MYPROJECT_MAX_BUFFER_SIZE 1024  // ✅ 프로젝트 접두사 포함
#define DEBUG_MODE 1  // ✅ 글로벌 매크로는 대문자로 작성

#define MyProjectRound(x) ((x) + 0.5)  // ❌ PascalCase 사용 금지
#define my_project_max_buffer_size 1024  // ❌ 소문자 사용 금지
#define DebugMode 1  // ❌ CamelCase 사용 금지

일반적인 코드에서는 constexpr, inline, const 등을 대신 사용할 것을 권장한다.

  • 예시 1. 매크로 사용의 좋지 않은 방법과 그 대안
#define SQUARE(x) ((x) * (x))  // ❌ 위험: x가 식일 경우 예상치 못한 동작 가능

int result = SQUARE(3 + 1);  // 예상: (3+1) * (3+1) = 16
// 실제 동작: (3 + 1 * 3 + 1) = 7 (잘못된 결과)

// constexpr을 사용하는 방법
constexpr int Square(int x) {
    return x * x;
}

Exceptions to Naming Rules

C 표준 라이브러리와 유사한 함수는 기존 스타일을 유지한다.

int bigopen(const char* filename, int flags); // ✅ 기존 open() 함수 스타일 유지
int BigOpen(const char* filename, int flags); // ❌ C 스타일 함수는 PascalCase 사용하지 않음

C 스타일 타입 정의 (typedef or using)은 기존 스타일을 유지한다.

typedef unsigned int uint;  // ✅ 기존 C 스타일 유지
using uint = unsigned int;  // ✅ C++ 스타일 유지

typedef unsigned int UnsignedInt;  // ❌ `typedef`는 일반적으로 소문자 사용

STL 스타일을 따르는 경우, 기존 스타일을 유지한다.

template <typename Key, typename Value>
class sparse_hash_map {
    // ✅ STL 스타일 유지
};

template <typename Key, typename Value>
class SparseHashMap {  // ❌ STL 스타일을 따르지 않음
};

상수(constexpr 또는 #define)는 기존 C 스타일(SCREAMING_SNAKE_CASE)을 유지해야 한다.

#define LONGLONG_MAX 9223372036854775807LL  // ✅ 기존 INT_MAX 스타일 유지
constexpr long long LONGLONG_MAX = 9223372036854775807LL;  // ✅ 같은 스타일 유지

constexpr long long LongLongMax = 9223372036854775807LL;  // ❌ 기존 C 스타일과 다름

+ Recent posts