๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿคท๐Ÿผ‍โ™€๏ธ Etc.../- ๊ธฐํƒ€

[๊ฐœ๋ฐœ์ž ์ฑ…์ฝ๊ธฐ] ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ - ์ผ„ํŠธ ๋ฒก (๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ)

by Wonit 2021. 4. 10.

ํ•ด๋‹น ๊ธ€์€ Kent-Beck์˜ ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ By Example ์ด๋ผ๋Š” ์ฑ…์„ ์ฝ๊ณ  ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌ ๋ฐ ํšŒ๊ณ ํ•˜๋Š” ๊ธ€ ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์‚ฌํ•ญ์€ YES 24 ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ ์—์„œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ - Test Driven Development By Example (Kent-Beck)

  • ์ธ์‚ฌ์ดํŠธ(insight)
  • ์ง€์€์ด: Kent-Beck
  • ์—ฎ์€์ด: ๊น€์ฐฝ์ค€, ๊ฐ•๊ทœ์—ญ
  • ์ถœ๊ฐ„์ผ: 2014.02.15

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

์—ฌ๊ธฐ Dollar ํด๋ž˜์Šค์™€ Francํด๋ž˜์Šค์˜ times() ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

class Dollar extends Money{
  // ... ์ƒ๋žต
  public Dollar times(int multiplier) {
    return new Dollar(amount * multiplier);
  }
}
class Franc extends Money {
  // ... ์ƒ๋žต
  public Franc times(int multiplier) {
    return new Franc(amount * multiplier);
  }
}

์•„์ฃผ ๊ฑฐ์˜ ๋น„์Šทํ•˜๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ Money๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋”์šฑ ๋น„์Šทํ•ด์ง„๋‹ค.

์—ฌ๊ธฐ์„œ ๋งŒ์•ฝ times๋ฅผ ๊ณตํ†ต์œผ๋กœ ๋ปˆ๋‹ค๊ณ  ์น˜์ž, ๊ทธ๋Ÿผ Dollar์™€ Franc๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ์„ ์–ธ๋งŒ ์กด์žฌํ•˜๋Š” ๋นˆ ํด๋ž˜์Šค๊ฐ€ ๋œ๋‹ค.

์ด ๋‘˜์˜ ๋ฌด์˜๋ฏธํ•จ์„ ํ•œ๋ฒˆ์— ์—†์• ๊ณ ์‹ถ์ง€๋งŒ ๋„ˆ๋ฌด ํฐ ์ผ์ด๋ผ ์ž‘์€ ์ผ๋ถ€ํ„ฐ ํ…Œ์ŠคํŠธ๋กœ ์ˆ˜ํ–‰ํ•ด๊ฐ€๋Š” TDD์˜ ๋ชฉ์ ์— ์•Œ๋งž์ง€ ์•Š๋‹ค.

์ž‘์€ ๊ฒƒ๋ถ€ํ„ฐ ํ•ด๋ณด์ž.

Dollar์™€ Franc์„ ์—†์• ๊ธฐ ์œ„ํ•œ ๋…ธ๋ ฅ

1. ์ง์ ‘ ์ฐธ์กฐ๋ฅผ ์—†์• ์ž.

์—ฌ๊ธฐ์„œ ์ž‘์€ ๊ฒƒ์ด๋ž€ Money์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ธ Dollar์™€ Franc์— ๋Œ€ํ•œ ์ง์ ‘ ์ฐธ์กฐ๊ฐ€ ์ ์–ด์ง„๋‹ค๋ฉด Dollar์™€ Franc์„ ์ œ๊ฑฐํ•˜๋Š”๋ฐ ๋”์šฑ ์‰ฌ์šธ ๊ฒƒ ๊ฐ™๋‹ค.

์šฐ์„  ์šฐ๋ฆฌ๋Š” Factory Method ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

Factory Method ํŒจํ„ด์„ ํ†ตํ•ด์„œ Dollar๊ฐ€ ํ˜น์€ Franc์ด ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ  Money์—์„œ ๊ฐ๊ฐ Dollar์™€ Franc๋ฅผ ๋งŒ๋“ค๋„๋ก ํ•˜๋ฉด ์•„๋งˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทธ๋ฆผ์ด ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.
TDD๋‹ต๊ฒŒ ํ…Œ์ŠคํŠธ๋ฅผ ๋จผ์ € ์ถ”๊ฐ€ ํ•ด๋ณด์ž.

