ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ ch 5-10

AUSG

TDD

10/05/2020


๋ณธ ๊ธ€์€ ์ผ„ํŠธ ๋ฐฑ์˜ <ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ>์„ ์ฝ๊ณ  ๊ฐœ์ธ์ ์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ์‹œ ์ง€์ ํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

5์žฅ ์†”์งํžˆ ๋งํ•˜์ž๋ฉด

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF

Dollar ๊ฐ์ฒด๋ฅผ ๋น„์Šทํ•˜๊ฒŒ ๋ณธ๋”ด Franc ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋ณธ๋‹ค. ์ด์ „์˜ Dollar ํ…Œ์ŠคํŠธ์—์„œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.(์žฌ์‚ฌ์šฉ์„ฑ!)

JAVA
public void testFrancMultiplication() {
Franc five = new Franc(5);
assertEquals(new Franc(10), five.times(2));
assertEquals(new Franc(15), five.times(3));
}

์ด์ œ ์ด์ „์— Dollar ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฒช์—ˆ๋˜ ๊ธธ์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ๊ฐ„๋‹ค(๋ณต๋ถ™!)

JAVA
class Franc {
private int amount;
Franc(int amount) {
this.amount = amount;
}
Franc times(int multiplier) {
return new Franc(amount * multiplier);
}
public boolean equals(Object object){
Franc franc = (Franc) object;
return amount == franc.amount;
}
}

์ปดํŒŒ์ผ์€ ์ผ๋‹จ ์„ฑ๊ณต!

๊ทธ๋Ÿฌ๋‚˜ ์ด์ „์— ๋งŒ๋“ค์—ˆ๋˜ Dollar ์ฝ”๋“œ์™€ ์ค‘๋ณต์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ค์Œ ์žฅ์—์„œ๋Š” ์ค‘๋ณต์„ ๊ณ ์ณ์„œ ์žฌ ์ž‘์„ฑํ•  ๊ฒƒ์ด๋‹ค.

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times


6์žฅ ๋Œ์•„์˜จ '๋ชจ๋‘๋ฅผ ์œ„ํ•œ ํ‰๋“ฑ'

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times

Franc์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์ง€๋งŒ, ๋ณต๋ถ™ํ•˜๋Š” ๊ณผ์ •์—์„œ Dollar ๊ฐ์ฒด์™€ ์ค‘๋ณต์ด ๋„ˆ๋ฌด ๋งŽ์ด ์ƒ๊ฒจ๋ฒ„๋ ธ๋‹ค.

๋”ฐ๋ผ์„œ ๋‘ ๊ฐ์ฒด์˜ ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ณตํ†ต ์ƒ์œ„ ํด๋ž˜์Šค Money์˜ ์ฝ”๋“œ๋กœ ๋บ€ ํ›„, Dollar ์™€ Franc ์ด ๋ชจ๋‘ ์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ฒŒ ํ•  ๊ฒƒ์ด๋‹ค.

JAVA
class Money{
protected int amount; // ํ•˜์œ„ ํด๋ž˜์Šค(Dollar, Franc)์—์„œ๋„ ๋ณ€์ˆ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ๊ฐ€์‹œ์„ฑ์„ private -> protected๋กœ ๋ณ€๊ฒฝ
}
class Dollar extends Money {
}

amount ๋ฅผ Money ์˜ ํ•„๋“œ๋กœ ๋บ๋‹ค๋ฉด, ๋‹ค์Œ์€ equals ์ฝ”๋“œ๋ฅผ ๋นผ ์˜ฌ๋ฆด ์ฐจ๋ก€๋‹ค.

ย JAVA
// Money
public boolean equals(Object object) {
Money money = (Money) object;
return amount == money.amount;
}

์œ„์˜ ๊ณผ์ •์€ ์ถ•์•ฝํ•ด์„œ ํ•œ๋ฒˆ์— ์ ์—ˆ์ง€๋งŒ, ์ฑ…์—์„œ๋Š” Dollar ๊ฐ์ฒด ๋‚ด์—์„œ ํƒ€์ž… ์บ์ŠคํŒ… ํ•˜๋‚˜, ๋ณ€์ˆ˜๋ช… ํ•˜๋‚˜๋ฅผ ๋ฐ”๊ฟ€๋•Œ๋งˆ๋‹ค ํ…Œ์ŠคํŠธ์ฝ”๋“œ์— ์ด์ƒ์ด ์—†๋Š”์ง€ ๋Œ๋ ค๊ฐ€๋ฉฐ ์ˆ˜ํ–‰ํ•˜๊ณ , Money ์˜ ๋ฉ”์„œ๋“œ๋กœ ์™„์ „ํžˆ ๋ฆฌํŒฉํ† ๋งํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐ๋  ๋•Œ Money ๋กœ ์˜ฎ๊ธด๋‹ค. ์ •๋ง ์ฐจ๊ทผ์ฐจ๊ทผ ์กฐ๊ธˆ์”ฉ ํ•˜๋Š” ์…ˆ.

