. 구조화

탭문자 처리에 대한 코드를 작성해 봤는데 생각보다 그리 어렵지 않았을 것이다. 이 실습은 사실 탭문자를 처리하는 기법보다는 프로그램의 구조를 만들어 가는 방법을 보여준다는 데 더 큰 의의가 있다. 이 예제에서 DrawLine 함수는 OnPaint 함수의 서브함수로 정의되었으며 OnPaint 이외의 곳에서는 호출하지 않는다. 마찬가지로 DrawSegment DrawLine의 서브함수이며 오로지 DrawLine만 이 함수를 호출한다. 이 관계는 정렬할 때 작성한 GetLine GetLineSub와의 관계와 동일하다.

이렇게 서브함수를 만들면 함수단위로 업무가 분담되기 때문에 개발과정이 여러 모로 편리해진다. OnPaint DrawLine을 불러 한 줄씩 출력하므로 줄 내에 탭이 있건 없건 상관할 필요없이 이 함수만 불러주면 된다. DrawLine도 마찬가지로 출력할 줄의 범위를 구하거나 DC를 생성하는 일 따위는 신경쓸 필요가 없다. OnPaint가 준 hdc Line 줄을 제대로 출력하면 소임을 완수하는 것이다.

DrawLine은 위에서 시키는 대로만 하니 얼마나 편한가? 뿐만 아니다. DrawSegment라는 말 잘 듣는 졸병까지 하나 거느리게 되었으며 조각을 출력할 필요가 있으면 조각의 범위만 잘 조사해서 DrawSegment에게 시키면 된다. 화면출력을 세 함수가 나누어 맡게 되었으므로 이제 책임소재가 분명해지고 문제가 생기더라도 범위를 쉽게 좁힐 수 있다. DrawLine은 제대로 범위를 조사했는데 조각이 제대로 출력되지 않는다면 DrawSegment의 코드가 이상이 있는 것으로 쉽게 판단할 수 있다.

또한 각 함수의 임무가 분명하기 때문에 코드를 개선하기도 훨씬 더 쉬워진다. DrawLine은 한 줄을 출력하는 작업을 분담하고 있으며 OnPaint DrawLine만 호출하면 한 줄이 출력된다고 생각하고 있다. 따라서 DrawLine은 한 줄을 출력하는 임무에만 충실하다면 내부구조를 어떻게 바꾸더라도 OnPaint가 영향을 받지는 않는다. 즉 인터페이스만 유지하면 구현은 자유롭게 바꿀 수 있다.

, 그럼 저렇게 함수를 나누어 놓으면 좋다는 건 알겠는데 그렇다면 어떻게 저런 구조를 생각해 내고 만들 수 있을까? 함수를 작업 단위로 나누는 무슨 공식 같은 게 있지 않을까 생각될 것이다. 그러나 수학식 같은 절대적인 공식은 없고 함수의 구조를 설계하는 몇 가지 원칙이 존재한다. 그 원칙 중 몇 가지를 간단히 소개해보자면 다음과 같다.

 

함수는 입력과 출력이 명확해야 한다.

한 함수는 하나의 작업만 해야 한다.

분리할 수 있는 작업 단위는 가급적 잘게 함수로 나누어야 한다.

동작을 가장 함축적으로 설명할 수 있는 이름을 붙여 준다.

 

이런 몇 가지 원칙대로 함수를 디자인하되 이런 구조를 한 번에 그것도 제대로 잡아가는 능력은 쉽게 생기지 않으며 다소 풍부한 실전 경험을 요구한다. 사실 여러분들도 이 정도 함수 설계 원칙은 이미 알고 있거나 스스로 필요성을 느끼고 있다. 문제는 원칙을 아느냐 모르느냐가 아니라 이 원칙을 얼마나 잘 실천할 수 있는가이다. 프로그램과 함수, 객체를 설계하는 방법에 대한 참고 서적들이 많이 발표되어 있으므로 읽어보기 바란다.