@Test voidtestSimpleAddition(){ Money five = Money.dollar(5); Expression sum = five.plus(five); // here Bank bank = new Bank(); Money reduced = bank.reduce(sum, "USD"); assertEquals(Money.dollar(10), reduced); }
이전에는, 가짜 구현이 있을 때 진짜 구현으로 작업해가는 것이 명확했다. 이번에는 어떻게 거꾸로 작업해야할지 명확하지 않다. 그래서 조금 불확실하지만 순방향으로 작업해보자. 우선, Money.plus() 는 그냥 Money 가 아닌, Expression(Sum) 을 반환해야한다. 두 Money 의 합은 Sum 이어야한다.
1 2 3 4 5 6 7 8
@Test voidtestPlusReturnsSum(){ Money five = Money.dollar(5); Expression result = five.plus(five); Sum sum = (Sum) result; assertEquals(five, sum.augend); assertEquals(five, sum.addend); }
위 코드를 컴파일하기위해서는, augend, addend 필드를 가진 Sum 클래스가 필요하다.
1 2 3 4
classSum{ Money augend; Money addend; }
다시 실행해보면, Money.plus() 는 Sum 이 아닌 Money 를 반환하게 되어 있어서, ClassCastExceptoin 을 발생시킨다. 그래서, 다음 처럼 수정하자.
@Test voidtestReduceSum(){ Expression sum = new Sum(Money.dollar(3), Money.dollar(4)); Bank bank = new Bank(); Money result = bank.reduce(sum, "USD"); assertEquals(Money.dollar(7), result); }
위 테스트는 테스트가 깨지도록 인자를 선택했다. Bank 클래스를 수정하자.
1 2 3 4 5 6 7 8
classBank{
Money reduce(Expression source, String to){ Sum sum = (Sum) source; int amount = sum.augend.amount + sum.addend.amount; returnnew Money(amount, to); } }
위 코드는 다음 이유로 지저분하다.
Casting. 위 코드는 모든 Expression 에 대해 작동해야한다.
public 필드와 그 필드들에 대한 두 단계에 걸친 레퍼런스.
우선, 외부에서 접근 가능한 필드 몇개를 들어내기 위해 메서드 본문을 Sum 으로 옮길 수 있다.
1 2 3 4 5 6 7
classBank{
Money reduce(Expression source, String to){ Sum sum = (Sum) source; return sum.reduce(to); } }