Money ์— ์ผ๋ฐ˜ํ™”๋œ equals ์˜ ์ฝ”๋“œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ์ด์ œ Franc ์˜ equals ๋ฅผ ์ œ๊ฑฐํ•ด์•ผํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด์ „์— ๋งŒ๋“ค์–ด๋’€๋˜ ๋™์น˜์„ฑ ํ…Œ์ŠคํŠธ( testmultiplication )๊ฐ€ Franc ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” ๋น„๊ตํ•˜๊ณ  ์žˆ์ง€ ์•Š์œผ๋ฏ€๋กœ, Franc ๋„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (๋ชจ๋“  ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ๋‚ด๋ถ€ ๋กœ์ง์„ ํ…Œ์ŠคํŠธํ•˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€๋กœ ๋“œ๋Ÿฌ๋‚˜๋Š” ๊ฒฐ๊ณผ-๊ทธ๋ž˜์„œ equals์ธ๊ฑฐ์•ผ?-์— ๋Œ€ํ•ด์„œ ํ…Œ์ŠคํŠธํ•œ๋‹ค. ์™ธ๋ถ€, ์™ธ๋ถ€.)

JAVA
public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
assertFalse(new Dollar(5).equals(new Dollar(6)));
assertTrue(new Franc(5).equals(new Franc(5)));
assertFalse(new Franc(5).equals(new Franc(6)));
/*
์ค‘๋ณต๋œ assertTrue, assertFalse ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ๋Š” ์ถ”ํ›„์— ๋ฆฌํŒฉํ† ๋งํ•œ๋‹ค.
*/
}

Franc ์˜ equals ๋„ Dollar ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฆฌํŒฉํ† ๋ง ํ•œ ํ›„, ์ƒ์œ„ ํด๋ž˜์Šค Money ์˜ equals ์™€ ๋‹ค๋ฅธ ์ ์ด ์—†์Œ์„ ํ™•์ธํ•˜๊ณ  ์ œ๊ฑฐํ•œ๋‹ค.

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ


7์žฅ ์‚ฌ๊ณผ์™€ ์˜ค๋ Œ์ง€

*์„œ๋กœ ๋‹ค๋ฅธ ๊ณผ์ผ์ธ ์‚ฌ๊ณผ์™€ ์˜ค๋ Œ์ง€์™€ ๊ฐ™์ด, ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋น„๊ตํ•  ์ˆ˜ ์—†์Œ์„ ์ด๋ฅด๋Š” ๊ด€์šฉ์–ด๊ตฌ์ด๋‹ค.

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ

๋งŒ์•ฝ์—, Franc๊ณผ Dollar๋ฅผ ๋น„๊ตํ•œ๋‹ค๋ฉด ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ์ผ์–ด๋‚ ๊นŒ?

JAVA
public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
assertFalse(new Dollar(5).equals(new Dollar(6)));
assertTrue(new Franc(5).equals(new Franc(5)));
assertFalse(new Franc(5).equals(new Franc(6)));
assertFalse(new Franc(5).equals(new Dollar(5)));
}

๋‹น์—ฐํžˆ java ๊ฐ์ฒด์ƒ Franc์™€ Dollar๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด์ด๋ฏ€๋กœ ์‹คํŒจํ•œ๋‹ค.

์ด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ•˜์—ฌ, ๋‘ ํ†ตํ™”(Currency)๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋‹ค๋ฅด๋ฉด ๋™์น˜์„ฑ ๋น„๊ต๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ž.

JAVA
public boolean equals(Object object) {
Money money = (Money) object;
return amount == money.amount && getClass().equals(money.getClass());
}

์•„์ง ํ†ตํ™”(Currency)์˜ ๊ฐœ๋…์ด ์—†์œผ๋ฏ€๋กœ, equals ๋ฉ”์†Œ๋“œ๋Š” ๋‘ ๊ฐ์ฒด(ํ†ตํ™”)์˜ ํด๋ž˜์Šค๊ฐ€ ์™„์ „ํžˆ ๋™์ผํ•ด์•ผ ํ•œ๋‹ค๋Š” ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์ž๋ฐ” ์ฝ”๋“œ(ํด๋ž˜์Šค)์ ์ธ ์ธก๋ฉด์ด์ง€, ์žฌ์ • ๊ฐœ๋…์ ์œผ๋กœ ๋ช…ํ™•ํ•œ ๋น„๊ต๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ผ๋‹จ ๋‹น์žฅ์— ํ†ตํ™” ๊ฐœ๋…์„ ๋งŒ๋“ค์–ด์•ผ ํ•  ํ•„์š”์„ฑ์€ ์—†์œผ๋‹ˆ ์ผ๋‹จ ํ• ์ผ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•ด ๋‘”๋‹ค.

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?

