# 설계 | 팀 코드 컨벤션

## 있어서 유용했던 컨벤션

팀 코드 컨벤션을 협의해야 합니다. 읽고, 관리하기 쉬운 코드를 작성하기 위한 일종의 코딩 스타일 규약으로, 팀이 어떤 스타일로 코딩을 할 것인가를 사전에 약속하는 것입니다. 저희가 사전에 협의한, 그리고 따로 협의하지는 않았지만 암묵적으로 지켰던 코드 컨벤션들은 다음과 같습니다.

{% hint style="info" %}
헤더 파일에서 private 접근자를 public 접근자보다 위에 놓는 점을 제외하면 대부분 c++의 코드 컨벤션 규칙들을 그대로 사용했습니다.
{% endhint %}

### 들여쓰기

* 띄어쓰기가 아니라 tab으로 한다.

### 변수명

* 클래스의 멤버 변수 앞에 m\_을 붙이며 소문자와 '\_'을 사용해 스네이크 표기로 명명한다.

### .함수

* 함수는 소문자로 시작하며 '\_'대신 대문자를 중간에 사용하여 카멜 표기로 명명한다.
* getter, setter 함수는 예외적으로 스네이크 표기로 명명하며 멤버변수와 이름을 일치시킨다. get\_m\_variable, set\_m\_variable과 같이 사용한다.
* constructor, setter의 인자명은 멤버변수명에서 m\_ 접두사만 제거하고 그대로 사용한다.

### 캐노니컬&#x20;

* 모든 클래스는 캐노니컬 폼을 준수한다.

### 괄호

```
const std::string& Server::get_m_server_name() const { return (this->m_server_name); }
```

* 한 줄로 쓸 수 있는 코드(주로 getter)는 한 줄에 쓴다.

```
	char *
	strdup(const char *s)
	{
```

* 리턴 자료형 타입은 함수 이름과 분리한다.
* 포인터 아스테리스크(\*)는 리턴 자료형 뒤에 붙인다.
* 여는 괄호는 독립적인 줄에 위치시킨다.

### 헤더파일 내 나열 순서

* enum, static 변수, 멤버 변수, private 멤버 메소드, 캐노니컬 폼, getter, setter, public 멤버 메소드, 중첩 예외 클래스 순서로 작성한다.
* 성격이 같은 변수/메소드들은 붙여서 기술하고, 성격이 다르다면 한 줄 개행하고 가급적 주석으로 표시한다.

### 소스파일 내 나열 순서

```
/* ************************************************************************** */
/* ------------------------------ CONSTRUCTOR ------------------------------- */
/* ************************************************************************** */
```

* 헤더파일과 같은 순서대로 작성한다.
* 성격이 다른 메소드들은 위와 같이 주석으로 영역을 명확하게 구분한다.

```
namespace {
	int	setEnv(char **env, int idx, std::string key, std::string val) {...}
	char **dupBaseEnvWithExtraSpace(Config *config, const Request& request) {...}
	std::string getCGIEnvValue(const Request& request, std::string token, Server *server = NULL, Config config = Config()) {...}
}

char**
Server::createCGIEnv(const Request& request)
{
	char **env = dupBaseEnvWithExtraSpace(m_config, request);
	int idx = ft::lenDoubleStr(m_config->get_m_base_env());
	setEnv(env, idx++, "AUTH_TYPE", "");
	setEnv(env, idx++, "CONTENT_LENGTH", getCGIEnvValue(request, "CONTENT_LENGTH"));
	...
}

```

* 헤더파일 내 명시된 멤버 메소드를 구현하기 위해 필요한 유틸 함수의 경우 프로젝트 전체에 쓰일만한 범용성이 있다면 libft에, 해당 소스 파일에서 여러 번 쓰일 가능성이 있다면 소스 파일 상단 util 섹션에 구현한다. 오직 하나의 멤버 메소드만을 위한 유틸 함수들은 위의 예제처럼 해당 메소드의 바로 위에 noname namespace를 만들어서 묶는다.

### 없어서 아쉬웠던 컨벤션들

반면, 미리 사전에 협의하지 못해서 아쉬웠던 컨벤션들은 주로 캐너니컬 폼에 관한 것으로 다음과 같습니다.

* 생성자 호출시 Member initializer를 통한 초기값 할당과 생성자 코드를 통한 초기값 할당을 어떤 기준으로 나눌 것인가?
* string, int, pointer 등 변수 자료형에 따른 디폴트 값 할당을 구체적으로 어디까지 어떻게 할 것인가?
* 할당자(operator=) 사용시 getter를 사용할 것인가?
* 모든 not public 멤버 변수에 대해 getter와 setter를 만들 것인가?
* 소멸자 안의 코드를 어떻게 선언할 것인가?
