저번 항목에 이어서, 이번 항목은 리팩토링이다. 때 마침 리팩토링 관련 서적을 읽고 있던 터라, 그 필요성을 알게 되었었터라 "무엇을 어떻게 리팩토링 할까?" 에 대해서 생각해 보게 된다.
1 ) std::string의 멤버 함수들 중 멤버가 아니면 안되는 것들은 무엇이 있고, 왜 그런가?
멤버가 아니면 안되는 함수들은, 생성자, 소멸자, 할당 연산자, operator[] 연산자들이 있다. 이것은 멤버가 아니면, 어찌 할 수 없는 것들이다.
왜 생성자와 소멸자, operator=과, operator[] 연산자들은 왜 멤버로 놔야 할까?
여기서 중요한 개념을 짚어 봐야 한다. 스콧 마이어스는 "멤버로도 구현할 수 있고, 비친구 비멤버로도 구현 할 수 있는 함수가 있다면, 비친구 비멤버를 선호 해야 한다" 로 말했다.
이 이야기의 대표적인 사례는 바로 "algorithm header"에 있다. 만약 순차열 검색을 컨테이너 멤버 함수로 지정해 두었다면, 다른 컨테이너들은 그 구현을 다시 만들어야 할 것이다. 이것(멤버로 둔다는 것)은 재사용에 큰 제약을 걸게 되는 꼴이 된다.
그러니, 멤버로 두어야 할지 비멤버로 두어야 할지가 중요한 것이다.
그럼에도 불과하고, 멤버로 놔야 할 것들이 있는데, C++ 언어의 규칙상 반드시 멤버가 되어야할 연산자들이 있다. 그것이 바로 생성자와 소멸자, 그리고 각 operator 들이 있다.
여기서 멤버와 비멤버로 두어야 할 분류 규칙을 알아보자.
- 반드시 멤버가 되어야 할 것은 멤버로 한다.
- 클래스 내부에 접근할 필요가 있다면, 멤버로 하는 것을 선호한다.
- 그 외의 모든 경우들에서는 비멤버 비친구 함수로 만드는 것을 선호한다.
즉, 비멤버 비친구로 쉽게 할 수 있다면, 이것을 우선시하고, 이럴 수 없다면, 멤버로 두는 것이 좋다.
"생성자, 소멸자, operator=, operator[]"는 C++ 언어의 규칙과 클래스 내부에 접근할 필요성이 있기에, 멤버로 하는 하는 것이 좋다.(경험상 경우에 따라, 친구 비멤버 함수로 해야 할 경우도 더러 있더라...)
2 ) std::string의 멤버 함수들 중 멤버가 되는 게 좋은 것들은 무엇이고, 왜 그런가?
우선 함수들은 begin(), end(), rbegin(), rend(), size(), max_size(), capacity(), reserve(), swap(), c_str(), data(), get_allocator(), insert(), erase(), replace() 들이 있다. 이 것들은 아주 밀접하게 내부 데이터와 연결되어 있기 때문이다. 물론 이것들은 non-member friend function 으로 만들 수 있지만, 좀 귀찮아지고 보기도 껄끄러워 지기에, 멤버로 두는것이 더 좋을 것이다. 즉, 모든 조건이 동등할 경우, 가장 단순한 것을 택하는게 제일 좋다는 것이다.
3 ) std::string의 멤버 함수 at, clear, empty, length를 비멤버 비친구 함수로 제공해도 일반성이나 유용성이 손실되지 않으며, std::string의 나머지 인터페이스에 어떠한 영향도 미치지 않는 이유에 예를 들어라.
책의 예를 코드로 쓰자니 너무 귀찮다. : )
이 함수들은 non-member non-friend function 으로 구현 한다면, 다음의 이점을 갖게 된다.
1. 단순함, 멤버 함수가 적으면 적을 수록 클래스는 더 단순해 질 것이다.
2. 호환성, 통합된 인터페이스만 사용 하게 되면, 호환 알고리즘 작성이 더 쉽게 될 것이다.
3. 캡슐화, 내부를 더 적게 건들이니, 캡슐화가 향산 된다.
4. 이름공간 오염, : 이건 장단점도 아닌데, 이런 반박이 있기에 허브셔터가 쓴 것으로 보인다.
5. 일관성, 마이어스가 말했던 데로 비멤버, 멤버를 구분지어 만들었다면, 일관성을 갖게 된다.
총평
음~ 뭐 더 좋을 수 있다는 이야기이지, 그렇게 해야만 한다라는 이야기가 아니므로, 크게 연연해하지 말자.
'책 정리 > Exceptional C++ Style' 카테고리의 다른 글
Exceptional C++ Style (익셉셔널 C++ 스타일 : ECPPS ) 목차 (0) | 2009.02.10 |
---|---|
항목 40 : 일체적 클래스의 해악, 4부 : std::string 대미 ( 난이도 : 6 ) (0) | 2009.02.10 |
항목 39 : 일체적 클래스의 해악, 3부 : std::string 살 빼기 ( 난이도 : 5 ) (0) | 2009.02.04 |
항목 37 : 일체적 클래스의 해악, 1부 : std::string의 사례 ( 난이도 : 3 ) (0) | 2009.02.02 |
항목 36 : 생성되는 객체를 가진 공용체 ( 난이도 : 4 ) (0) | 2009.02.02 |
항목 35 : 일반적 콜백 ( 난이도 : 5 ) (0) | 2009.02.02 |
항목 34 : 색인 테이블 ( 난이도 : 5 ) (0) | 2009.02.01 |
항목 33 : 연산자 놀이 ( 난이도 : 4 ) (0) | 2009.02.01 |
항목 32 : 오타 또는 C++의 생소한 표기법 (0) | 2009.01.26 |
항목 31 : 이상한 코드 ( 난이도 : 4 ) (2) | 2009.01.26 |
최근댓글