์ด์ œ ๋‹ค์Œ์žฅ์—์„œ๋Š” ๊ณตํ†ต์˜ times() ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•ด๋ณด๊ธฐ๋กœ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ํ˜ผํ•ฉ๋œ ํ†ตํ™”์˜ ์—ฐ์‚ฐ์„ ๋‹ค๋ฃฐ๊ฒƒ์ด๋‹ค.


8์žฅ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?

JAVA
// Franc code
Franc times(int multiplier) {
return new Franc(amount * multiplier)
}
// Dollar code
Dollar times(int multiplier) {
return new Dollar(amount * multiplier)
}

ํ˜„์žฌ Franc๊ณผ Dollar์˜ times() ์ฝ”๋“œ๋Š” ๊ฐœ๋…์ ์œผ๋กœ ์™„์ „ํžˆ ๋™์ผํ•˜๋‹ค.(๋ณต๋ถ™์˜ ํํ•ด..)

JAVA
// Franc code
Money times(int multiplier) {
return new Franc(amount * multiplier)
}
// Dollar code
Money times(int multiplier) {
return new Dollar(amount * multiplier)
}

์–‘์ชฝ ๋ชจ๋‘ Money ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ๋‘ ๊ฐ์ฒด์˜ times ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค ์‚ญ์ œํ•˜๊ณ  ์ƒ์œ„์—์„œ ๋ฆฌํŒฉํ† ๋งํ•˜๋Š”๊ฒƒ์€ ํšจ์œจ์ ์ธ TDD๊ฐ€ ์•„๋‹Œ ๊ฒƒ ๊ฐ™๋‹ค.(์•ผ๊ธˆ์•ผ๊ธˆ, ์‚ด๊ธˆ์‚ด๊ธˆ!)

Money ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ธ Dollar, Franc ํด๋ž˜์Šค์˜ ์ง์ ‘์ ์ธ ์ฐธ์กฐ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ, Money ๊ฐ์ฒด ๋‚ด๋ถ€์— ํ•˜์œ„ ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด ์–ด๋–จ๊นŒ?

JAVA
// Money ์ฝ”๋“œ
// Money ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ, dollar ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
static Dollar dollar(int amount) {
return new Dollar(amount);
}

JAVA
public void testMultiplication() {
Money five = Money.dollar(5); // ์›๋ž˜ ์ฝ”๋“œ๋Š” Dollar five = new Dollar(5);
assertEquals(new Dollar(10), five.times(2));
assertEquals(new Dollar(15), five.times(3));
}

๊ทธ๋Ÿฌ๋‚˜ ์ด๋ ‡๊ฒŒ ๋ฐ”๊พธ์—ˆ์„ ๊ฒฝ์šฐ์—, Money.times() ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์—๋Ÿฌ๋ฅผ ๋ฑ‰๋Š”๋‹ค. ๋”ฐ๋ผ์„œ Money๋ฅผ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ, Money.times() ๋ฅผ ์„ ์–ธํ•ด์ค€๋‹ค.

JAVA
// Money ์ฝ”๋“œ
abstract class Money
abstract Money times(int multiplier);
// ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์„ ์–ธ์„ Money๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.
static Money dollar(int amount) { // ์›๋ž˜ ์ฝ”๋“œ๋Š” static Dollar dollar(int amount)
return new Dollar(amount);
}
// ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Franc๋„ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค.
static Money franc(int amount) { // ์›๋ž˜ ์ฝ”๋“œ๋Š” static Franc franc(int amount)
return new Franc(amount);
}

์ด์ œ ๊ธฐ์กด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ Dollar, Franc ํ•˜์œ„ ๊ฐ์ฒด ์ง์ ‘ ํ˜ธ์ถœ์„ ๋ฆฌํŒฉํ† ๋งํ•ด์ค€๋‹ค.

JAVA
public void testMultiplication() {
Money five = Money.dollar(5);
assertEquals(Money.Dollar(10), five.times(2));
assertEquals(Money.Dollar(15), five.times(3));
}
public void testEquality() {
assertTrue(Money.dollar(5).equals(Money.dollar(5)));
assertFalse(Money.dollar(5).equals(Money.dollar(6)));
assertTrue(Money.franc(5).equals(Money.franc(5)));
assertFalse(Money.franc(5).equals(Money.franc(6)));
assertFalse(Money.franc(5).equals(Money.dollar(5)));
}

