Eternity's Chit-Chat

aeternum.egloos.com



유연한 설계를 위한 패턴과 원리 - 2.의도를 명확하게 5부 Supple Design

환율 계산

Money times() 메소드를 추가했으므로 환율에 따라 통화를 변환할 있다. 통화 변환은 환율로 정해진 일정 비율을 금액에 곱한다는 것을 의미한다. 이전에 기록해 두었던 TODO 목록을 펼쳐보자.

 

$1 원화로 변환할 경우 \1027 얻기

\1027 USD 변환할 경우 $1 얻기

 

테스트를 통과시키기 위해 어떤 테스트 케이스를 작성해야 할까? 다시 한번 강조하지만 우리는 지금 테스트 케이스를 작성하는 동시에 설계를 하고 있는 것이다. 이것을 어떻게 구현하는지 알고 있고, 그래서 가장 좋은 방법으로 테스트를 작성할 있다면 그렇게 한다. 하지만 확신이 없거나 다른 아이디어를 탐구하고 싶다면 테스트를 작성하기 전에 짧은 설계 회의를 가지는 것이 좋다.

 

솔직히 말해서 환율 계산에 대한 테스트를 어떻게 작성해야 할지 모르겠다. 그렇다고 해서 테스트 케이스 말고 작은 단위로 테스트할 있는 방법도 떠오르지 않는다. 이럴 경우에는 동료와 함께 카드를 가지고 CRC 설계를 하거나 화이트보드나 종이에 UML 사용하여 가지 경우를 스케치하는 것이 좋다. 여러 가지 대안을 놓고 논쟁하는데 시간을 소비하지 않는 것이 중요하다. 그리고는 효과가 있는 가장 간단한 방법을 선택한다.

 

객체 지향 설계는 책임의 분할과 할당에 관한 것이다. 우선 통화 환율을 알고 있을 책임을 담당할 객체가 필요하다. 현실에서 돈을 바꿔주는 곳은 어디일까? 환전소다. ChangeBooth라는 클래스를 추가하자. ChangeBooth 환율을 알고 있어야 한다. 따라서 ChangeBooth 환율을 추가하거나 삭제하는 오퍼레이션을 포함하고 있어야 한다.

 

ChangeBooth 환율을 알고 있어야 하므로 명시적으로 환율 개념을 나타내는 ExchangeRate 클래스도 추가하는 것이 좋을 같다. ExchangeRate 기준 통화, 대상 통화, 환율을 나타내는 속성을 추가한다.

 

환율 변환에 있어 가장 중요한 책임은 환율에 따라 금액을 변환하는 것이다. 그렇다면 책임을 어떤 객체에 할당하는 것이 좋을까? 금액 정보를 가지고 있는 객체가 Money이므로 INFORMATION EXPERT 패턴 따라 Money 객체에 추가한다고 가정하자. 경우 Money 객체가 ChangeBooth 환율 정보를 알아야 하므로 Money에서 ChangeBooth로의 의존관계가 필요하다. Money STANDALONE CLASS 유지하기 위해서는 Money 본질적인 개념에 속하지 않는 환전 개념에 대한 의존성은 배제하는 것이 좋다. 나아가 의존성은 전이되기 때문에 Money 의존하는 클래스는 ChangeBooth에도 의존하게 된다. Money 필요로 하는 대부분의 클래스는 환전 기능을 필요로 하지 않기 때문에 ChangeBooth까지 필요는 없을 것이다. 반면 ChangeBooth 필요로 하는 클래스는 반드시 Money 필요로 한다. 따라서 환율을 변환할 책임을 Money 대신 ChangeBooth 할당하는 것이 결합도를 낮추는 좋은 설계라고 있다.

다음은 설계 회의를 통해서 결정된 클래스 다이어그램이다.

 

그림 1 환율 계산을 위한 설계 다이어그램


다이어그램을 그리는데 30분이 걸렸음에 주목하자. 대개의 경우 30분이 넘어가면 회의가 소모적으로 흐르기 쉽다. 대략적인 설계를 잡고 최대한 빠르게 구현 작업으로 전환하여 문제가 없는지를 검증하는 것이 효과적이다.

어떤
클래스부터 테스트해야 할까? ChangeBooth부터 시작하자. 가장 간단한 테스트는 동일한 통화로 변환하는 것이다. , 원화를 원화로 바꿀 경우 원래의 금액과 동일하면 된다.

 

ChangeBoothTest.java 

@Test

public void exchangeEqualCurrency() {

  ChangeBooth booth = new ChangeBooth();

  assertEquals(Money.wons(1000),

    booth.exchange(Money.wons(1000), Money.KRW));

}

 

ChangeBooth 클래스를 생성하고 exchange() 메소드를 구현한다. 금액이 동일한 통화인지 판단하는 책임은 통화에 대해 알고 있는 Money 클래스에 있으므로 Money 클래스에 isCurrencyEquals() 메소드를 추가하고 메소드를 사용하여 환율을 비교하도록 한다.

 

ChangeBoothTest.java  

public Money exchange(Money amount, Currency to) {

  if (amount.isCurrencyEquals(to)) {

    return amount;

  }

 

  return null;

}

 

Money 클래스에 isCurrencyEquals() 메소드를 추가하고 equals() 역시 isCurrencyEquals() 사용하도록 수정한다. 테스트를 실행하고 녹색 막대인지를 확인한다.

 

Money.java 

public boolean isCurrencyEquals(Currency currency) {

  return this.currency.equals(currency);

}


덧글

  • 긁적 2010/01/11 22:45 #

    헐. 이거슨 좋은 포스트군요.
    (근데 난 코딩 되도록 안 할건데 _-_....)
    여튼 잘 읽겠습니다. 감사합니다. ^^/
※ 로그인 사용자만 덧글을 남길 수 있습니다.