함수도 인터페이스, 클레스도 인터페이스, 템플릿도 인터페이스다. 인터페이스는 사용자가 당신의 코드와 만니장성을 쌓는 접선수단이다. 인터페이스 개발시 사용자가 저지를 만한 실수의 종류를 미리 머리에 넣어두고 있어야 한다.
1. 매개변수의 전달 순서가 잘못
2. 유효한 값의 범위를 벗어나는 어이없는 숫자일 경우
* 인터페이스의 올바른 사용을 이끄는 방법으로는 인터페이스 사이의 일관성 잡아주기, 그리고 기본제공 타입과의 동작 호환성 유지하기가 있습니다.
* 사용자의 실수를 방지하는 방법으로는 새로운 타입 만들기, 타입에 대한 연산을 제한하기, 객체의 값에 대해 제약 걸기, 자원 관리 작업을 사용자 책임으로 놓지 않기가 있습니다.
class Date { public: Date(int month, int day, int year); ... }; Date d(30, 3, 1995); // 30월 3일 ? 하지만 Compile 단계에서는 통과 Date d(3, 40, 1995); // 3월 40일 ? 하지만 Compile 단계에서는 통과 // ------------------------------------ struct Day { explicit Day(int d) : val(d) {} int val; }; struct Month { explicit Month(int d) : val(d) {} int val; }; struct Year { explicit Year(int d) : val(d) {} int val; }; class Date { public: Date(const Month& m, const Day& d, const Year& y); ... }; Date d(Month(3), Day(30), Year(1995)); // 이렇게 안쓰면 Compile 단계에서 Error 발생
타입 안전성이 신경 쓰인다면 유효한 Month의 집합을 미리 정의해 두어도 괜찮다.
class Month { public: static Month Jan() { return Month(1); } ... static Month Dec() { return Month(12); } private explicit Month(int m); }; Date d(Month::Mar(), Day(30), Year(1995));
그렇게 하지 않을 번듯한 이유가 없다면 사용자 정의 타입은 기본제공 타입처럼 동작하게 만들어져야 한다. 예를 들어서 int 타입의 성질은 이미 다 알고 있는 사람들이 많으니깐, int 처럼 동작하게 만드는 것이 좋다. (When in doubt, do as the ints do)
Java의 경우 배열에는 length라는 property 사용하고, String에는 length라는 method를 사용하며, List에는 size라는 method를 사용한다.
.NET에서는 Array에는 length라는 property, ArrayList에는 Count라는 property를 사용한다.
물론 IDE(Integrated Development Environment)가 좋아져서 쉽게 찾아주긴 하지만, 한 마리 새끼 양처럼 순한 개발자가 받은 마음의 상처는 IDE 할아버지라도 완전히 없앨 수는 없다.
* tr1::shared_ptr은 사용자 정의 삭제자를 지원합니다. 이 특징 때문에 tr1::shared_ptr은 교차 DLL 문제를 막아 주며, Mutex 등을 자동으로 잠금 해제하는데 쓸 수 있습니다.
tr1::shared_ptr을 반환하는 구조는 자원 해제에 관련된 상당수의 사용자 실수를 사전 봉쇄활 수도 있어서 여러모로 인터페이스 설계자에게 좋다.
댓글 없음:
댓글 쓰기