SmalltalkBestPracticePatterns:8.4
- 8.4 Arithmetic (산술)
Arithmetic (산술)
두 개의 Money를 어떻게 합칠까? 간단한 case, 즉 두 개의 Money에 동일한 통화를 가지는 경우를 먼저 올바르게 만들어보자. 동일한 통화로 된 두 개의 Money를 추가할 때는 결과적 Money는 첫 번째 두 개를 합한 금액만큼 가져야 한다.
Money>>+ aMoney
^self species
amount: amount + aMoney amount
currency: currency
이것이 작동하려면 "amount" 변수에 Getting Method가 필요하다:
Money>>amount
^amount
달러에 달러를 추가하고 있다면 올바른 해답을 얻는다:
| m1 m2 |
m1 := Money
amount: 5
currency: #USD.
m2 := Money
amount: 7
currency: #USD.
m1 + m2 12 USD
Moneys를 다른 통화로 변경할 경우 틀린 해답을 얻는다:
| m1 m2 |
m1 := Money
amount: 5
currency: #USD.
m2 := Money
amount: 7
currency: #GBP.
m1 + m2 12 USD
5 달러와 7 파운드를 합하면 12 달러가 아니다. 산술에 간단한 "+" 프로토콜을 유지하면서 다수의 통화를 가진 case를 처리할 수 있는 방법으로 무엇이 있을까? 해답은 Money에 대해 Imposter를 (모델링 패턴) 도입하여 환율 변환을 따르는 것이다. 그것으로 MoneySum라는 Simple Superclass Name(간단한 슈퍼클래스명)을 제공한다.
Class: MoneySum
superclass: Object
instance variables: monies
Role Suggesting Instance Variable Name(역할을 제안하는 인스턴스 변수) "monies"를 이용한 변수는 Moneys의 Collection을 보유할 것이다.
Constructor Method(생성자 메서드)를 이용해 MoneySum을 생성한다:
MoneySum class>>monies: aCollection
^self new setMonies: aCollection
컬렉션은 Constructor Parameter Method(생성자 파라미터 메서드)로 옮겨간다:
MoneySum>>setMonies: aCollection
monies := aCollection
Debug Print Method(디버그 인쇄 메서드)를 MoneySum으로 추가하면 결과를 확인할 수 있다:
MoneySum>>printOn: aStream
monies do:
[:each |
aStream
print: each;
nextPutAll: ' + '].
aStream skip: -3
이 메서드에서는 꽤 많은 패턴들이 사용되었다: Direct Variable Access(직접 변수 접근), Role Suggesting Parameter Name(역할을 제안하는 파라미터명), Simple Enumeration Parameter(간단한 열거 파라미터), Rectangular Block(직사각형 블록), Indented Control Flow(들여쓴 제어 흐름), Do.
MoneySum을 사용할 수 있다면 두 개의 통화가 일치하지 않을 시 MoneySum을 리턴하도록 Money>>+를 수정할 수 있다.
Money>>+ aMoney
^currency = aMoney currency
ifTrue:
[self species
amount: amount + aMoney amount
currency: currency]
ifFalse:
[MoneySum monies: (Array
with: self
with: aMoney)]
Money의 통화에 Getting Method가 필요하다:
Money>>currency
^currency
이제 우리의 복수통화 예제가 작동한다:
| m1 m2 |
m1 := Money
amount: 5
currency: #USD.
m2 := Money
amount: 7
currency: #GBP.
m1 + m2 5 USD + 7 GBP
확인차 단일통화 예제를 시도해보니 작동한다:
| m1 m2 |
m1 := Money
amount: 5
currency: #USD.
m2 := Money
amount: 7
currency: #USD.
m1 + m2 12 USD