Skip to content

Files

Latest commit

ef3369c · Jun 12, 2022

History

History

15. 서로 다른 통화 더하기

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jun 12, 2022

15. 서로 다른 통화 더하기

TODO)

  • $5 + 10CHF = $10(환율이 2:1일 경우)
  • $5 + $5 = $10
  • $5 + $5에서 Money 반환하기
  • Bank.reduce(Money)
  • Money에 대한 통화 변환을 수행하는 Reduce
  • Reduce(Bank, String)

내용

드디어 모든 작업의 시초인 $5 + 10CHF에 대한 테스트를 추가할 준비가 되었다.

public void testMixedAddition() {
  Expression fiveBucks = Money.dollar(5);
  Expression tenFrancs = Money.franc(10);
  
  Bank bank = new Bank();
  bank.addRate("CHF", "USD",2);
  
  Money result = bank.reduce(fiveBucks.plus(tenFrancs),"USD");
  assertEquals(Money.dollar(10),result);
}

Money에서 Expression으로 일반화 할때 어설프게 남겨둔 부분들이 많기에 무수히 많은 컴파일 에러가 생기고,
이런 컴파일 에러들을 해결해야 한다. 우선 Expression을 Money로 변경해주자.

public void testMixedAddition() {
  Money fiveBucks = Money.dollar(5);    //Expression -> Money로 변경
  Money tenFrancs = Money.franc(10);    //Expression -> Money로 변경
  
  Bank bank = new Bank();
  bank.addRate("CHF", "USD",2);
  
  Money result = bank.reduce(fiveBucks.plus(tenFrancs),"USD");
  assertEquals(Money.dollar(10),result);
}

Expression을 Money로 변경 후 다시 테스트해보면 10USD 대신 15USD가 나오게 된다.
Sum.reduce()가 인자를 축약하지 않는것 같아 보인다.

//Sum 클래스
public class Sum implements Expression {
  Money augend;
  Money addend;
  
  Sum(Money augend, Money addend) {
    this.addend = addend;
    this.augend = augend;
  }
  
  public Money reduce(Bank bank, String to) {
    int amount = augend.amount + addend.amount;
    return new Money(amount,to);
  }
  
}

다음과 같이 두 인자를 모두 축약하면 테스트가 통과하게 될것이다.

//Sum 클래스
public class Sum implements Expression {
  Money augend;
  Money addend;
  
  Sum(Money augend, Money addend) {
    this.addend = addend;
    this.augend = augend;
  }
  
  public Money reduce(Bank bank, String to) {
    int amount = augend.reduce(bank, to).amount + addend.reduce(bank, to).amount;
    return new Money(amount,to);
  }
  
}

테스트를 통과하게 되고, 이제 우리는 Expression이어야 하는 Money들을 조금씩 없엘수 있다.
파급 효과를 피하기 위해 가장자리에서 작업해 나가기 시작해서 그 테스트 코드까지 거슬러 올라오도록 하자.
예를들어 피가산수와 가수는 이제 Expression으로 취급 할 수 있다.
생성자의 인자 또한 Expression일 수 있다.

//Sum 클래스
public class Sum implements Expression {
  Expression augend;
  Expression addend;
  
  Sum(Expression augend, Expression addend) {
    this.addend = addend;
    this.augend = augend;
  }
  
  public Money reduce(Bank bank, String to) {
    int amount = augend.reduce(bank, to).amount + addend.reduce(bank, to).amount;
    return new Money(amount,to);
  }
  
}

Sum을 변경해 주었으니, plus()의 인자가 Expression으로 취급될 수 있다.

//Money 클래스
Expression plus(Expression addend) {
  return new Sum(this, addend);
}

times() 의 반환 값도 Expression 일수 있다.

//Money 클래스
Expression times(int multiplier) {
  return new Money(amount*multiplier, currency);
};

이제 테스트 케이스에 나오는 plus()의 인자도 바꿀 수 있다.

public void testMixedAddition() {
  Money fiveBucks = Money.dollar(5);
  Expression tenFrancs = Money.franc(10);    //Money ->Expression로 다시 변경
  
  Bank bank = new Bank();
  bank.addRate("CHF", "USD",2);
  
  Money result = bank.reduce(fiveBucks.plus(tenFrancs),"USD");
  assertEquals(Money.dollar(10),result);
}

fiveBucks 를 Expression 으로 바꾸고 나면 몇 군데를 같이 수정해야 한다.
컴파일러가 Expression에 plus()가 정의 되지 않았다고 알려준다. 정의해주자.

//Expression 클래스
Expression plus(Expression addend);

이제 Money와 Sum에도 추가해야 한다.
Money는 공용으로 변경해 준다.

//Money 클래스
public Expression plus(Expression addend) {
  return new Sum(this, addend);
}

Sum의 구현을 스텁구현으로 바꾸고 할일 목록에 적어두자.

//Sum 클래스
public Expression plus(Expression addend) {
  return null;
}

TODO)

  • $5 + 10CHF = $10(환율이 2:1일 경우)
  • $5 + $5 = $10
  • $5 + $5에서 Money 반환하기
  • Bank.reduce(Money)
  • Money에 대한 통화 변환을 수행하는 Reduce
  • Reduce(Bank, String)
  • Sum.plus
  • Expression.times

우리는

  • 원하는 테스트를 작성하고, 한 단계에 달성할 수 있도록 뒤로 물렀다.
  • 좀더 추상적인 선언을 통해 가지에서 뿌리(애초의 테스트 케이스)로 일반화했다.
  • 변경 후, 그 영향을 받은 다른 부분들을 변경하기 위해 컴파일러의 지시를 따랐다.