์ด์ œ Money์˜ ํ•˜์œ„ ํด๋ž˜์Šค Dollar, Franc์˜ ์กด์žฌ๋ฅผ ํ…Œ์ŠคํŠธ์—์„œ ์™„์ „ํžˆ ๋ถ„๋ฆฌํ–ˆ๋‹ค.๋”ฐ๋ผ์„œ ์ƒ์†๊ตฌ์กฐ๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค(์ด๊ฒŒ ์–ด๋–ค ๋ง์ธ์ง€ ์•„์ง ์ •ํ™•ํžˆ ์ดํ•ด๊ฐ€ ๊ฐ€์ง€๋Š” ์•Š๋Š”๋‹ค). ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์กด์žฌ๋ฅผ ๋ถ„๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด๋‹ค. ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ (์™ธ๋ถ€) ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋–ผ์–ด๋‚ด๋Š” ๊ฒƒ์„ ์ž˜ ๊ธฐ์–ตํ•ด๋‘์ž.

๊ทธ๋Ÿฐ๋ฐ ์ด์ „์— ๋งŒ๋“ค์–ด๋‘์—ˆ๋˜ testFrancMultiplication() ์ด ์ปค๋ฒ„ํ•˜๋Š” ๋ถ€๋ถ„์ด, Dollar์— ๋Œ€ํ•œ ๊ณฑํ•˜๊ธฐ ํ…Œ์ŠคํŠธ์ฝ”๋“œ์ธ testMultiplication() ๊ณผ ๋™์ผํ•œ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์กด์žฌ ์ž์ฒด๋ฅผ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋–ผ๋‚ด๋ ค๊ณ  ํ•˜๋Š”๋ฐ, ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํ•˜์œ„ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ์…ˆ์ด๋‹ค.

JAVA
public void testFrancMultiplication() {
Franc five = new Franc(5);
assertEquals(new Franc(10), five.times(2));
assertEquals(new Franc(15), five.times(3));
}

์ด ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•˜์—ฌ ์‚ญ์ œํ• ์ง€ ์–ด์ฉ”์ง€๋Š”, ํ• ์ผ ๋ชฉ๋ก์— ์ผ๋‹จ ์ถ”๊ฐ€ํ•ด๋‘๋„๋ก ํ•˜์ž. ์•„์ง ์ฝ”๋“œ์— ๋Œ€ํ•œ ์™„์ „ํ•œ ํ™•์‹ ์€ ์—†์œผ๋‹ˆ๊นŒ..

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?
โ—ฆ testFrancMultiplication์„ ์ง€์›Œ์•ผํ• ๊นŒ?


9์žฅ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ๋Š” ์‹œ๊ฐ„(time, ๊ณฑํ•˜๊ธฐ)

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?
โ—ฆ testFrancMultiplication ์ œ๊ฑฐ

ํ†ตํ™” ๊ฐœ๋…์˜ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์งœ๊ธฐ ์œ„ํ•ด์„œ, ํ†ตํ™”๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋“ค์ด ํ•„์š”ํ•˜๋‹ค. ๊ฐ๊ฐ ๊ตฌํ˜„ํ• ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ, ์ผ๋‹จ์€ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•ด์„œ ํ‘œํ˜„ํ•œ๋‹ค.

JAVA
public void testCurrency() {
assertEquals("USD", Money.dollar(1).currency());
assertEquals("CHF", Money.franc(1).currency());
}

Franc์™€ Dollar ๋‘ ํด๋ž˜์Šค์— ๊ฐ™์€ currency() ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์— ๋ฌธ์ž์—ด์„ ์ €์žฅํ•œ ํ›„ ๋ฉ”์„œ๋“œ์—์„œ ๊ทธ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
abstract String currency();
// Franc ์ฝ”๋“œ
private String currency;
Franc(int amount) {
this.amount = amount;
currency = "CHF";
}
String currency() {
return currency;
}
// Dollar ์ฝ”๋“œ
private String currency;
Dollar(int amount) {
this.amount = amount;
currency = "USD";
}
String currency() {
return currency;
}

๋‘ ํ•˜์œ„ํด๋ž˜์Šค์˜ currency() ๊ฐ€ ๋™์ผํ•˜๊ณ , ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋„ ๋™์ผํ•˜๋ฏ€๋กœ ์ด ๋‘ ๋ถ€๋ถ„์„ ์ƒ์œ„ ํด๋ž˜์Šค๋กœ ์˜ฌ๋ฆด(push up) ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
protected String currency;
String currency() {
return currency;
}

'USD'์™€ 'CHF' ๋ฌธ์ž์—ด์„ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์˜ฎ๊ธด๋‹ค๋ฉด ๋‘ ์ƒ์„ฑ์ž๋Š” ๋™์ผํ•ด์งˆ๊ฑฐ๊ณ , ๊ณตํ†ต ๊ตฌํ˜„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
// Franc์˜ ์ƒ์„ฑ์ž
Franc(int amount, String currency) {
this.amount = amount;
this.currency = "CHF";
}

