728x90
UE5
언리얼 c++ 코딩 표준
코딩 표준(Coding Standard)
- 프로그래밍을 작성하는데 지켜야 하는 프로그래밍 이름 규칙, 작성 방법등을 지정한 가이드라인
- 코딩 스타일, 코딩 컨벤션이라고도 한다.
클래스 체계
- 클래스 체계는 작성하는 사람 보다는 읽는 사람을 염두에 두고 체계를 잡아야 한다. 읽는 사람 대부분은 클래스의 공용 인터페이스를 쓸 것이기에, public을 먼저 선언하고, 그 후 클래스의 private 구현이 뒤따른다.
저작권 공지
- 에픽이 배포용으로 제공한 (.h, .cpp, .xaml 등의) 소스 파일은 반드시 파일의 첫 줄에 저작권 공지를 포함시켜야 한다. 공지의 포맷은 반드시 다음과 같아야 한다.
- Copyright Epic Games, Inc. All Rights Reserved.
- 이 줄이 없거나 포맷이 다르게 되어 있다면, CIS가 오류를 내고 중단시킨다.
작명 규칙
- 모든 코드와 코멘트는 미국 영어 철자법과 문법을 사용해야 한다.
- (유형 이름이나 변수 이름 등) 이름 내 각 단어의 첫 글자는 대문자로 써야 하며, 단어 사이에 보통은 밑줄이 없다. Health 와 UPrimitiveComponent 정도를 예로 들 수 있다.
- 변수의 이름과 구분하기 위해 유형 이름을 대문자 한 글자로 나타내는 접두사를 붙인다. 예를 들어 FSkin 이 유형 이름이고, Skin 은 FSkin 의 인스턴스이다.
- 템플릿 클래스 접두사는 T이다.
- UObject 에서 상속하는 클래스 접두사는 U이다.
- AActor 에서 상속하는 클래스 접두사는 A이다.
- SWidget 에서 상속하는 클래스 접두사는 S이다.
- 추상 인터페이스인 클래스 접두사는 I이다.
- Enum(열거형)의 접두사는 E이다.
- Boolean(부울) 변수의 접두사는 b이다.
- 그 외 대부분 클래스의 접두사는 F이나, 일부 서브시스템은 다른 글자를 사용하기도 한다.
- Typedef 접두사는 적합한 유형을 붙여야 한다. 구조체의 typedef인 경우 F, UObject 등의 typedef인 경우 U이다.
- 특정 템플릿 인스턴스의 typedef는 더이상 템플릿이 아니라 그에 맞는 접두사를 붙여야 한다.
- C#에서는 접두사가 생략된다.
- UnrealHeaderTool(언리얼 헤더 툴)은 대부분의 경우 올바른 접두사가 필수이므로, 제대로 붙여주는 것이 중요하다.
- 유형과 변수명은 명사이다.
- 메서드 이름은 동사로 그 메서드가 하는 일이나, 하는 일이 딱히 없는 경우 반환값을 설명한다.
- 변수, 메서드, 클래스 이름은 명확하고 애매하지 않으며 서술적이여야 한다. 이름의 범위가 클 수록, 서술적인 좋은 이름의 중요성이 역시 커진다. 과도한 축약은 피해야 한다.
- 프로시져(반환값이 없는 함수)는 강한 동사 뒤에 오브젝트를 붙여 써야 한다.
코멘트
- 코멘트는 소통이고, 소통은 중요하다.
- 자체적으로 설명이 되는 코드를 작성해라.
- 도움이 되는 코드를 작성해라
- 나쁜 코드에 코멘트를 달지 마라. 그냥 다시 작성해라
- 코드를 모순되게 만들지 마라
람다 및 무명 함수
- 람다는 자유롭게 사용할 수 있다. 최적의 사용법은 길이상 두 구문 정도가 되어야 한다. 특히나 규모가 더 큰 표현식이나 구문의 일부로 사용될 때, 예를 들면 범용 알고리즘의 술부(predicates)에 사용될 때는 더욱 그러해야 한다.
- 주의할 점이라면, 스테이트풀 람다는 많이 사용하는 경향이 있는 함수 포인터에 할당할 수 없다.
코드 포맷
- 중괄호
- 단일 문장 블록에도 항상 중괄호를 포함시켜라
- if (bThing) { return; }
If-Else
- if-else 문의 각 실행 블록은 중괄호로 묶어야 한다. 이는 편집상의 실수를 방지하기 위함으로, 중괄호를 사용하지 않은 경우 다른 사람이 의도치 않게 if 블록에다 다른 줄을 추가하게 될 수가 있다.
탭 및 들여쓰기
- 코드 들여쓰기 표준이다.
- 실행 블록별로 코드를 들여써라
- 줄 시작 부분의 공백은 스페이스가 아니라 탭을 사용하고, 탭 크기는 4자로 설정한다.
- C# 코드를 작성한다면 스페이스가 아니라 탭을 사용해라
Switch 문
- 빈 케이스를 제외하고, switch case 문에서는 다음 케이스로 넘어가는지를 명시적으로 밝혀줘야 한다. 각각의 경우마다 break를 넣던가, fall through 코멘트를 달아주어라. 다른 코드 제어 - 이동 명령(return, continue)도 괜찮다.
- default case는 항상 만들어 두고, 다른 사람이 그 뒤에 새로운 케이스를 추가할 때에 대비해 break도 넣어둬라.
switch (condition)
{
case 1:
...
// falls through
case 2:
...
break;
case 3:
...
return;
case 4:
case 5:
...
break;
default:
break;
}
네임스페이스
- 해당하는 경우 네임스페이스를 사용하여 클래스, 함수 및 변수를 구성할 수 있다. 네임스페이스를 사용하는 경우 아래 규칙을 따른다.
- 대부분의 UE 코드는 현재 글로벌 네임스페이스에 둘러싸여 있지 않다. 특히나 서드 파티 코드를 사용하거나 포함할 떄는 전역 범위에서 충돌이 일어나지 않도록 주의를 기울여야 한다.
- 언리얼 헤더 툴에는 네임 스페이스가 지원되지 않으므로, UCLASS , USTRUCT 등을 정의할 때는 사용할 수 없다.
- UCLASSes , USTRUCTs 등이 아닌 새 API는 적어도 UE:: 네임스페이스에 배치해야 하며 이상적으로는 중첩된 네임스페이스를 사용하는 것이 좋다.
- Using 선언
- 전역 범위에는 using 선언을, .cpp 파일에서도 넣지않아야 한다.(unity빌드 시스템에 문제가 생긴다.)
- 다른 네임스페이스 안이나 함수 바디 안에는 using 선언을 넣어도 괜찮다.
- 네임스페이스 안에 using 선언을 넣는 경우, 행당 네임스페이스 동일 변환 단위 내 다른 곳으로 이어지게 된다. 일관성만 있으면 괜찮을 것이다.
- 오직 위 규칙을 따를 때만 헤더 파일에서 using 선언을 사용해도 안전하다.
- 앞서 선언된 유형은 각각의 네임스페이스 안에서 선언해 줘야 한다. 그렇게 하지 않으면 링크 오류가 난다.
- 한 네임스페이스 안에 다수의 클래스/유형을 선언하면, 다른 전역 범위의 클래스에서 사용하기가 어려울 수 있다.
- using 선언을 사용해서 네임스페이스 안의 특정 변수만 자신의 범위로 에일리어싱 할 수 있다. 그러나 언리얼 코드에서는 보통 그렇게 하지 않는다.
- 매크로는 네임스페이스 내에 있을 수 없지만, 대신 UE_ 접두사를 붙이면 된다.
물리적 종속성
- 파일 이름에는 가급적 접두사를 붙이지 않는 것이 좋다. 예를 들면 UScene.cpp 보다는 Scene.cpp 가 좋다.
- 모든 헤더는 #pragma once 디렉티브(지시자)로 복수의 include를 방지해야 한다. 참고로 요즘의 컴파일러는 전부 #pragma once 를 지원한다.
- 일반적으로 물리적 결합을 최소화 시켜라. 특히, 다른 헤더의 표준 라이브러리 헤더를 include 하지 마라
- 헤더 include 대신 앞선 선언이 가능하면, 그리하라.
- include 할 때는 가급적 세세하게 해라. 예를 들어 Core.h를 include하지 말고, Core의 헤더 중 정의가 필요한 특정 부분을 include해라.
- 자신이 include한 다른 헤더에 의해 간접적으로 include되는 헤더에 의존하지 마라.
- 다른 헤더를 통해 include시키기 보다는, 필요한 것을 전부 include해라
- 모듈에는 private과 public 소스 디렉터리가 있다. 다른 모듈이 필요로 하는 정의는 public 디렉터리의 헤더에 있어야 한다. 그 외 모든 것은 private 디렉터리에 있어야 할 것이다. 참고로 구형 언리얼 모듈의 경우 이 디렉터리는 ‘Src’ 및 ‘Inc’로 불리기도 하는데, 이름만 그럴 뿐 같은 방식으로 프라이빗 코드와 퍼블릭 코드를 구분하기 위함일 뿐이지, 헤더 파일을 소스 파일과 구분하기 위함은 아니다.
- 인라인 함수는 너무 많이 사용하지 말아라. 사용하지 않는 파일에 있어도 강제로 리빌드 시키기 때문이다.
- FORCEINLINE 사용에 있어서는 조금 더 보수적이어야 한다. 모든 코드와 로컬 변수는 호출하는 함수로 확장되어, 큰 함수에서 발생하는 것과 동일한 빌드 시간 문제가 생긴다.
캡슐화
- 보호 키워드로 캡슐화 시켜라. 클래스 멤버는 클래스의 public/protected 인터페이스 일부가 아닌 한, 거의 항상 private으로 선언해야 한다. 상황에 따라 판단을 잘하되, 접근자가 없으면 나중에 기존 프로젝트와 플러그인 해체 없이 리팩터링 작업을 하는 것이 힘들어 진다는 점을 염두해야 한다.
- 특정 칸은 파생 클래스에서만 사용하도록 의도된 경우, private으로 만들어 보호된 접근자를 제공해줘야 한다.
- 더 이상 파생시킬 클래스가 아닌 경우 final을 사용해라
일반적인 스타일 문제
- 종속성 거리를 최소화 해라
- 메서드는 가급적 하위 메서드로 분할해라
- 함수 선언이나 함수 호출 위치에서 함수의 이름과 인수 목록에 선행되는 괄호 사이에 스페이스를 추가하지 마라.
- 컴파일러 경고에 주의를 기울여라.
- 파일 끝에 빈 줄을 하나 놔둬라. 모든 .cpp 와 .h 파일은 빈 줄이 있어야 gcc에 제대로 돌아간다.
- 스트링 리터럴 주변에는 항상 TEXT() 매크로를 사용해라. 그렇지 않으면, 코드가 리터럴에서 FString 을 생성하는 경우 원치 않는 스트링 변환 프로세스가 유발된다.
728x90
'UE5' 카테고리의 다른 글
Add Mapping Context (0) | 2024.10.30 |
---|---|
Cast to PlayerController (0) | 2024.10.30 |
Event BeginPlay (0) | 2024.10.30 |
UE5. 패킷 데이터 직렬화(버퍼 생성) (0) | 2024.10.30 |
UE5. 클래스 만들기, 컴파일, 로그 (1) | 2024.09.30 |