๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒˆ Chapter 14: ๋ฐ”๊พธ๊ธฐ

2ํ”„๋ž‘์ด ์žˆ๋Š”๋ฐ ์ด๊ฑธ ๋‹ฌ๋Ÿฌ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค.

public void testReduceMoneyDifferentCurrency() {
Bank bank = new Bank();
bank.addRate("CHF", "USD", 2);
Money result = bank.reduce(Money.franc(2), "USD");
assertEquals(Money.dollar(1), result);
}

๋‚˜๋Š” ํ”„๋ž‘์„ ๋‹ฌ๋Ÿฌ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ๋‚˜๋ˆ„๊ธฐ 2๋ฅผ ํ•œ๋‹ค. ๋‹ค์Œ ํ•œ ์คŒ์˜ ์ง€์ €๋ถ„ํ•œ ์ฝ”๋“œ๋ฉด ์ดˆ์ด‰ ๋ง‰๋Œ€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

// Money
public Money reduce(String to) {
int rate = (currency.equals("CHF") && to.equals("USD")) ? 2 : 1;
return new Money(amount / rate, to);
}

ํš์œจ์— ๋Œ€ํ•œ ์ผ์€ ๋ชจ๋‘ Bank๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. Expression.reduce()์˜ ์ธ์ž๋กœ Bank๋ฅผ ๋„˜๊ฒจ์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ์šฐ์„  ํ˜ธ์ถœํ•˜๋Š” ๋ถ€๋ถ„์„ ์ž‘์„ฑํ•˜์ž.

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

๊ทธ๋ฆฌ๊ณ  ๊ตฌํ˜„ ๋ถ€๋ถ„.

// Expression
Money reduce(Bank bank, String to);

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

// Money
public Money reduce(Bank bank, String to) {
int rate = (currency.equals("CHF") && to.equals("USD")) ? 2 : 1;
return new Money(amount / rate, to);
}

์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋Š” ๊ณต์šฉ์ด์–ด์•ผ ํ•˜๋ฏ€๋กœ Money์˜ reduce()๋„ ๊ณต์šฉ์ด์–ด์•ผ ํ•œ๋‹ค. ์ด์ œ ํš์œจ์„ Bank์—์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋๋‹ค.

// Bank
int rate(String from, String to) {
return (from.equals("CHF") && to.equals("USD")) ? 2 : 1;
}

๊ทธ๋ฆฌ๊ณ  ์˜ฌ๋ฐ”๋ฅธ ํ™˜์œจ์„ bank์—๊ฒŒ ๋ฌผ์–ด๋ณด์ž.

// Money
public Money reduce(Bank bank, String to) {
int rate = bank.rate(currency, to);
return new Money(amount / rate, to);
}

๊ท€์ฐฎ์€ 2๊ฐ€ ์•„์ง๋„ ํ…Œ์ŠคํŠธ์™€ ์ฝ”๋“œ ๋‘ ๋ถ€๋ถ„์— ๋ชจ๋‘ ๋‚˜์˜จ๋‹ค. ์ด๊ฑธ ์—†์• ๋ฒ„๋ฆฌ๋ ค๋ฉด Bank์—์„œ ํ™˜์œจํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผํ•œ๋‹ค. ํ‚ค๋ฅผ ์œ„ํ•œ ๊ฐ์ฒด๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์•ผ๊ฒ ๋‹ค.

// Pair
private class Pair {
private String from;
private String to;

Pair(String from, String to) {
this.from = from;
this.to = to;
}

public boolean equals(Object object) {
Pair pair = (Pair) object;
return from.equals(pair.from) && to.equals(pair.to);
}

public int hashCode() {
return 0;
}
}

0์€ ์ตœ์•…์˜ ํ•ด์‹œ ์ฝ”๋“œ๋‹ค. ํ•˜์ง€๋งŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ๋นจ๋ฆฌ ๋‹ฌ๋ฆด ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ด๋Œ€๋กœ ๋‘”๋‹ค๋ฉด ํ•ด์‹œ ํ…Œ์ด๋ธ”์—์„œ์˜ ๊ฒ€์ƒ‰์ด ๋งˆ์น˜ ์„ ํ˜• ๊ฒ€์ƒ‰๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์ˆ˜ํ–‰๋  ๊ฒƒ์ด๋‹ค. ๋‚˜์ค‘์— ๋งŽ์€ ํ†ตํ™”๋ฅผ ๋‹ค๋ค„์•ผ ํ•  ์ผ์ด ์ƒ๊ธฐ๋ฉด ๊ทธ๋•Œ ์‹ค์ œ ์ธก์ • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ์„ ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ์ผ๋‹จ, ํ™˜์œจ์„ ์ €์žฅํ•  ๋ญ”๊ฐ€๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

// Bank
private Hashtable rates = new Hashtable();

ํ™˜์œจ์„ ์„ฑ์ •ํ•  ์ˆ˜๋„ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

// Bank
void addRate(String from, String to, int rate) {
rates.put(new Pair(from, to), new Integer(rate));
}

๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•  ๋•Œ ํ™˜์œจ์„ ์–ป์–ด๋‚ผ ์ˆ˜๋„ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

// Bank
int rate(String from, String to) {
Integer rate = (Integer) rates.get(new Pair(from, to));
return rate.intValue();
}

์ž ๊น! ๋นจ๊ฐ„ ๋ง‰๋Œ€๋‹ค. ๋ฌด์Šจ ์ผ์ผ๊นŒ? ์—ฌ๊ธฐ์ €๊ธฐ ์กฐ๊ธˆ ๊ธฐ์›ƒ๊ฑฐ๋ ค ๋ณด๋ฉด, USD์—์„œ USD๋กœ์˜ ํ™˜์œจ์„ ์š”์ฒญํ•˜๋ฉด ๊ทธ ๊ฐ’์ด 1์ด ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ๊ธฐ๋Œ€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋œป๋ฐ–์˜ ์ผ์ด๋ฏ€๋กœ, ์ข€ ์ „์— ์šฐ๋ฆฌ๊ฐ€ ๋ฐœ๊ฒฌํ•œ ๋‚ด์šฉ์„ ๋‚˜์ค‘์— ์ฝ”๋“œ๋ฅผ ์ฝ์–ด๋ณผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋„ ์•Œ๋ ค ์ฃผ๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋กœ ๋งŒ๋“ค์–ด ๋‘์ž.

public void testIdentityRate() {
assertEquals(1, new Bank().rate("USD", "USD"));
}

์ด์ œ ์—๋Ÿฌ๊ฐ€ ์ด ๋‘ ๊ฐœ๋‹ค. ํ•˜์ง€๋งŒ ํ•œ ๊ณณ๋งŒ ๋ฐ”๊ฟ” ์ฃผ๋ฉด ๋‘ ๊ฐœ๊ฐ€ ๋ชจ๋‘ ์—†์–ด์งˆ ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

// Bank
int rate(String from, String to) {
if (from.equals(to)) return 1;
Integer rate = (Integer) rates.get(new Pair(from, to));
return rate.intValue();
}

์ดˆ๋ก ๋ง‰๋Œ€!