SmalltalkBestPracticePatterns:7.7
- 7.7 Conditional Expression (조건 표현식)
Conditional Expression (조건 표현식)
- 두 개의 분기(branch)가 값을 할당하거나 리턴하는 조건 표현식은 어떻게 포맷팅하는가?
대부분 프로그래밍 언어는 값을 리턴하는 표현식과, 부가적 효과에 의해서만 작동하는 statement를 구별한다. 예를 들면, C와 Pascal에서 제어 구조는 다른 statement들이 실행되는 방식의 제어를 통해서만 작동한다.
스몰토크에선 순수한 statement란 없다. 모든 제어 구조는 메시지와 관련해 구현되고, 모든 메시지는 값을 리턴한다. 이는 제어 구조의 값을 사용하는 가능성으로 이어진다.
스몰토크에 생소한 프로그래머들은 표현식으로 사용된 조건문 또는 루프를 처음으로 목격하곤 놀라기 십상이다. 신규 스몰토커들은 아래와 같이 작성하기 쉽다:
self isInitialized
ifTrue: [cost := self calculateCost]
ifFalse: [cost := 0]
이 표현식들은 의미를 변경하지 않고 아래와 같이 번역이 가능하다:
cost := self isInitialized
ifTrue: [self calculateCost]
ifFalse: [0]
형태가 더 단순하다고 해서 초보자들에게 혼란을 불러일으킬만한 가치가 있을까? 이는 표현식의 의도를 좀 더 직접적으로 전달한다. "두 개의 표현식 경로가 있는데, 하나는 비용가(value of cost)를 스스로 calculateCost를 전송한 결과로 설정하는 경로이고, 다른 하나는 비용가를 0으로 설정하는 경로이다,"란 말을 하려는 것이 아니다. 그보다는 "비용을 스스로 calculateCost로 전송한 결과 또는 0 중에서 하나의 값으로 설정하라,"는 의미일 것이다.
- 조건문을 포맷팅하여 그들의 값이 메서드의 의도를 분명히 전달하는 곳에 사용하도록 하라.
할당과 리턴은 조건문의 두 분기(branch)에서 종종 발견된다. 이 둘을 조건문 외부로 팩토링(factor)할 기회를 모색하라.
아래는 조건문의 두 분기에서 return의 예제를 소개한다:
cost
self isInitialized
ifTrue: [^self calculateCost]
ifFalse: [^0]
이와 같은 코드를 작성할 때는, "여기 두 가지 대안적 실행 경로가 있습니다,"가 아니라, "여기 리턴시킬 두 가지 대안 값이 있습니다,"를 의미하는 것이다. 따라서 Conditional Expression가 필자의 의도를 좀 더 명확히 표현한다:
cost
^self isInitialized
ifTrue: [self calculateCost]
ifFalse: [0]
필자는 조건 표현식의 양면이 Boolean으로 평가하는 코드를 흔히 목격하는데, 이는 아래와 같이 시작한다:
aCollection isEmpty
ifTrue: [empty := true]
ifFalse: [empty := false]
Conditional Expression을 이용해 할당(assignment)을 먼저 가려낸다:
empty := aCollection isEmpty
ifTrue: [true]
ifFalse: [false]
한 단계 더 나아가 조건문을 전체적으로 제거할 수 있다. 아래 코드는 앞의 것과 동일하다:
empty := aCollection isEmpty
Composed Method(p.21)를 이용하여 조건문에서 하나 또는 두 개의 분기를 좀 더 명시적으로 표시할 수 있다.