•
조건문 다른 명령문의 실행을 제어하며 프로그래밍의 요소 중 하나인 분기의 대표적인 구현체다.
◦
논리적으로는 while과 for도 조건문이라고 해야하지만 관례상 이 둘은 별도로 다룬다.
1. if 문
if-then 문
•
큰 흐름의 코드를 먼저 작성한 다음 예외 처리에 대한 코드를 작성한다.
◦
일반적인 코드의 흐름이 분명하도록 코드를 작성한다. 특별한 경우가 일반적인 흐름을 모호하게 만들지 않도록 한다.
•
부등호를 조건문에 사용해야할 때, 등호에 대한 조건을 정확하게 사용하자.
•
정상적인 경우를 else가 아니라 if 문 다음에 입력하라.
◦
정상적으로 처리되는 경우를 먼저 작성한다. 이는 조건 판단의 결과로부터 가능한 결정하는 위치와 가깝게 코드를 작성하는 일반적인 원칙과 일치한다.
◦
다음 예시를 살펴보자.
OpenFile( inputFile, status )
If ( status = Status_Error ) Then
errorType = FileOpenError <-- 1 오류
Else
ReadFile( inputFile, fileData, status ) <-- 2 정상
If ( status = Status_Success ) Then
SummarizeFileData( fileData, summaryData, status ) <-- 3 정상
If ( status = Status_Error ) Then
errorType = ErrorType_DataSummaryError <-- 4 오류
Else
PrintSummary( summaryData ) <-- 5 정상
SaveSummaryData( summaryData, status )
If ( status = Status_Error ) Then
errorType = ErrorType_SummarySaveError <-- 6 오류
Else
UpdateAllAccounts() <-- 7 정상
EraseUndoFile()
errorType = ErrorType_None
End If
End If
Else
errorType = ErrorType_FileReadError
End If
End If
Visual Basic
복사
▪
이 코드는 정상적인 경우와 오류가 발생한 경우가 모두 섞여 있어 흐름을 읽기 힘들다.
▪
오류 처리가 else 절이 아니라 if 절에서 처리되는 경우가 존재하므로 if 문을 읽을 때도 예외와 정상 흐름을 확인해야 한다.
◦
재작성한 코드에서는 일반적인 경우가 일관성있게 먼저 작성되었으며 오류가 발생한 경우는 모두 나중에 작성되었다.
OpenFile( inputFile, status )
If ( status = Status_Success ) Then
ReadFile( inputFile, fileData, status ) <-- 1
If ( status = Status_Success ) Then
SummarizeFileData( fileData, summaryData, status ) <-- 2
If ( status = Status_Success ) Then
PrintSummary( summaryData ) <-- 3
SaveSummaryData( summaryData, status )
If ( status = Status_Success ) Then
UpdateAllAccounts() <-- 4
EraseUndoFile()
errorType = ErrorType_None
Else
errorType = ErrorType_SummarySaveError <-- 5
End If
Else
errorType = ErrorType_DataSummaryError <-- 6
End If
Else
errorType = ErrorType_FileReadError <-- 7
End If
Else
errorType = ErrorType_FileOpenError <-- 8
End If
Visual Basic
복사
•
정확성 파악을 위해 else 문을 테스트하라.
◦
테스트 코드의 커버리지를 높이는 것은 코드의 좋은 부정 지표로서 작용한다.
◦
else 문을 테스트할 수 있다면 꼭 그렇게 해야 한다.
연속적인 if-then-else 문
•
case 문을 지원하지 않거나 부분적으로 지원하는 언어에서는 종종 if-then-else 테스트를 연속해서 작성하게 된다.
◦
예를 들어서 문자를 분류하는 코드는 다음과 같은 연속적인 if-then-else 문을 사용할 것이다.
if ( inputCharacter < SPACE ) {
characterType = CharacterType_ControlCharacter;
}
else if (
inputCharacter == ' ' ||
inputCharacter == ',' ||
inputCharacter == '.' ||
inputCharacter == '!' ||
inputCharacter == '(' ||
inputCharacter == ')' ||
inputCharacter == ':' ||
inputCharacter == ';' ||
inputCharacter == '?' ||
inputCharacter == '-'
) {
characterType = CharacterType_Punctuation;
}
else if ( '0' <= inputCharacter && inputCharacter <= '9' ) {
characterType = CharacterType_Digit;
}
else if (
( 'a' <= inputCharacter && inputCharacter <= 'z' ) ||
( 'A' <= inputCharacter && inputCharacter <= 'Z' )
) {
characterType = CharacterType_Letter;
}
Visual Basic
복사
•
복잡한 테스트를 불린 함수로 대체하라.
◦
앞선 코드가 읽기 어려운 이유는 문자열을 분류하는 조건문들이 복잡하기 때문이다.
◦
코드를 이해하기 쉽게 이 조건문들을 불린 함수로 대체할 수 있다.
if ( IsControl( inputCharacter ) ) {
characterType = CharacterType_ControlCharacter;
}
else if ( IsPunctuation( inputCharacter ) ) {
characterType = CharacterType_Punctuation;
}
else if ( IsDigit( inputCharacter ) ) {
characterType = CharacterType_Digit;
}
else if ( IsLetter( inputCharacter ) ) {
characterType = CharacterType_Letter;
}
Visual Basic
복사
•
가장 흔한 경우를 앞에 놓아라.
◦
가장 흔한 경우를 앞에 놓으면 일반적인 흐름을 찾기 위해 읽어야 하는 예외처리의 코드의 양을 최소화할 수 있다.
•
모든 경우를 다루었는지 확인하라.
◦
마지막 else 문에는 놓친 조건들을 처리할 오류 메시지나 어설션을 작성한다.
▪
이 오류 메시지는 개발자를 위한 것이니 정보를 적절히 제공한다.
•
언어가 지원한다면 다른 구조를 사용하라.
◦
문자열과 열거형, 논리함수를 사용할 수 있는 case 문이 가독성이 더 좋다.
2. case 문
•
case, switch 문은 언어에 따라 다르게 구현되는데 Java는 한 번에 하나의 값만 저장하는 순서형의 값에 대해서만 case를 지원한다.
•
다음 절에서는 case 문을 효과적으로 사용하기 위한 가이드라인을 제공한다.
가장 효과적인 case 순서의 선택
•
알파벳 순이나 숫자 순으로 케이스를 나열하라.
◦
케이스의 중요도가 동일하다면 알파벳 순으로 나열하여 가독성을 향상시켜라.
•
가장 정상적인 경우를 앞에 놓아라.
◦
정상적인 경우 하나와 예외적인 경우가 여럿 있는 경우 가장 일반적인 경우를 앞에 놓는다.
◦
그리고 나머지 경우들이 모두 예외임을 주석으로 표시한다.
•
빈도나 우선순위에 따라서 case를 나열하라.
◦
가장 빈번하게 실행되거나 우선순위 중요한 것을 가장 앞에 두고 가장 드물게 실행되는 경우를 마지막에 놓는다.
◦
이러한 접근법은 가장 흔한 경우를 쉽게 찾을 수 있다는 장점을 제공한다.
case 문 사용팁
•
case 문이 하는 일을 간단하게 유지한다.
◦
각 케이스와 연관된 코드를 짧게 유지하면 case 문의 구조를 명확하게하는 데 도움을 준다.
◦
케이스의 조건이 복잡하다면 메소드로 추출해내자.
•
case 문에서 사용하기 위한 가짜, 임시 변수를 만들지 않는다.
◦
case 문은 쉽게 분류될 수 있는 형태에만 사용해야 한다.
◦
데이터가 단순하지 않다면 if-then-else를 사용해야 한다.
•
유효한 기본값을 찾고자 하는 경우나 오류를 검출하기 위해서 default 문을 사용한다.
◦
일반적으로 default는 기본값을 대체해야한다. 특정한 조건에서의 값을 대변해서는 안 된다.
▪
그 의미를 흐리게 한다.
◦
입력되어서는 안 되는 데이터가 입력되었을 경우, 오류 메시지를 적절히 처리하기에 적합하다.
•
중첩된 case 문을 사용하지 않는다.
◦
맥락에 계층이 생길수록 가독성은 떨어지기 마련이다.
요점 정리
•
특히 많은 오류를 처리할 때는 간단한 if-else 문에서 if와 else 문의 순서에 주의를 기울인다. 정상적인 경우가 명확하게 드러나게 한다.
•
if-then-else 문과 case 문에서는 가독성을 고려하여 정렬 순서를 결정한다.
•
오류를 잡기 위해서 case 문에서는 default, if-then-else 문에서는 else를 활용한다.
•
각 코드 블록에 적합한 조건문 제어 구조를 선택할 줄 알아야 한다. 은탄환은 없다.