[Effective C++] #18 인터페이스 설계
Scott Meyers의 "Effective C++"를 통해, C++ 구현에 필요한 개념들을 이해하고, 기록하기 위함입니다. 해당 항목은 4장 "설계 및 선언", 항목 18 "인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자"에 해당하는 내용입니다.
인터페이스
이번 항목에서 다룰 "인터페이스"란, C++에서 제공하는 "__interface" 혹은 추상 클래스로 특정 짓는 것이 아니라, 사용자가 코드 작성 시 사용하는 함수, 클래스, 그리고 템플릿 등을 의미합니다. 인터페이스의 정의가 의미하는 바, 그 자체를 의미합니다. 건물을 짓기 위한 기반 및 자재들이라고 볼 수 있죠. 책에서 설명하는 인터페이스 설계의 궁극적인 목적은 사용자가 원하는 동작 수행을 얻기 위해 인터페이스는 오히려 걸림돌들이 되는 것이라고 설명합니다. 여기서 "걸림돌"이란, 코드가 정상적인 궤도에 오르기 위해, 중간 과정에서 오용된 내용들에 대해여 항의하는 역할을 의미합니다. 말 그대로 "엉터리로 쓰기엔 어렵게"하자는 것이죠.
구체적인 인터페이스 설계
class Date {
public:
Date(int month, int day, int year); // Date 클래스의 생성자
...
};
Date d(30, 3, 1995); // 정상적인 함수 사용
Date d(3, 40, 1995); // 비 정상적인 함수 사용
위 예제 코드는 날짜를 의미하는 클래스의 생성자를 설계하고 있습니다. 먼저, 매개 변수의 전달 순서가 잘못될 우려가 있습니다. 따라서, 우리는 새로운 타입을 들여와 인터페이스를 보다 구체적으로 설계할 수 있습니다. 각 매개 변수마다 개별적으로 구조체를 정의하여 각각을 구분할 수 있도록 래퍼 타입을 생성하고 이들을 Date 클래스 생성자 안에 둘 수 있습니다. 여기서 래퍼란, 기본 자료형 데이터 하나를 멤버로 갖는 클래스를 의미합니다. 이 클래스 혹은 구조체는 기본 자료형의 데이터를 객체에 넣기 위해 제공하는 함수들을 갖고 있겠죠. 쉽게 말해, "int a = 5;"를 "int a = new integer(5);"로 표현할 수 있도록 하는 겁니다.
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;
};
clas Date {
public:
Date(const Month& m, const Day& d, const Year& y);
...
};
Date d(30, 3, 1995); //에러
Date d(Month(30), Day(3), Year(1995)); //타입 에러
Date d(Day(30), Month(3), Year(1995)); // 성공!
Date 클래스의 생성자는 각 매개 변수의 타입을 더욱 구체적으로 작성하도록 요구함으로써, 인터페이스의 잘못된 사용을 미연에 방지하는 것이 가능해집니다. 이 방법 이외에도, const 사용, 그리고 스마트 포인터 사용 등의 방법들이 있겠습니다.
Summary
- 궁극적인 목적은 인터페이스 사이의 일관성 유지입니다.
- 새로운 타입 만들기
- 타입에 대한 연산 제한하기
- 객체의 값에 대해 제약 걸기
- 자원 관리 작업
'언어 > Effective C++' 카테고리의 다른 글
[Effective C++] #20 값에 의한 전달, 참조자에 의한 전달 (0) | 2022.01.24 |
---|---|
[Effective C++] #19 클래스 설계 (0) | 2022.01.24 |
[Effective C++] #17 자원 관리 객체와 new 사용 (0) | 2022.01.17 |
[Effective C++] #16 new 및 delete 사용 (0) | 2022.01.17 |
[Effective C++] #15 자원 관리 객체, 자원에 대한 접근 (0) | 2022.01.15 |