Eternity's Chit-Chat

aeternum.egloos.com



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

ExchangeRate 기준 통화, 대상 통화, 환율을 포함하며 Set 추가되기 위해 equals() hashCode() 오버라이딩한다.

 

ExchangeRate.java

public class ExchangeRate {

  private Currency from;

  private Currency to;

  private double rate;

 

  public static ExchangeRate of(Currency from, Currency to, double rate) {

    return new ExchangeRate(from, to, rate);

  }

 

  ExchangeRate(Currency from, Currency to, double rate) {

    this.from = from;

    this.to = to;

    this.rate = rate;

  }

 

  public boolean isAcceptable(Currency from, Currency to) {

    return this.from.equals(from) && this.to.equals(to);

  }

 

  double getRate() {

    return rate;

  }

 

  public boolean equals(Object object) {

    if (this == object) {

      return true;

    }

 

    if (!(object instanceof ExchangeRate)) {

      return false;

    }

 

    ExchangeRate other = (ExchangeRate)object;

    return this.from.equals(other.from) &&

      this.to.equals(other.to) &&

      this.rate == rate;

  }

 

  public int hashCode() {

    int result = 17;

    result = 37 * result + from.hashCode();

    result = 37 * result + to.hashCode();

    result = 37 * result + (int)rate;

    return result;

  }

}

 

너무 보폭으로 진행했다고 생각하는가? 확신이 없고 막막할 때는 작은 보폭으로 걷는다. 자신감이 충만하고 구현에 확신이 있을 때는 보폭으로 걷는다. 보폭이 적당한지 아닌지는 전적으로 자신에게 달려 있다. 동일한 코드라고 해도 날의 컨디션에 따라 보폭이 달라질 있다. 절대로 여기에 적힌 보폭이 옳다고 생각해서는 된다. 스스로 실천해보고 피드백을 통해 여러분 스스로의 보폭을 찾기 바란다.

 

종종걸음으로 진행하는 것이 불안한가? 그러면 보폭을 넓혀라. 성큼성큼 걷는 것이 불안한가? 그럼 보폭을 줄여라. TDD 조종해 나가는 과정이다. 이쪽으로 조금, 저쪽으로 조금. 지금도, 그리고 앞으로도 정해진 올바른 보폭이라는 것은 존재하지 않는다.

- Kern Beck, Test-Driven Development

 

앞의 getExchangeRate() 메소드는 통화 간의 환율이 존재하지 않을 경우 0 반환하도록 작성했다. 그러나 0값이 잘못됐다는 의미를 포함하지 않는다. 물론 일반적인 경우 환율이 0 되는 경우는 없겠지만 동시에 가지 의미로 해석될 가능성이 있는 값을 사용하는 것은 좋지 않다. 환율이 존재하지 않을 경우 0 반환하지 말고 ExchangeRateNotFoundException 반환하도록 수정하자. ExchangeRateNotFoundException 던져질 경우 모든 클라이언트가 예외를 처리할 필요는 없으므로 Unchecked Exception 되도록 RuntimeException 상속받도록 한다. 우선 테스트부터 작성한다.

 

ChangeBoothTest.java

@Test(expected=ExchangeRateNotFoundException.class)

public void exchangeInvalidCurrency() {

  ChangeBooth changeBooth = new ChangeBooth();

  assertEquals(1027,

    changeBooth.getExchangeRate(Currency.getInstance("CHF"), Money.KRW));

}

 

ExchangeRateNotFoundException 반환하도록 getExchangeRate() 메소드를 수정한다.

 

ChangeBooth.java

double getExchangeRate(Currency from, Currency to)
   
throws ExchangeRateNotFoundException {

  for(ExchangeRate rate : rates) {

    if (rate.isAcceptable(from, to)) {

      return rate.getRate();

    }

  }        

  throw new ExchangeRateNotFoundException();

}

 

테스트를 통과한다. 이제 환율을 계산할 있을까? 잠깐만 숨을 돌리고 코드를 살펴보자. 솔직하게 말하자면 현재 설계가 마음에 들지 않는다. 회의 시에는 모든 것이 완벽하게 보였지만 실제 코드로 구현하는 과정에서 문제점이 보이기 시작했다.