방프리

17.07.21. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목18) 본문

C++/Effective C++

17.07.21. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목18)

방프리 2020. 1. 9. 18:38

항목 18 : 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자

 

프로그래머도 사람입니다. 언제나 실수하기 마련이죠. 하지만 이 실수가 굉장히 큰 버그를 만들 수 도 있습니다.

예를 들어보겠습니다.

class Date

{

public:

Date(int month, int day, int year);

};

Date d(30, 3, 1995); // 날짜와 월을 바꾸어서 초기화

만약 이렇게 잘못된 데이터가 들어갈 경우 그 결과는.... 여러분의 상상에 맡기겠습니다. 

이러한 잘못된 코드를 최소한으로 줄여야 하기 때문에 맨 처음부터 인터페이스 설계를 탄탄하게 만들어야 합니다.

struct Day {

explicit Day (int d)

 : val(d)

 

  int val;

};

struct Month {

explicit Month (int m)

 : val(m)

 

  int val;

};

struct Year {

explicit Year (int y)

 : val(y)

 

  int val;

};

class Date

{

public:

Date(const Month& m, const Day& d, const Year& y);

...

};

 

Date d(Month(3), Day(30), Year(1995));

만약 구조체를 통해 인터페이스를 설계했다면 완벽하진 않지만 그래도 오류를 최소화 시킬 수 있게 만들 수 있습니다.

이외에도 enum을 통해 구현할 수 있지만....

타입 안전성으로는 좋지 못하기 때문에 권장하진 않습니다.

이 책의 필자는 tr1::shared_ptr을 굉장히 좋아하는 것 같습니다. 이번 항목에서도 해결책으로 shared_ptr을 주장했거든요

shared_ptr이 가지고 있는 장점이 굉장히 크지만 DLL 파일의 충돌에서도 굉장한 성능을 보입니다.

이것만 가지고도 tr1::shared_ptr은 이 항목의 문제를 해결할 수 있습니다.

(애초에 DLL 파일을 많이 사용하는 것을 추천하진 않습니다.)

 

이것만은 잊지 말자!

* 좋은 인터페이스는 제대로 쓰기에 쉬우며 엉터리로 쓰기에 어렵습니다. 인터페이스를 만들 때는 이 특성을

지닐 수 있도록 고민하고 또 고민합시다.

* 인터페이스의 올바른 사용을 이끄는 방법으로는 인터페이스 사이의 일관성 잡아주기, 그리고 기본제공 타입과의

동작 호환성 유지하기가 있습니다.

* 사용자의 실수를 방지하는 방법으로는 새로운 타입 만들기, 타입에 대한 연산ㅇ르 제한하기, 객체의 값에 대해

제약 걸기, 자원 관리 작업을 사용자 책임으로 놓지 않기가 있습니다.

* tr1::shared_ptr은 사용자 정의 삭제자를 지원합니다. 이 특징 때문에 tr1::shared_ptr은 교차 DLL 문제를 막아 주며, 

뮤텍스 등을 자동으로 잠금 해제하는 데(항목 14 참조) 쓸 수 있습니다.

Comments