์ƒ์„ฑ์ž๋ฅผ ์ธ์ž์— ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

์ƒ์„ฑ์ž์— ์ธ์ž๋ฅผ ์ถ”๊ฐ€ํ–ˆ์œผ๋‹ˆ, ๋‹น์—ฐํžˆ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ถ€๋ถ„๋“ค์ด ๊นจ์ง„๋‹ค. ๊นจ์ง€๋Š” ๋ถ€๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

JAVA
// Money ์ฝ”๋“œ
// #1
static Money franc(int amount) {
return new Franc(amount, null);
}
// Franc ์ฝ”๋“œ
// #2
Money times(int multiplier) {
return new Franc(amount * multiplier, null);
}

#2์—์„œ times() ๊ฐ€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•˜๋Š”๋ฐ, ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒ์„ฑ์ž๋ฅผ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์ •๋ฆฌํ•ด์ค€๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
// #2
Money times(int multiplier) {
return Money.franc(amount * multiplier);
}

์ด์ œ #1์—์„œ Money์˜ ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ franc() ์ด "CHF"๋ฅผ ์ „๋‹ฌํ•˜๋„๋ก, null๊ฐ’์„ ๋ฐ”๊พธ์–ด์ฃผ๋ฉด๋œ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
// #1
static Money franc(int amount) {
return new Franc(amount, "CHF");
}

๊ทธ๋Ÿฌ๊ณ  ๋‚˜๋ฉด ๋น„๋กœ์†Œ ์ƒ์„ฑ์ž Franc์ด "CHF"๋ฅผ ์ธ์ž๋กœ ์ž๋™์œผ๋กœ ์ „๋‹ฌ๋ฐ›๋„๋ก ๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ธ์Šคํ„ด์Šค ๋‚ด๋ถ€์—์„œ "CHF"๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ์ธ์ž๋กœ ๋“ค์–ด์˜จ currency๋ฅผ ๊ทธ๋Œ€๋กœ ๋„˜๊ฒจ์ฃผ๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
// Franc์˜ ์ƒ์„ฑ์ž
Franc(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}

์ด์ฒ˜๋Ÿผ ์ž˜๊ฒŒ [constant, ๋ฌธ์ž์—ด ๋“ฑ์„ ๋„˜๊ฒผ๋‹ค๊ฐ€] - [๊ณตํ†ต ๋ถ€๋ถ„์„ push upํ•˜๊ณ ] - [๋‚ด๋ถ€์˜ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ์ฝ”๋“œ๋“ค์„ ๋ฆฌํŒฉํ† ๋งํ•ด๊ฐ€๋Š” ๊ฒƒ]์ด ๊ฑฐ๋ถ€๊ฐ์ด ๋“ค๊ธด ํ•œ๋‹ค. ์ „์ฒด์ ์œผ๋กœ ๋ณด๋ฉด ๋‚˜๋„ ์ด๋Ÿฐ ๊ณผ์ •๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งคํ…Œ์ง€๋งŒ, ์ด๊ฑธ ์˜์‹์ ์œผ๋กœ ํ•ญ์ƒ ๋”ฐ๋ผํ•˜๊ธฐ์—๋Š” ๋ฌด๋ฆฌ๊ฐ€ ์žˆ๋Š”๊ฒƒ๊ฐ™๋‹ค. ์ €์ž๋Š” '์ด๋Ÿฐ์‹์œผ๋กœ ํ•˜๋ผ'๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ '์ด๋Ÿฐ์‹์œผ๋กœ ํ•  ์ค„๋„ ์•Œ์•„์•ผํ•œ๋‹ค'๋ผ๋Š” ์ž…์žฅ์ด๋‹ค.

Dollar๋„ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
// ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ dollar
static Money dollar(int amount) {
return new Dollar(amount, "USD"); // ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ dollar๋Š” ์ƒ์„ฑ์ž์˜ currency์— ํ•ญ์ƒ "USD"๋ฅผ ๋„˜๊ฒจ์คŒ(ํ†ตํ™”๋ฅผ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด ์—ฌ๊ธฐ๋งŒ ๊ณ ์น˜๋ฉด ๋ผ!)
}
// Dollar ์ฝ”๋“œ
Dollar(int amount, String currency) {
this.amount = amount;
this.currency = currency; // ์ธ์ž๋ฅผ ์ด์šฉํ•˜์—ฌ currency ์ธ์Šคํ„ด์Šค๋ณ€์ˆ˜๋ฅผ ์„ ์–ธ
}
Money times(int multiplier) {
return Money.dollar(amount * multiplier); // ์ƒ์„ฑ์ž๋ฅผ ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ๋กœ ๋Œ€์ฒด
}

