본문 바로가기

C++

[C++] 구글 C++ 코딩 스타일가이드 번역

언어는 약속이다.

코딩 또한 약속된 문법은 같지만 수많은 사람들이 본인만의 스타일로 코딩을 한다.

정답은 없지만 구글처럼 체계가 잘 잡힌 회사라면 코딩 규약도 깔끔하게 잘 잡혀있지 않을까?

모두가 100% 공감할 수는 없겠지만 그래도 구글이니 한번 알아보자.

 

구분선 아래는 개인적인 의견이 아닌 구글 공식 가이드의 번역임

 


일반적인 이름 규칙

다른 팀에서도 알아볼 수 있을 정도로 가독성이 좋으며 분명한 이름이어야 한다.

목적과 의도에 맞는 이름으로 지을 것.

이름이 길어지는 것은 신경쓰지 않는다. 그것보다 훨씬 중요한 것은 그 코드를 처음보는 사람을 즉시 이해 가능하게 하는 것이다.

단어 사이의 글자를 지워 약어로 만드는 것은 좋지않다. 단, 위키피디아에 실려 누구나 알 수 있을 정도의 약어라면 사용 가능. iteration variable 인 i 와 template의 T처럼 범용적으로 사용되는 약어라면 바람직하다.

 

파일 이름

파일 이름은 모두 소문자여야 하고 특수문자 중 언더스코어 ( _ ) 와 대쉬 ( - ) 만을 포함한다.

 

<예시>

  • my_useful_class.cc
  • my-useful-class.cc
  • myusefulclass.cc
  • myusefulclass_test.cc 

 

C++ 파일은 .cc 로 끝나야하며 헤더파일은 .h 로 끝나야한다.

/usr/include 에 이미 포함되어 있는 이름을 파일 이름으로서 사용하지 않는다. (e.g. db.h)

일반적으로 파일이름은 매우 구체적이어야 한다.

예를 들어서 logs.h 보다는 http_server_logs.h 가 더 바람직함.

관련 파일들은 쌍으로 짝지어 이름 짓는 것이 좋다. (e.g. foo_bar.h , foo_bar.cc)

 

타입 이름

타입이름은 언더스코어 ( _ ) 를 포함하지 않으며 대문자로 시작하고 각 단어의 시작도 대문자로 한다.

 

<예시>

  • class UrlTableTester { ...
  • typedef hash_map<UrlTableProperties *, std::string> PropertiesMap;
  • using PropertiesMap = hash_map<UrlTableProperties *, std::string>;
  • enum UrlTableErrors { ...

 

변수 이름

- 일반적인 변수 이름

모두 소문자로 이루어지며 각 단어사이는 언더스코어 ( _ ) 가 온다.

클래스의 멤버 변수의 이름은 언더스코어 ( _ ) 로 끝낸다. (구조체 제외)

 

<예시>

  • std::string table_name;
  • std::string a_struct_data_member;
  • std::string a_class_data_member_;

 

- 상수 이름

const 로 선언되는 상수는 "k" 를 붙혀 구분짓고 각 단어는 대문자로 시작한다.

언더스코어 ( _ ) 는 대문자로 구분할 수 없는 경우만 구분자로서 사용한다.

 

<예시>

  • const int kDaysInAWeek = 7;
  • const int Android8_0_0 = 24; // Android 8.0.0

 

- 함수 이름

보통의 함수는 대문자로 시작하며 각 단어도 대문자로 시작한다.

 

<예시>

  • AddTableEntry()
  • DeleteUrl()
  • OpenFileOrDie()

 

- 네임스페이스 이름

네임스페이스의 이름은 모두 소문자로 구성하며 최상위 네임스페이스 이름은 프로젝트 이름을 기반으로 한다.

잘 알려진 최상위 네임스페이스 이름과의 충돌을 피해서 짓는다. 보통의 경우 팀이나 구성원의 프로젝트에 관한 이름이 포함되어진다.

 

- 메크로 이름

솔직히 우리는 메크로를 많이 안쓰지 않는가.

그렇지만 정말 꼭 써야겠다면 모두 대문자로 쓰고 언더스코어 ( _ ) 로 연결한다.

 

<예시>

  • #define ROUND(x) ...
  • #define PI_ROUNDED 3.0

 

주석

주석은 코드의 가독성을 위해 필수적이다.

그렇지만 정말 좋은 코드는 주석없이도 스스로 읽히는 코드이다.

후에 누구든 주석을 읽을 수 있으니 일반적으로 작성되어야 한다.

 

- 일반적인 주석 스타일

// 와 /* */ 는 모두 바람직하되 일관성 있게 사용한다.

// 을 사용하는 것이 일반적이다.

 

- 클래스에 관한 주석

클래스가 어디에서 어떻게 사용되는지를 서술한다.

 

<예시>

// Iterates over the contents of a GargantuanTable.
// Example:
//     GargantuanTableIterator* iter = table->NewIterator();
//     for (iter->Seek("foo"); !iter->done(); iter->Next()) {
//     process(iter->key(), iter->value());
//     }
//     delete iter;
class GargantuanTableIterator { 
	... 
};

 

- 함수에 관한 주석

모든 함수는 선언되는 곳 앞에 어떻게 쓰이는지에 대한 주석이 있어야한다.

함수에 관한 주석은 동사로 시작하며 명령보다는 서술적으로 쓴다. (e.g. Opens the file)

// Returns an iterator for this table.  It is the client's
// responsibility to delete the iterator when it is done with it,
// and it must not use the iterator once the GargantuanTable object
// on which the iterator was created has been deleted.
//
// The iterator is initially positioned at the beginning of the table.
//
// This method is equivalent to:
//    Iterator* iter = table->NewIterator();
//    iter->Seek("");
//    return iter;
// If you are going to immediately seek to another place in the
// returned iterator, it will be faster to use NewIterator()
// and avoid the extra seek.
Iterator* GetIterator() const;

단, 불필요하게 너무 많이 쓰지 않고 애매한 것들만 명백하게 언급한다.

 

- TODO 주석

TODO 주석은 단기적이며 일시적으로만 사용한다.

TODO 와 같이 모두 대문자인 형식을 지켜서 쓰며 이는 후에 검색되어지기 위함이다.

TODO 는 작성자의 이름, 이메일, 버그 ID 등과 함께 사용하여 문제해결에 대한 참조를 해놓는다.

 

<예시>

// TODO(jwk70915@gmail.com): Use a "*" here for concatenation operator.
// TODO(Jinuk) change this to use relations.
// TODO(bug 12345): remove the "Last visitors" feature

 

함수를 대문자로 시작하는 등 누군가에겐 낯선 규칙일 수 있지만

협업하는 모든 인원이 문서의 내용을 잘 지키기만 한다면 정말 좋은 규칙이 될 것 같다.