Skip to content
 

C++ 클래스 설계

C++을 사용하면서 자신만의 클래스를 설계하는 경우가 요즘은 참 드문거 같다. 특히 국내 개발사이트들을 찾아다니다 보면…

C++의 핵심이 클래스인데 왜 다들 MFC클래스에만 의존하는걸까?
물론 MFC클래스가 구조적을 상당히 안정되고 그 기능이 매우 잘 정리된 라이브러리임은 부정하지 않는다.

초기 MFC보다 볼란드에선 OWL 이라는 클래스 라이브러리가 MFC와 더불어 윈도우 클래스의 양대산맥이였다. 많은 개발자들은 두 라이브러리중에서 어떤걸 사용해야 할까라는 질문을 많이 했었다. 실제 사용상이나 편의성으로 볼때 OWL이 훨씬 더 좋은 라이브러리지만 장기적인 차원에서 MFC를 따르는게 대세였던거 같다.

나는 그당시 두 라이브러리가 아닌 순수 C++ 클래스를 공부하라는 지적을 많이하고 했다..사실 나즌 요즘에서야 비로서 MFC를 뒤적거리고 있기도 하다.

프로그램을 하다 필요한 클래스가 혹시나 있을까 생각해서 사이트를 뒤지다 보면 솔직히 별로 쓸만한 소스를 찾는적은 거의 없던것 같다.
모든 클래들이 상속을 전제로 만들었다기 보다는 마치 하나의 함수묶음정도로 밖엔 생각이 안들정도의 소스뿐이기 때문이다.

클래스에서 가장 중요한 상속성을 고려하지 않고 하나의 클래스가 너무나 많은 기능으로 제작되어 실제 사용시 필요하지 않은 기능까지 너무 많이 나열되어 특정한 부분을 수정할려고 해도 내장 함수 상호연동상의 문제로 그 수정이 용의하지 않는게 대부분이다.

내가 보기는 MFC 처럼 상당히 거의 완성된 클래스만을 사용하다보니 이런 결과가 나오지 않았나 생각된다. 결국에 MFC든 OWL이 되든 객체지향적인 설계가 아니라 객체지향 라이브러리의 조합을 잘하는 모양이 된게 아닌가 생각한다.

객체지향 클래스 설계에 있어서 가장 중요한 점은 상속성 설계에 있다. 대부분 1단계 상속에만 익수하다보니 어떤 기능을 조상과 후손으로 발전할지가 정리하는게 쉽지많은 않다. 그러다 보니 최종 클래스를 미리 만들고 거기서 기능을 추려서 상위 클래스로 올라가는 꺼꾸로식 설계를 하는 개발자도 쉬 찾아볼 수 있다.

잘 설계된 클래스의 경운 약 3~5 단계의 상속으로 사용하도록 설계하는게 가장 효과적이라고 생각한다.

1단계는 대부분이 클래스들의 종류나 그 타입을 정의하는 최소한의 클래스를 위치한다. CObject 가 바로 그 것이다.

2단계의 경우는 큰 그룹으로 나뉘어 지게 된다.
세부 기능보다는 큰 줄기를 구성하는 형태가 될것이다.

보통은 I/O, Buffer, Memory, 등과 같이 입출력의 형태별로 쪼개지며 그 기초 함수들이 정의된다. open, read, wirte, close 등과 같이 모든 입/출력 클래스에서 필요로 하는 기본 함수들이 정의된다. 또한 Abstract 함수가 이 단계에서 정의 된다.

3단계의 클래스에서 비로소 그 특징적 성격이 클래스 변수형태로 추가되어 비로서 특정한 로직을 구현하는 클래스가 완성되며 이 단계에서 Virtual함수들이 이 단계에서 정의 된다.

4 단계에서는 사용자의 함수와 더블어 Abstract, Virtual함수의 재 사용성으로 설계를 한다.

보통은 4단계 정도면 대부분의 많은 기능이 다 구현되고 있지만 유지보수 또는 테스트 단계에서 5단계의 클래스를 만들어 이용하기도 한다.

클래스 설계시 두번쨰로 중요한건 바로 접근 범위의 설정이다.
private, protected, public, friend의 4가지 형태의 접근방법이 있다.

영어다 보니 정확한 이해가 안될수 있으니까 좀더 쉽게 설명하면
개인, 집안, 공개, 친구 이런식의 해석이 될수 있다.

개인(private)은 아버지와 아들간에서도 서로 숨겨야 될 성격으로 해당 클래스에서만 접근할 수 있는 영역이다.
집안(protected)는 상속된 클래스만이 접근할수 있으나 친구(friend)로 별도 정의된 영역에서도 그 내용을 볼수 있다.
공개(public)은 모든 영역에서 접근할수 있도록 형용한 영역이다.

보통 public 은 기존의 global변수와 동일한 수준이다 보니 가능하면 최소한의 한다는 정도는 다들 알고 있다.

private, protected의 경우가 개발자들이 별 구분없이 쓰다 보니 대부분 protected(생략시 기본) 과 public의 두개로 클래스가 구성된 경우가 많다. 크래스를 설계시 최대한 변수나 함수를 private로 많이 배치하는 습관이 중요하다. 그것이 상속된 프로그램에서 실수를 하지 않는 좋은 습관이다.

추상함수(Abstract)함수는 virtual void fun() = 0; 과 같은 식으로 정의하는 함수이며 상위 클래스 함수에서 호출할 예정인 함수로 그 내용은 바로 정의 하지 못할때 사용하는 함수로서 이 함수를 이용하게 되면 상속받을 클래스의 코딩시 꼭 필요한 기능에 대한 제한적 설계가 용의 하다. 이 함수를 잘 사용한다는것은 바로 클래스를 상속을 정확히 이해하며 상속단계별 그 용도에 대한 설계를 충분히 검토했다고 생각할 수 있다.

가상함수(Virtual)는 함수의 재사용에 대한 부분으로 추상함수보다는 좀더 확정성 측면을 고려된 함수다. 기본적인 기능이 구현된 상태에서 그 기능의 확장을 이용할 수 있도록 설계하는 방식으로 기능 추가및 확장성을 고려한다면 Virtual함수를 잘 사용해야 할것이다.

클래스 설계시 함수 또는 변수명은 개인별 취향이나 많은 문서에서도 나름대로 정의하고 있기는 하지만 가급적 간단하고 그 의미가 한정되지 않도록 하는것이 좋다.
open, close, read, write, send, recv, init, quit, set, get, count, print, 등과 같은 함수명들이 내가 주로 사용하는 함수들이다.

모든 클래스에서 위의 함수를 사요하게 되면 아마도 대부분의 기능을 다 구현할 수 있을것이다. 이미 클래스로 한정된 그룹이므로 함수나 변수 자체에 너무 의미를 주지 않고 작성하는게 좋다.
함수이름만으로는 그 동작의 의미가 충분이 이해할 정도의 이름을 붙이고 클래스 이름에 좀더 한정적인 이름을 붙이는것이 보다 효과적인 사용에 유리하다.

클래스를 처음 설계하다 보면 하나의 대형 클래스로 되어서 실제로 모든 함수가 Public이 되는 경우를 누구나 경험하게 된다.
클래스의 설계는 정말 많은 노력과 연습만이 그 단계를 정의가 가능하다고 생각된다.

list, queue, stack, array, container 는 프로그램어라면 한번쯤 코딩해 보는것을 추천하고 싶다.

Leave a Reply