๋‘ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์ด ๋น„์Šทํ•ด์กŒ์œผ๋ฏ€๋กœ , ๊ตฌํ˜„์„ ์ƒ์œ„ ํด๋ž˜์Šค๋กœ ์˜ฌ๋ฆฐ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
Money(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}
// Franc ์ฝ”๋“œ
Franc(int amount, String currency) {
super(amount, currency);
}
// Dollar ์ฝ”๋“œ
Dollar(int amount, String currency) {
super(amount, currency);
}

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?
โ—ฆ testFrancMultiplication ์ œ๊ฑฐ

์ง€๊ธˆ๊นŒ์ง€ Dollar์™€ Franc์˜ ์ค‘๋ณต ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๋ ค๋‹ค๊ฐ€, ์ž‘์€ ๋ฌธ์ œ๋“ค(๊ฐ ๋ฉ”์„œ๋“œ, ๋ณ€์ˆ˜๋“ค์˜ push up)์„ ๋งŽ์ด ๋งž๋‹ฅ๋œจ๋ ธ๋‹ค. ํ•˜์œ„ํด๋ž˜์Šค ์ƒ์„ฑ์ž๋“ค์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋“ค์„ ์ผ์น˜์‹œํ‚ค๊ณ  ์ด๋ฅผ push upํ–ˆ๋‹ค. ๋˜, times()๊ฐ€ ์ƒ์„ฑ์ž๊ฐ€ ์•„๋‹Œ ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค(์ƒ์œ„ํด๋ž˜์Šค๋กœ times()๋ฅผ ์˜ฎ๊ธฐ๊ธฐ ์œ„ํ•œ ๋ฐœํŒ์ด๋‹ค) ์ด์ œ times() ๋ฅผ ์ƒ์œ„ํด๋ž˜์Šค๋กœ ์˜ฌ๋ฆฌ๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐ ํ•  ์ค€๋น„๊ฐ€ ๊ฑฐ์˜ ๋‹ค ๋œ ๊ฒƒ ๊ฐ™๋‹ค.


10์žฅ ํฅ๋ฏธ๋กœ์šด ์‹œ๊ฐ„

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?
โ—ฆ testFrancMultiplication ์ œ๊ฑฐ

์ด๋ฒˆ ์žฅ์—์„œ Money๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๊ณ , Money ํด๋ž˜์Šค๋งŒ ๋‚จ๊ฒจ๋‘˜ ๊ฒƒ์ด๋‹ค(๋ฆฌํŒฉํ† ๋ง ์™„์„ฑ!)

์ผ๋‹จ ๋‘ ํ•˜์œ„ํด๋ž˜์Šค์˜ times() ํ•จ์ˆ˜๋ฅผ ๋น„๊ตํ•ด๋ณด์ž.

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return Money.franc(amount * multiplier);
}
// Dollar ์ฝ”๋“œ
Money times(int multiplier) {
return Money.dollar(amount * multiplier);
}

์‚ดํŽด๋ณด์•„๋„ ๋‘ ํ•จ์ˆ˜๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งŒ๋“ค ๋ฐฉ๋ฒ•์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” ๋‹ค์‹œ ๋’ค๋กœ ๋Œ์•„๊ฐ€๋ณธ๋‹ค. ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ธ๋ผ์ธ์‹œ์ผœ๋ณธ๋‹ค(๋ฌธ๋งฅ์ƒ ์ƒ์„ฑ์ž ์ฝ”๋“œ๋กœ ์žฌ์ž‘์„ฑํ•œ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ธ ๋“ฏ ํ•˜๋‹ค).

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Franc(amount * multiplier, "CHF");
}
// Dollar ์ฝ”๋“œ
Money times(int multiplier) {
return new Dollar(amount * multiplier, "USD");
}

์ด๋ ‡๊ฒŒ ๋ฐ”๊พธ๊ณ  ๋ณด๋‹ˆ, Franc๊ณผ Dollar๋Š” ๋ชจ๋‘ ๊ฐ™์€ ์ด๋ฆ„์˜ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜ currency๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ๋งˆ์นจ "CHF", "USD"์™€ ๋งž์•„๋–จ์–ด์ง„๋‹ค. ํ•˜๋“œ์ฝ”๋”ฉ๋œ "CHF", "USD"๋ฅผ ๋™์ผํ•œ currency๋กœ ๋ฐ”๊ฟ”๋ณธ๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Franc(amount * multiplier, currency);
}
// Dollar ์ฝ”๋“œ
Money times(int multiplier) {
return new Dollar(amount * multiplier, currency);
}

๊ทธ๋Ÿผ ์ด์ œ ์ฝ”๋“œ์—์„œ ๋‹ค๋ฅธ ๋ถ€๋ถ„์€ ์ƒ์„ฑ์ž ๋ถ€๋ถ„ (new Franc ์™€ new Dollar )๋ฐ–์— ์—†๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด๊ฑธ ๋‘˜๋‹ค Money๋กœ ๋ฐ”๊ฟ”๋„ ์ž˜ ์ž‘๋™ํ• ๊นŒ..?

