SmalltalkBestPracticePatterns:8.4

From 흡혈양파의 번역工房
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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


Notes