본문으둜 κ±΄λ„ˆλ›°κΈ°

🌈 Chapter 13: μ§„μ§œλ‘œ λ§Œλ“€κΈ°

λͺ¨λ“  쀑볡을 μ œκ±°ν•˜κΈ° μ „κΉŒμ§€λŠ” $5 + $5 ν…ŒμŠ€νŠΈμ— μ™„λ£Œ ν‘œμ‹œλ₯Ό ν•  수 μ—†λ‹€. μ½”λ“œ 쀑볡은 μ—†μ§€λ§Œ 데이터 쀑볡이 μžˆλ‹€. κ°€μ§œ κ΅¬ν˜„μ— μžˆλŠ” $10λŠ”

// Bank
Money reduce(Expression source, String to) {
return Money.dollar(10);
}

사싀 ν…ŒμŠ€νŠΈ μ½”λ“œμ— μžˆλŠ” $5 + $5와 κ°™λ‹€.

public 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);
}

μš°μ„ , Money.plusλŠ” κ·Έλƒ₯ Moneyκ°€ μ•„λ‹Œ Expression(Sum)을 λ°˜ν™˜ν•΄μ•Ό ν•œλ‹€.
두 Money의 합은 Sum이어야 ν•œλ‹€.

public void testPlusReturnsSum() {
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 ν΄λž˜μŠ€κ°€ ν•„μš”ν•˜λ‹€.

// Sum
class Sum {
Money augend;
Money addend;
}

Money.plus()λŠ” Sum이 μ•„λ‹Œ Moneyλ₯Ό λ°˜ν™˜ν•˜κ²Œ λ˜μ–΄ 있기 λ•Œλ¬Έμ—, 이 μ½”λ“œλŠ” ClassCastException을 λ°œμƒμ‹œν‚¨λ‹€.

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

Sum μƒμ„±μžλ„ ν•„μš”ν•˜λ‹€.

// Sum
Sum(Money augend, Money addend) {
this.augend = augend;
this.addend = addend
}

그리고 Sum은 Expression의 일쒅이어야 ν•œλ‹€.

// Sum
class Sum implements Expression

이제 Bank.reduce()λŠ” Sum을 μ „λ‹¬λ°›λŠ”λ‹€. λ§Œμ•½ Sum이 가지고 μžˆλŠ” Money의 톡화가 λͺ¨λ‘ λ™μΌν•˜κ³ , reduceλ₯Ό 톡해 μ–»μ–΄λ‚΄κ³ μž ν•˜λŠ” Money의 톡화 μ—­μ‹œ κ°™λ‹€λ©΄, κ²°κ³ΌλŠ” Sum 내에 μžˆλŠ” Money듀이 amountλ₯Ό ν•©μΉœ 값을 κ°–λŠ” Money 객체여야 ν•œλ‹€.

public void testPlusReturnsSum() {
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);
}

ν˜„μ‘΄ν•˜λŠ” ν…ŒμŠ€νŠΈκ°€ 깨지도둝 인자λ₯Ό μ„ νƒν–ˆλ‹€. μš°λ¦¬κ°€ Sum을 κ³„μ‚°ν•˜λ©΄ κ²°κ³ΌλŠ” Moneyκ°€ λ˜μ–΄μ•Ό ν•˜λ©°, κ·Έ Money의 양은 두 Money μ–‘μ˜ 합이고, ν†΅ν™”λŠ” μš°λ¦¬κ°€ μΆ•μ•½ν•˜λŠ” 톡화여야 ν•œλ‹€.

// Bank
Money reduce(Expression source, String to) {
Sum sum = (Sum) source;
int amount = sum.augend.amount + sum.addend.amount;
return new Money(amount, to);
}

이 μ½”λ“œλŠ” λ‹€μŒ 두 가지 이유둜 μ§€μ €λΆ„ν•˜λ‹€.

  • μΊμŠ€νŒ…(ν˜•λ³€ν™˜), 이 μ½”λ“œλŠ” λͺ¨λ“  Expression에 λŒ€ν•΄ μž‘λ™ν•΄μ•Ό ν•œλ‹€.
  • 곡용(public) ν•„λ“œμ™€ κ·Έ ν•„λ“œλ“€μ— λŒ€ν•œ 두 λ‹¨κ»˜λ₯Ό 걸친 레퍼런슀.

κ°„λ‹¨νžˆ κ³ μΉ  수 μžˆλŠ” λ¬Έμ œλ“€μ΄λ‹€.

// Bank - μΆ”ν›„ μˆ˜μ •
Money reduce(Expression source, String to) {
Sum sum = (Sum) source;
return sum.reduce(to);
}

// Sum
public Money reduce(String to) {
int amount = augend.amount + addend.amount;
return new Money(amount, to);
}

λ§‰λŒ€κ°€ μ΄ˆλ‘μƒ‰μ΄κ³  μœ„μ˜ μ½”λ“œμ— λŒ€ν•΄ 더 ν•  것이 λͺ…ν™•ν•˜μ§€ μ•ŠμœΌλ‹ˆκΉŒ 일단 κ·Έ ν…ŒμŠ€νŠΈλ₯Ό μž‘μ„±ν•˜λ„λ‘ ν•˜μž.

public void testReduceMoney() {
Bank bank = new Bank();
Money result = bank.reduce(Money.dollar(1), "USD");
assertEquals(Money.dollar(1), result);
}

// Bank
Money reduce(Expression source, String to) {
if (source instanceof Money) return (Money) source;
Sum sum = (Sum) source;
return sum.reduce(to);
}

μ§€μ €λΆ„ν•˜λ‹€, 지저뢄해. κ·Έλž˜λ„ 초둝 λ§‰λŒ€ μƒνƒœμ΄λ―€λ‘œ λ¦¬νŒ©ν† λ§μ„ ν•  수 μžˆλ‹€. 클래슀λ₯Ό λͺ…μ‹œμ μœΌλ‘œ κ²€μ‚¬ν•˜λŠ” μ½”λ“œκ°€ μžˆμ„ λ•Œμ—λŠ” 항상 λ‹€ν˜•μ„±μ„ μ‚¬μš©ν•˜λ„λ‘ λ°”κΎΈλŠ” 것이 μ’‹λ‹€. Sum은 reduce(String)λ₯Ό κ΅¬ν˜„ν•˜λ―€λ‘œ, Money도 그것을 κ΅¬ν˜„ν•˜λ„λ‘ λ§Œλ“ λ‹€λ©΄ reduce()λ₯Ό Expression μΈν„°νŽ˜μ΄μŠ€μ—λ„ μΆ”κ°€ν•  수 있게 λœλ‹€.

// Bank
Money reduce(Expression source, String to) {
if (source instanceof Money)
return (Money) source.reduce(to);
Sum sum = (Sum) source;
return sum.reduce(to);
}

// Money
public Money reduce(String to) {
return this;
}

Expression μΈν„°νŽ˜μ΄μŠ€μ— reduce(String)λ₯Ό μΆ”κ°€ν•˜λ©΄,

// Expression
Money reduce(String to);

μ§€μ €λΆ„ν•œ μΊμŠ€νŒ…κ³Ό 클래슀 검사 도ꡬλ₯Ό μ œκ±°ν•  수 μžˆλ‹€.

// Bank
Money reduce(Expression source, String to) {
return source.reduce(to);
}