์‹ฌ์‚ฌ์ˆ™๊ณ ์—์„œ ์ถ”๋ฆฌํ• ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ๋ฏธ๋ฆฌ ์งœ๋†จ์œผ๋‹ˆ ํ•œ๋ฒˆ ๋Œ๋ ค๋ณด๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Money(amount * multiplier, currency);
}

Money๊ฐ€ ์ง€๊ธˆ abstract class(์ถ”์ƒ ํด๋ž˜์Šค)์ธ๋ฐ, concrete class(๊ตฌ์ƒ ํด๋ž˜์Šค)๋กœ ๋ฐ”๊พธ๋ผ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋œฌ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
class Money
Money times(int amount) {
return null;
}

Money์˜ ์˜คํผ๋ ˆ์ด์…˜์ด ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๋„๋ก ์ตœ์†Œํ•œ์˜ times์ฝ”๋“œ๋ฅผ ์งฐ๋‹ค.

๋Œ๋ฆฌ๊ณ  ๋‚˜๋‹ˆ ๋นจ๊ฐ„๋ง‰๋Œ€(์—๋Ÿฌ๋ฉ”์‹œ์ง€)๊ฐ€ ๋œจ๋Š”๋ฐ, ๋ฉ”์‹œ์ง€๊ฐ€ ๋ญ๋ผ๊ณ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
// ๊ฐ์ฒด ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•ด์ฃผ๋Š” ์ŠคํŠธ๋งํ•จ์ˆ˜
public String toString() {
return amount + " " + currency
}

์ด ์ฝ”๋“œ๋ฅผ ์ง  ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ ค๋ณด๋‹ˆ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œฌ๋‹ค.

expected:<10 CHF> but was:<10 CHF>

๋ญ์ง€? ๊ฐ™์€๊ฑด๋ฐ ๋‹ค๋ฅด๋‹ค๊ณ ? ์‚ดํŽด๋ณด๋‹ˆ ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅด๋‹จ๋‹ค. ์•ž์˜ <10 CHF>๋Š” Franc์ธ๋ฐ, ์‹ค์ œ๋กœ ๋“ค์–ด๊ฐ„ ๊ฐ’์ธ ๋’ค์˜ <10 CHF>๋Š” Money๋ž€๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Money(amount * multiplier, currency);
}

์•„๊นŒ times()๊ฐ€ Money๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์งฐ์œผ๋‹ˆ ๋’ค์˜ ๊ฑด ๋งž๋Š”๋ฐ, ์•ž์˜ Franc <10 CHF>๋Š” ์–ด๋””์„œ ๋‚˜์™”์„๊นŒ?

ํ…Œ์ŠคํŠธ์ฝ”๋“œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋–ด์œผ๋‹ˆ ๋น„๊ต์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ์„ํ…๋ฐ... ๊ทธ๋ ‡๋‹ค๋ฉด equals() ๋ฅผ ์‚ดํŽด๋ณด์ž.

JAVA
// Money ์ฝ”๋“œ
public boolean equals(Object object) {
Money money = (Money) object;
return amount = money.amount && getClass().equals(money.getClass());
}

getClass() ๋กœ ํด๋ž˜์Šค๋ฅผ ๋น„๊ตํ•จ์œผ๋กœ์จ ํ†ตํ™”๋ฅผ ๋น„๊ตํ–ˆ๋‹ค๋Š” ์ฐฉ๊ฐ์— ๋น ์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. Money(10, 'CHF')์™€ Franc(10, 'CHF')๋Š” ์„ ์–ธํ•œ ํด๋ž˜์Šค์˜ ์œ„์น˜๋งŒ ๋‹ค๋ฅผ ๋ฟ์ด์ง€. ๋‚ด๋ถ€์˜ currency๋Š” 'CHF'๋กœ ๊ฐ™๋‹ค. ์ฆ‰ ๊ฐ™์€ ํ†ตํ™”์ธ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์œ„์˜ ์ฝ”๋“œ๋Š” ํด๋ž˜์Šค๋ฅผ ๋น„๊ตํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ currency ๋น„๊ต๋กœ ๊ณ ์ณ์•ผํ•  ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ๋ฌธ์ œ์˜ ์›์ธ์„ ํŒŒ์•…ํ–ˆ์œผ๋‹ˆ ๋ฐ”๋กœ ๊ณ ์น ๊นŒ?

