반응형
Interface
- I.1: 인터페이스는 명확하게(explicit) 작성하라
- I.2: const가 아닌 전역변수를 지양하라
- I.3: 싱글톤 패턴을 지양하라
- I.4: 인터페이스가 타입 시스템을 정확하고 엄격하게 준수하도록 만들어라
- I.5: (하나라도 있다면) 사전 조건을 기술하라
- I.6: 사전 조건을 표현하고 싶다면 Expects()를 사용하라
- I.7: 사후 조건을 기술하라
- I.8: 사후 조건을 표현하고 싶다면 Ensures()를 사용하라
- I.9: 인터페이스가 템플릿이라면 컨셉(Concept)을 사용해서 매개 변수를 문서화하라
- I.10: 요구된 작업의 수행 실패를 알리기 위해 예외를 사용하라
- I.11: 원시 포인터(T*) 혹은 참조(T&)를 사용해 소유권을 전달하지 마라
- I.12: null이 되어선 안되는 포인터는 not_null로 선언하라
- I.13: 배열을 단일 포인터로 전달하지 마라
- I.22: 전역 개체가 복잡하게 초기화되지 않도록 하라
- I.23: 함수 인자 개수를 최소로 유지하라
- I.24: 같은 타입의 관련없는 매개 변수가 붙어있지 않도록 하라
- I.25: 클래스 계층에 대한 인터페이스로 추상 클래스를 사용하라
- I.26: 크로스 컴파일러 ABI를 원한다면 C 스타일 코드를 사용하라
- I.27: 변화가 적은(stable) ABI를 원한다면, Pimpl idiom 사용을 고려하라
- I.30: 규칙을 위반하는 코드는 캡슐화하라
인터페이스가 타입 시스템을 정확하고 엄격하게 준수하도록 만들어라
다음 예제에서 인터페이스만 보고는 time_to_blink이 무엇을 의미하는지 잘 모르겠다. 초를 의미할까? 밀리초를 의미할까?
void blink_led(int time_to_blink) // 나쁜 코드 -- 시간의 단위를 알 수 없다
{
// ...
// time_to_blink로 무언가 한다
// ...
}
void use()
{
blink_led(2);
}
C++11에 도입된 std::chrono::duration 타입은 지속 시간의 단위를 명시적으로 표현하는데 도움이 된다.
void blink_led(milliseconds time_to_blink) // 좋은 코드 -- 단위를 명확히 알 수 있다
{
// ...
// time_to_blink로 무언가 한다
// ...
}
void use()
{
blink_led(1500ms);
}
사전 조건(pre-condition)을 표현하고 싶다면 Expects()를 사용하라
int area(int height, int width)
{
Expects(height > 0 && width > 0); // good
if (height <= 0 || width <= 0) my_error(); // obscure
// ...
}
사후 조건을 표현하고 싶다면 Ensures()를 사용하라
int area(int height, int width)
{
auto res = height * width;
Ensures(res > 0);
return res;
}
null이 되어선 안되는 포인터는 not_null로 선언하라
int length(const char* p); // nullptr를 사용할 수 있는지 분명하지 않다.
length(nullptr); // 이렇게 사용해도 괜찮을까?
int length(not_null<const char*> p); // 좀 더 낫다: p가 nullptr가 되면 안된다는 것을 알 수 있다.
int length(const char* p); // p가 nullptr가 될수 있다고 가정해야 한다.
변화가 적은(stable) ABI를 원한다면, Pimpl idiom 사용을 고려하라
Pointer Implementation idiom 구현
class widget {
class impl;
std::unique_ptr<impl> pimpl;
public:
void draw(); // public API that will be forwarded to the implementation
widget(int); // defined in the implementation file
~widget(); // defined in the implementation file, where impl is a complete type
widget(widget&&) = default;
widget(const widget&) = delete;
widget& operator=(widget&&); // defined in the implementation file
widget& operator=(const widget&) = delete;
};
규칙을 위반하는 코드는 캡슐화하라
코드를 단순하고 안전하게 유지한다. 때때로 논리적이거나 성능상의 이유로 지저분하고 안전하지 않으며 오류를 일으키기 쉬운 기술들이 필요할 때도 있다.
그렇다면, 그 코드들은 인터페이스에 노출시키지 말고 캡슐화해라. 이는 보다 많은 프로그래머들이 세세하게 알 필요가 없도록 한다.
'프로그래밍 일반 > C++ Core Guildlines' 카테고리의 다른 글
C++ Core Guidlines 함수 (0) | 2019.11.11 |
---|---|
C++ Core Guidlines 철학 (0) | 2019.11.11 |
C++ Core Guidlines 소개 (0) | 2019.11.11 |