DKGL Coding Conventions. [DRAFT/작업중]
https://dkscript.com/wiki/CodingConventions 여기서 가져옴.
Coding
{ 와 } 는 다른 라인에 위치하게 되는 경우는 new-line 후에 한다. https://en.wikipedia.org/wiki/Indentation_style#Allman_style
- 올바른 방법
if (expr) { // 되도록 이렇게. }
- 올바르지 않음
if (expr) { // 특별한 이유가 없다면 이렇게 하지 말것. }
- 예외: 짧은것, 한줄에 한해서는 허용함.
if (expr) {... } // 한줄, 짧은것에 대하여 허용
struct ABC { int Number() const { return 10; } // 허용 };
주석
- 의미없는 주석, 코드와 동일한 주석은 필요없다.
- 잘못된 예제들:
void GenerateItems(); // 아이템 생성.
for (int i = 0; i < 100; ++i) // 일단 100까지 루프를 돌아보자 { Item* item = FindItem(i); if (item) DoSomethingWithItem(item); // 아이템 찾음. 뭔가 하자. }
class UserIdGenerator; // 사용자ID 생성기, ID 생성할때 쓰면 된다.
- 나중에 다시 봤을때 까먹을것 같은곳에 쓰자. (하지만 주석 없으면 안될정도로 복잡하면 그것도 문제)
- 유용한 정보를 담은 주석
void SimulateHardwarePrecision(); // A 사 하드웨어에는 뭔가 부족해서 문제가 있었다.. 등등 유용한 정보 void GenerateEarOfKing(); // 유저와 플랫폼에 따라 결과가 다름. 주의할것.. 기타등등
- 기타
void DrawObjectFast(); // TODO: 빠르게 그리는 함수. 현재 미구현, 빨리 구현할 것. bool CalculateComplex(); // FIXME: 어떠어떠한 상황에서 크래시 발생, 수정할것.
Naming
매크로를 제외하고 기본적으로 CamelCase 를 따른다. 의미 있는 이름을 사용해야 한다. 함수는 동사형, 변수는 명사형을 권장함.
리턴값이 함수의 역할에 해당하는 값이라면 Get 으로 시작하지 않는다.
- 올바른 이름
String Name() { return this->name; }
- 올바르지 않음
String GetName() { return this->name; }
- 예외: 허용 가능한 경우 (리턴값이 함수 수행에 대한 결과값)
bool GetName(String& name) noexcept { if (this->name != nullptr) { name = this->name; return true; } return false; // Cannot find name property! but I don't want to throw an exception. }
함수, 상수, 타입
대문자로 시작한다. (CamelCase)
변수, 인스턴스
- 소문자로 시작함. (camelCase)
- lambdas 도 변수와 동일하게 취급한다. (캡춰를 하지 않는 전역함수의 lambdas 도 동일)
매크로
- 대문자와 _ 로 구성함 (UPPER_CASE_WITH_UNDERSCORES)
#define SOME_MACRO_FOR_SOMETHING 20
기타
- lambda 는 소문자로 (인스턴스 취급한다) 템플릿 매개변수도 상수로 취급한다.
auto lambda = [](){};
template <int Num> struct Number { };
의미있는 이름 짓기
- 이름은 그 이름을 가진'것'이 무슨 역할을 하는지 그 의미를 가져야 한다.
- 애매한 이름은 피해야 한다.
- 역할이 애매모호한 이름 (무슨 역할을 하는지 구체적으로 표현하기 어려운 이름들)
- ...Manager
- ...System
- ...Processor
- 역할이 애매모호한 이름 (무슨 역할을 하는지 구체적으로 표현하기 어려운 이름들)
- 추상적인 이름은 되도록 사용하지 말것!
- 추상적인 이름은 '제품명' 또는 '프로젝트명 (코드명)' 으로 쓰는것임.
- 소스코드에서는 쓰면 안된다.
- 추상적인 이름은 '제품명' 또는 '프로젝트명 (코드명)' 으로 쓰는것임.
- 단순한 이름을 가질 수 있는 클래스가 설계하기 좋다.
- 설계하기 좋은 클래스는 사용하기도 쉽고 유용하다.
- 클래스와 함수는 한가지의 일만 해야 한다.
잘못된 예제:
int UploadFileAndOpenDatabaseConnection(file, db, options...)
void GenerateThumbnailImageFromUserFiles(fileId...)
- 단순한것이 좋은것이다.
- 클래스나 함수가 주어진 이름과 관련 없는 일을 하는것은 잘못 작성된 코드이다.
- 예:
// 아래 코드는 잘못된 코드이다. 따라하지 말것. bool VerifyUserProperty(int uid) { User* user = FindUserByUid(uid); if (user) { if (user->IsTesterId() && user->property.FindItem("Money") == nullptr) { // Fix user property! // Testers should be able to successfully purchase any item. user->property.SetItem("Money", 4000); } return true; // user property is fine. } return false; // cannot find user } // Purchase item code. User* customer = FindAnyUserByNames("James;John;Bob"); if (VerifyUserProperty(customer)) { Item* itemPurchased = customer->PurchaseItem("a luxury bag"); if (itemPurchased) { PrintReceipt(itemPurchased->ItemId()); } }
- 무엇이 잘못되었는지 바로 알수 있어야 한다.
- 예: