P.1: Express ideas directly in code
이유
컴파일러는 여러분이 쓴 주석을 전혀 읽지 않으며, 세상에 게으른 프로그래머들이 많기에 여러분이 쓴 주석에는 그다지 주의를 기울이지 않을 수 있습니다.
그럼 어떻게 해야할까요? 문법적으로 여러분의 의도를 코드로 명확히 표현해야 합니다 (주석 뿐만 아니라 코드 구조상)
예시 (나쁜 예)
class Date {
public:
int month(); // 이렇게 쓰지 마세요
// ...
};
위 코드에서 멤버 함수의 선언 int month(); 만 보면 리턴 값이 달(month) 을 나타내는 상수 함수인지 명확히 알 수 없습니다.
게으른 프로그래머들과 컴파일러는 멤버 함수의 선언 int month(); 만 보고는 month() 함수가 달력을 한달 뒤로 넘기고 성공하면 1을 반환하고 실패하면 -1을 반환하려는건지, 단순히 오늘이 몇 월인지를 반환하려는 함수인지 알 수가 없습니다. (심지어 이번 달에 휴일이 몇 개인지 반환하려는 것처럼 보이기도 하네요..)
예시 (좋은 예)
class Date {
public:
Month month() const; // 이렇게 쓰세요
// ...
};
위는 좋은 방식으로 수정된 코드입니다. month() 멤버 함수가 반환하려는 값이 달(month) 이라는 사실이 명확히 드러나고 있으며, 상수 함수이므로 내부적으로 달력을 넘기지 않을 것이라는 것도 잘 드러나고 있습니다.
이렇게 생각을 코드로 명확히 표현하면 게으른 프로그래머들이 코드를 읽기도 편하고, 컴파일러가 여러분의 의도를 파악하여 실수를 막을 수도 있습니다.
예시 (나쁜 예)
void f(vector<string>& v)
{
string val;
cin >> val;
// ...
int index = -1; // 나쁜 코드, gsl::index 를 쓰는게 좋습니다
for (int i = 0; i < v.size(); ++i) {
if (v[i] == val) {
index = i;
break;
}
}
// ...
}
음.. 위 코드를 볼까요? val 값을 하나 받고 그것으로 무언가(?) 하고 있습니다.
어디보자 어디보자.. 반복문을 돌면서 v 벡터에서 문자열을 하나씩 뽑아서 val 과 비교하고 있는 것처럼 보이네요..
index 는 뭐고 i 는 또 뭐고 아이고.. index 가 -1로 남아있으면 문자열을 못 찾은 걸로 생각하면 되는걸까요?
GSL(Guidelines Support Library) 을 사용해서 명확히 배열만을 인덱싱 하고자 표현 한다면 더욱 좋을 것 같은데 그것보다 반복문이 의도한 바가 명확히 드러나지 않는게 더 큰 문제입니다.
예시 (좋은 예)
void f(vector<string>& v)
{
string val;
cin >> val;
// ...
auto p = find(begin(v), end(v), val); // better
// ...
}
잘 디자인된 라이브러리(STL)를 사용하면 원시적인 언어 기능 (for, while) 들을 이용하는 것보다 프로그래머의 의도가 명확하게 드러나는 이쁜 코드를 작성할 수 있습니다.
예시 (나쁜 예)
change_speed(double s); // s 는 대체 뭘 의미할까요?
// ...
change_speed(2.3);
위 double s 만 보고는 프로그래머가 어떤 타입을 표현하고 싶어했는지 모호합니다.
step, speed, seed(random seed), ... 여러가지 단어로 해석될 수도 있어 보이고,
speed 라고 하더라도 단위가 초속인지, 시속인지, 시속이면 km/h 인지, cm/h 인지 알 수 없습니다.
예시 (좋은 예)
change_speed(Speed s); // s 가 의미하는 바가 명확합니다!
// ...
change_speed(2.3); // 에러 : 단위가 누락됨
change_speed(23_m / 10s); // 미터 / 초 로 속도를 계산하고 있군요
이제 s 는 속도를 나타내는 것이 명확해졌습니다.
C++11 User-defined literals 를 사용하면 속도의 단위도 명확하게 다루고 계산할 수 있습니다.
정리
const 를 일관되게 사용하세요. (멤버 함수가 개체를 수정하는지, 포인터나 참조로 전달된 인수를 내부적으로 수정하는지 나타내기)
묵시적 타입 변환에 의존하지 마세요. (직접 타입 정의하기)
가능하다면 잘 만들어진 표준 라이브러리를 사용하세요. (STL, GSL, Boost, ...)
주석에만 의존하지 마세요. 명쾌하게 프로그래머의 생각을 코드로 표현하는 방법은 많습니다.
'C++' 카테고리의 다른 글
[C++ Core Guidelines] P.5 가급적 컴파일 타임에 코드가 평가될 수 있도록 만들자 (0) | 2024.04.11 |
---|---|
[C++ Core Guidelines] P.4 가급적 컴파일 타임 타입을 사용하자 (0) | 2024.04.07 |
[C++ Core Guidelines] P.2 ISO 표준 C++ 코드로 작성하자 (0) | 2024.03.30 |
[C++ Core Guidelines] 번역에 앞서 (1) | 2024.03.26 |
[C++] 학습시 참고 할만한 사이트 정리 (0) | 2024.03.21 |