void testMultiplication() {
  Dollar five = Money.dollar(5);
  assertEquals(new Dollar(10), five.times(2));
  assertEquals(new Dollar(15), five.times(3));
}

๊ทธ๋Ÿผ ๋‹น์—ฐํžˆ ์‹คํŒจํ•œ๋‹ค.
์ด์œ ๋Š” Money์— dollar๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์–ด์„œ์ด๋‹ค.
์žฌ๋น ๋ฅด๊ฒŒ Green์œผ๋กœ ๊ฐ€๋ณด์ž.

static Dollar dollar(int amount) {
  return new Dollar(amount);
}

์ด์ œ Green์ด ๋˜์—ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์€ ์ง์ ‘ ์ฐธ์กฐ๋ฅผ ์—†์• ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— five๋ผ๋Š” ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๊ฐ€ ์•„์˜ˆ Money๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ๋˜๋ฉด ์ง์ ‘ ์ฐธ์กฐ๊ฐ€ ์‚ฌ๋ผ์งˆ ๊ฒƒ ๊ฐ™๋‹ค.

void testMultiplication() {
  Money five = Money.dollar(5);
  assertEquals(new Dollar(10), five.times(2));
  assertEquals(new Dollar(15), five.times(3));
}

๊ทธ๋Ÿผ ๋‹น์—ฐํžˆ ์‹คํŒจํ•œ๋‹ค.
์™œ? Money ํด๋ž˜์Šค์—๋Š” times๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
๋ญ”๊ฐ€ ๊ธฐ์˜๋‹ค.
์šฐ๋ฆฌ๊ฐ€ ์—†์• ๊ณ  ์‹ถ์€ ๊ฒƒ์€ times ๋ฉ”์„œ๋“œ๋ฅผ ํ†ต์ผํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์—ฌ๊ธฐ์„  ์ง€๊ธˆ Money ํด๋ž˜์Šค์— times๊ฐ€ ์—†์–ด์„œ, ์ฆ‰ ํ†ต์ผ๋˜์ง€ ์•Š์•„์„œ ์˜ค๋ฅ˜๋ฅผ ๋ฟœ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์ด ๋ฌธ์ œ๋งŒ ๋„˜์–ด๊ฐ„๋‹ค๋ฉด times๋ฅผ ํ†ต์ผ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค!

์—ฌ๊ธฐ์„œ Money ํด๋ž˜์Šค๋ฅผ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋ฐ”๊พธ๊ณ  times ๋ฅผ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋กœ ๋ฐ”๊ฟ”์„œ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

abstract class Money {

  abstract Money times(int multiplier);

  protected int amount;

  static Dollar dollar(int amount) {
    return new Dollar(amount);
  }

  // ... ์ƒ๋žต
}

๊ทธ๋Ÿผ tiems ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜ค๋ฅ˜๋Š” ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ณ€๊ฒฝํ•œ ๊ฒƒ์— ์–ด์šธ๋ฆฌ๊ฒŒ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐ”๊ฟ”๋ณด์ž.

Dollar๋‚˜ Franc์„ Money๋กœ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.

public class MainTest {
  @Test
  public void testMultiplication() {
    Money five = Money.dollar(5);
    assertEquals(Money.dollar(10), five.times(2));
    assertEquals(Money.dollar(15), five.times(3));
  }

  @Test
  public void testEquality() {
    assertEquals(Money.dollar(5), Money.dollar(5));
    assertNotEquals(Money.dollar(5), Money.dollar(10));
    assertNotEquals(Money.franc(5), Money.franc(15));
  }
}
abstract class Money {
  protected int amount;

  abstract Money times(int multiplier);

  static Dollar dollar(int amount) {
      return new Dollar(amount);
  }

  static Franc franc(int amount) {
      return new Franc(amount);
  }
  // ... ์ƒ๋žต
}

๋Œ“๊ธ€