๋ณด์ˆ˜์ ์œผ๋กœ ๋ณด๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ๋นจ๊ฐ• ๋ง‰๋Œ€์ธ ๊ฒฝ์šฐ์— ์‹ค์ œ ๋ชจ๋ธ ์ฝ”๋“œ๋ฅผ ๊ณ ์น˜์ง€ ์•Š๋Š”๋‹ค. ๋ถˆํ™•์‹ค์„ฑ ์œ„์— ๋ถˆํ™•์‹ค์„ฑ์„ ๋ง๋ถ™์ด๋Š” ์…ˆ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‹ค์ œ ๋ชจ๋ธ ์ฝ”๋“œ๋ฅผ ๊ฑด๋“œ๋ฆฌ๋ ค๋ฉด ์›์ธ์„ ๋จผ์ € ํŒŒ์•…ํ•˜๊ณ , ์ดˆ๋ก ๋ง‰๋Œ€์—์„œ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค(๋‹จ๋‹จํ•œ ๊ธฐ๋ฐ˜์—์„œ ์‹œ์ž‘ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ž). ๋นจ๊ฐ• ๋ง‰๋Œ€๋ฅผ ๋ณด๊ธฐ ์ง์ „ ์ฝ”๋“œ๋กœ ๋Œ์•„๊ฐ€์ž.

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Franc(amount * multiplier, currency);
}

๊ทธ๋Ÿผ ๋‹ค์‹œ ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ํŒŒ์•…ํ•œ ๋ฌธ์ œ์ -๋‹ค๋ฅธ ํด๋ž˜์Šค๋ผ๋„ currency๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๊ฐ™์€ ํ†ตํ™”๋กœ ์ทจ๊ธ‰ํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ-์„ ๊ทธ๋Œ€๋กœ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋กœ ์งœ๋ณธ๋‹ค.

JAVA
public void testDifferentClassEquality() {
assertTrue(new Money(10, "CHF").equals(new Franc(10, "CHF")));
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์‹คํŒจํ•œ๋‹ค. ์•„์ง ์‹ค์ œ ๋ชจ๋ธ ์ฝ”๋“œ๊ฐ€ currency๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค๋ฅผ ๋น„๊ตํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ…Œ์ŠคํŠธ์˜ fail์„ ํ™•์ธํ•˜๊ณ  ์‹ค์ œ ๋ชจ๋ธ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
public boolean equals(Object object) {
Money money = (Money) object;
return amount = money.amount && currency().equals(money.currency());
}

์ด์ œ ๋‘ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ๋ฆฌํ„ด๊ฐ’์˜ ํด๋ž˜์Šค๋ฅผ Money๋กœ ๋ฐ”๊พธ์–ด๋„ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

JAVA
// Franc ์ฝ”๋“œ
Money times(int multiplier) {
return new Money(amount * multiplier, currency);
}
// Dollar ์ฝ”๋“œ
Money times(int multiplier) {
return new Money(amount * multiplier, currency);
}

๋‘ ๊ตฌํ˜„์ด ๋™์ผํ•ด์กŒ์œผ๋‹ˆ, ์ƒ์œ„ ํด๋ž˜์Šค๋กœ push up ํ•  ์ˆ˜ ์žˆ๋‹ค.

JAVA
// Money ์ฝ”๋“œ
Money times(int multiplier) {
return new Money(amount * multiplier, currency);
}

์ด์ œ ํ•˜์œ„ ํด๋ž˜์Šค Franc์™€ Dollar์—์„œ ํ•˜๋Š” ๋ชจ๋“  ์˜คํผ๋ ˆ์ด์…˜์„ ์ƒ์œ„ ํด๋ž˜์Šค๋กœ ๋Œ์–ด์˜ฌ๋ ธ์œผ๋‹ˆ, Franc์™€ Dollar๋ผ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์„ ์ถฉ๋ถ„ํžˆ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

โ—ฆ 5+10CHF=5 + 10CHF =10(ํ™˜์œจ์ด 2:1์ผ ๊ฒฝ์šฐ)
โ—ฆ 5โˆ—2=5 * 2 =10
โ—ฆ amount๋ฅผ private์œผ๋กœ ๋งŒ๋“ค๊ธฐ
โ—ฆ Dollar ๋ถ€์ž‘์šฉ?
โ—ฆ Money ๋ฐ˜์˜ฌ๋ฆผ?
โ—ฆ equals()
โ—ฆ hashCode()
โ—ฆ Equal null
โ—ฆ Equal object
โ—ฆ 5CHF * 2 = 10CHF
โ—ฆ Dollar/Franc ์ค‘๋ณต
โ—ฆ ๊ณต์šฉ Equals
โ—ฆ ๊ณต์šฉ times
โ—ฆ Franc์™€ Dollar ๋น„๊ตํ•˜๊ธฐ
โ—ฆ ํ†ตํ™”?
โ—ฆ testFrancMultiplication ์ œ๊ฑฐ


WRITTEN BY

์•ŒํŒŒ์นด์˜ Always Awake Devlog

Seoul