코딩 표준
프로그래밍을 작성하는데 지켜야하는 프로그래밍 이름 규칙,
작성방법 등을 지정한 가이드 라인
Coding Style ,Coding Convention이라고도 함
좋은 코딩 표준
절대적으로 좋은 코딩 표준은 없다. 내가 사용한 코딩 표준이 항상 옮은것이 아니다.
중요한 것은 코딩 표준을 정하고 잘 따라는 것, 다른 프로젝트에 참여하게 되면 그 코딩 표준에 따를 것
프로젝트의 모든 코드는 한 사람이 만든 것처럼 보여져야하는게 최종 목표
언리얼 C++ 코딩 표준 공식 사이트
몇가지 코딩 표준을 알아보자.
1. 클래스 체계
클래스는 작성자보다는 읽는 사람을 염두에 두고 조작되어야 한다.
읽는 사람은 대부분 클래스의 퍼블릭 인터페이스를 사용할 것이므로, 퍼블릭 인터페이스에서 먼저 선언한 후 클래스의 프라이빗 구현이 뒤따라야 한다.
class HELLOUNREAL_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
private:
}
2. 명명 규칙
1. Casing
-
파스칼 케이싱 (Pascal Casing) : 합성어의 첫 글자를 대문자를 사용해 명명
-> 일반적으로 언리얼 C++에서 많이 사용
(ex) UnrealEngine
-
카멜(낙타) 케이싱(Camel Casing): 첫 합성어는 소문자로 나머지는 대문자를 사용해 명명
(ex) unrealEngine
-
스네이크 케이싱(Snake Casing) : 합성어 사이에 언더바(_)를 사용해 명명
-> 일반적으로 일반 C++ 개발에서 많이 쓰이는데, 언리얼C++에서는 위에서 말했듯이 한 사람이 제작한 것 처럼 보여야 하기에 파스칼 케이싱을 이용하자.
(ex) unreal_engine
2. 타입 이름에는 추가적으로 대문자로 이루어진 접두사를 포함하여 변수 이름과 구분
- 템플릿 클래스에는 접두사 T 포함
- UObject에서 상속받은 클래스는 접두사 U 포함
- AActor에서 상속받은 클래스는 접두사 A 포함
- SWidget에서 상속받은 클래스는 접두사 S 포함
- 추상적 인터페이스인 클래스는 접두사 I 포함
- 에픽의 개념이 유사한 클래스 타입(TModels 타입 특성에 첫 번째 argument로 사용)에는 접두사 C를 포함
- 열거형에는 접두사 E 포함
- 부울 변수에만 접두사 소문자 b 포함
- 그 외 대부분의 클래스는 접두사 F 포함, 일부 서브시스템 다른 글자 사용
- Typedef의 경우 해당 타입에 적합한 접두사 사용, ex) 구조체의 typedef인 경우 F, UObject의 typedef의 경우 U 사용
*특정 템플릿 인스턴스화의 typedef는 더 이상 템플릿이 아니며,
3. In/Out
- 접두사 In, 접두사 Out들을 써서 함수가 끝난 이후에 밖으로 나와서 사용이 될 것인지 아니면 입력으로만 사용 될것인지 둘 다 쓸 것인지
- 모든 파라미터에 In/Out을 다 하면 좋겠지만 되도록 많이 쓰도록 권장
4. 포터블 C++
- bool - 부울 값(부울 크기 추정 금지). BOOL 은 컴파일되지 않습니다.
- TCHAR - character(문자) (TCHAR 크기 추정 금지)
- uint8 - unsigned byte(부호 없는 바이트) (1바이트)
- int8 - signed byte(부호 있는 바이트) (1바이트)
- uint16 - unsigned shorts(부호 없는 short) (2바이트)
- int16 - signed short(부호 있는 short) (2바이트)
- uint32 - unsigned int(부호 없는 int) (4바이트)
- int32 - signed int(부호 있는 int) (4바이트)
- uint64 - unsigned quad word(부호 없는 쿼드 단어) (8바이트)
- int64 - signed quad word(부호 있는 쿼드 단어) (8바이트)
- float - 단정밀도 부동 소수점(4바이트)
- double - 배정밀도 부동 소수점(8바이트)
- PTRINT - 포인터를 가질 수 있는 정수(PTRINT 크기 추정 금지)
int형은 최소 32비트를 보장하기에 우리가 개발하는 게임이 메모리가 최적화 되려면 int타입을 지정해줘서 몇바이트를 사용하는지 알면 매우 좋다
5. C++ 표준 라이브러리는 사용하지 않는다
그러다보니 어떤 헤더라던지 몇가지 키워드들이 C++ 표준라이브러리와 곂치는게 있는데 이를 혼합하여 사용하지 않도록 하는게 중요하다.
6. Const 정확도
Const 문서이자 컴파일러 지시어(directive)이므로, 모든 코드는 const 정확도를 맞추어야 한다.
- 함수 argument가 함수에 의해 수정되지 않아 함수 argument를 const 포인터 또는 참조로 전달하는 경우
- 메서드가 오브젝트를 수정하지 않아 const로 플래그를 지정하는 경우
- 루프에서 컨테이너 수정을 하지 않아 const를 사용하여 컨테이너가 반복작업을 하는 경우
-> 간단히 말해 const 키워드를 붙여 보는 사람이 변경하면 안되는 인자,변수라는 것을 알도록 명시
-> 컴파일 단계에서 사전에 체크해서 코드의 정확성이 높아진다.
T* const Ptf = ...;
T& const Ref = ...;
래퍼런스에 대해서 const를 지정하는 것은 문법적으로 의모 없고 사용하면 안된다. 이미 래퍼런스로 선언하는 것 자체가 const가 지정 되어 있는 것이기 때문이다.
7. null은 nullptr 로 사용
8. auto는 거의 사용하지 말자
9. 클래스 이름에는 위에서 접두사가 붙었지만 파일 이름에는 빼는게 좋다.
10. 헤더에서는 중복된 헤더를 다시 복사하지 않게끔 지정하는 #pragma once 반드시 지정해줘야 한다.
11. 캡슐화
- 왠만하면 private으로 선언하고 getter , setter 함수로 접근할 수 있도록 만드는게 좋다.
12. Find in Files
- 포인터와 레퍼런스의 스페이스는 오른쪽에 한 칸만 두어야 한다.
그래야 빠르게 Find in Files를 사용 할 수있다.
ex) FShaerType Ptr (O)
FShaerType Ptr (X)
FShaerType * Ptr(X)
정리
- public 에서 private으로 이어지는 클래스 체계 준수
- 명명 규칙
- 파스칼 케이싱 사용
- 모든 클래스와 구조체에는 고유한 접두사가 있다.
- 코드의 명확성
- 파라미터에 가급적 In과 Out접두사를 사용해 명시
- const 지시자의 적극적인 활용
- 레퍼런스를 통한 복사 방지
- auto 키워드는 가급적 자제
- Find In Files의 활용
- 헤더 파일 및 #include 구문은 의존성을 최소화시켜 주의 깊게 다루기
자세한 내용은 공식 문서 참조