첫 페이지의 목표 $5 + 10CHF = $10을 이제 마주한다. 하지만 통화가 다른 덧셈은 크다. 더 작은 첫걸음은 같은 통화의 덧셈 $5 + $5 = $10이다.

핵심 통찰은 벡이 여기서 도입하는 은유다. $5 + $5의 결과를 즉시 $10으로 계산하지 않는다. 대신 “5달러와 5달러의 합”이라는 **식(Expression)**을 만들어 들고 있다가, 나중에 특정 통화로 **환산(reduce)**할 때 비로소 값을 구한다. 수식을 세우는 것과 계산하는 것을 분리하는 것 — 이것이 나머지 장들을 관통하는 설계다.

사이클: 큰 테스트 → 껍데기 → 가짜 초록 → Sum 도입

Refactoring Step 빨강 — plus / Bank / reduce 를 요구하는 테스트
1/4
@Testpublic void testSimpleAddition() {    Money five = Money.dollar(5);    Expression sum = five.plus(five);    Bank bank = new Bank();    Money reduced = bank.reduce(sum, "USD");    assertEquals(Money.dollar(10), reduced);}// Expression, plus(), Bank, reduce() — 아무것도 없다. 컴파일 실패.

plusnew Money(10, ...)을 바로 만들지 않고 new Sum(five, five)를 반환하는 전환이 이 장의 전부다. 지금은 Bank.reduce가 상수를 돌려주니 Sum이 하는 일이 없어 보인다. 하지만 구조가 먼저 서고 계산은 나중에 채운다 — 가짜 초록은 그 순서를 가능하게 하는 발판이다. Expression은 아직 메서드 하나 없는 표식 인터페이스지만, Money와 Sum을 한 지붕 아래 묶어 “reduce의 대상”이라는 역할을 부여한다.

판단 기준: $5 + 10CHF가 목표라도 첫 테스트는 $5 + $5다. 통화 변환이라는 어려움을 잠시 빼두면 “식 → 환산” 구조에만 집중할 수 있다. 함정: Expression에 지금 필요 없는 메서드를 미리 넣지 않는다. 인터페이스는 테스트가 요구할 때 자란다.

이 장이 남긴 할 일 목록

  • 5 = $10 (컴파일·구조)
  • Bank.reduce(Sum) 진짜로 만들기 → 13장
  • Bank.reduce(Money) — 단일 Money도 환산 대상
  • 10 (환율 2:1)

다음장으로 13장