19장 제어와 관련된 일반적인 이슈
목차
- 19.1 불린 표현식
- 19.2 복합문(블록)
- 19.3 널(Null) 명령문
- 19.4 지나치게 깊은 중첩 구조 처리
- 19.5 프로그래밍의 기초: 구조적 프로그래밍
- 19.6 제어 구조와 복잡성
19.1 불린 표현식
복잡한 표현식을 단순하게 만들기
- 복잡한 테스트를 새로운 불린 변수를 사용해 부분적인 테스트로 나눠라.
- 복잡한 표현식을 불린 함수로 옮겨라.
- 의사결정 테이블을 사용해 복잡한 조건을 대체하라.
불린 표현식을 사용할 때는 최대한 긍정문을 사용하는 것이 이해하기 쉽고, 또한 드모르간의 법칙을 적용해 부정 불린 테스트를 단순화하는 것이 좋다.
if (!displayOK || !printerOK) ...
위의 예제를 드모르간의 법칙을 적용하면 아래 코드처럼 바꿀 수 있다.
if (!(displayOK && printerOK)) ...
괄호를 사용하는 것은 비용이 거의 들지 않기 때문에, 최대한 괄호를 사용해 이해하기 쉬운 불린 표현식을 만들기 위해 노력하자.
숫자의 크기 순서대로 수치 표현식을 작성하자.
MIN_ELEMENTS <= i and i <= MAX_ELEMENTS
위의 코드 처럼 '>' 보다는 '<'를 사용해 수치 표현식을 작성하는 것이 여러 개를 사용할 때 이해하기 더 쉽다.
19.2 복합문(블록)
복합문을 사용할 때는 중괄호 쌍을 처음에 한번에 작성하는 것이 실수를 줄이는데 도움이 될 것이다.
19.3 널 명령문
널 명령문을 다룰 때 참고할 사항
- 널 명령문을 눈에 띄게 만들어라.
- 널 명령문으로 사용하기 위한 DoNothing() 전처리기 매크로나 인라인 함수를 작성하라.
- 널이 아닌 반복문을 사용하는 것이 더 분명하지 않은지 고려하라.
19.4 지나치게 깊은 중첩 구조 처리
중첩 구조의 길이를 줄이기 위한 방법
- 조건의 일부분을 다시 테스트하여 중첩된 if 문을 단순화하라.
- break 블록을 사용하여 중첩된 if 문을 단순화하라.
- 중첩된 if 문을 if-then-else 문으로 변환하라.
- 중첩된 if 문을 case 문으로 변환하라.
- 중첩 구조가 깊은 코드를 루틴으로 작성하라.
- 좀 더 객체지향적인 방법으로 접근하라.
- 깊게 중첩된 코드는 재설계하라.
19.5 프로그래밍 기초: 구조적 프로그래밍
구조적 프로그래밍의 핵심은 오직 하나의 입구와 하나의 출구만이 있는 제어구조를 사용해야 한다는 점이다.
구조적 프로그래밍을 통해 코드를 하향식으로 읽을 수 있고, 거의 같은 방법으로 실행된다.
구조적 프로그래밍 체계를 따르지 않으면 소스코드가 의미 없게 작성되고 기계에서 프로그램이 어떻게 실행되는지 파악하기도 어렵다. 가독성이 떨어진다는 것은 이해도가 낮다는 것을 의미하고 궁극적으로 프로그램의 품질도 떨어진다.
구조적 프로그래밍의 세가지 요소
순차적 명령문
순차적 명령문은 순서대로 실행되는 명령문의 집합이다. 전형적인 순차적 명령문에는 할당문과 함수 호출이 있다.
선택
선택은 명령문을 선택적으로 수행하는 제어 구조를 말한다. if-then-else 문이 흔한 예다. if-then 절이나 else 절 중 어느 하나가 실행되지만 동시에 실행되지는 않는다. 두 절 중 하나만 실행되기 위해서 "선택"된다.
반복
반복은 명령문 그룹을 여러 번 실행하는 제어 구조다. 반복은 일반적으로 "반복문"으로 알려져 있다. 반복의 종류에는 비주얼 베이직의 For-Next, C++와 자바의 while과 for가 있다.
19.6 제어 구조와 복잡성
제어 구조에 주의를 많이 기울여야 하는 이유는 제어 구조가 프로그램의 복잡도에 큰 영향을 주기 때문이다. 제어 구조를 어떻게 사용하느냐에 따라 복잡도가 크게 증가할 수도, 감소할 수도 있다.
"프로그래밍 복잡도"를 측정하는 한 가지 방법은 프로그램을 이해하기 위해서 기억해야 하는 객체의 수를 세어보는 것이다.
프로그램의 복잡성은 프로그램을 이해하기 위해서 얼마만큼 노력해야 하는지를 결정하는데 중대한 역할을 한다.
복잡도가 얼마나 중요한가?
유능한 개발자는 자신의 두뇌에 한계가 있다는 사실을 잘 알고 있어서 겸손한 자세로 프로그래밍 작업에 임한다. 이 말은 복잡도가 대단히 높은 코드를 다룰 수 있도록 두뇌의 능력을 키워야 한다는 이야기가 아니라, 복잡도가 대단히 높은 코드를 절대로 다룰 수 없기 때문에 가능한 한 복잡도룰 줄이기 위한 단계를 따라야 한다는 뜻이다.
복잡도를 줄이기 위한 일반적인 방법
- 두뇌 훈련을 통해서 두뇌의 처리 능력을 향상시킨다.
- 프로그램의 복잡도와 프로그램을 이해하기 위해 집중해야 하는 대상의 수를 줄인다.
아래의 방법이 우리가 더 빨리 복잡도를 줄일 수 있는 방법임에 이견이 없을 것이다.
복잡도 측정법
아마도 무엇 때문에 루틴의 복잡도가 증가하거나 감소하는지 직관적으로 알 것이다. 아래 방법은 한 루틴 안의 "의사결정 지점(decision point)"의 수를 세어 복잡도를 측정한다.
2. if, while, repeat, for, and, or와 같은 키워드를 만날 때마다 1을 더한다.
3. case 문의 경우마다 1을 더한다.
위의 방법으로 아래 코드의 복잡도를 구해보자.
if (((status = Success) and done) or
(not done and (numLines >= maxLines))) then ...
일단 시작할 때 1이고, if 에서 2, and 2개와 or 1개가 사용되었으므로 2 + 3 = 5 이므로 총 5개의 의사결정 지점이 있다.
복잡도 측정의 활용
6-10: 이 루틴을 단순화하기 위한 방법을 생각해 본다.
10+: 루틴을 다른 루틴으로 나눈 다음 첫 번째 루틴에서 두 번째 루틴을 호출한다.