TDD入門自分用メモ-20141123


# Part 1-10

* timesの実装を以下のように変更できれば共通かできる(サブクラスへの参照を減らせる)

``` Franc.java

  Money times(int multiplier){
    return new Money(amount * multiplier, currency);
  }

```
* test
 
``` DollarFrancTest.java

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

```

* テストは失敗するのでequalsのコードを修正する
* クラスの比較でなく通貨の比較をすべき

``` Money.java

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

```

* timesの実装を変えてみて動作するか確認する

``` Franc.java

  Money times(int multiplier){
    return new Money(amount * multiplier, currency);
  }

```

* Dollarも同じように動作することを確認し、スーパークラスに実装を移動する


# Part 1-11

* サブクラスに残っているのはコンストラクタだけとなった
* サブクラスを参照しているのはファクトリメソッドのみ

``` Money.java

  static Money dollar(int amount){
    return new Dollar(amount, "USD");
  }

  static Money franc(int amount){
    return new Franc(amount, "CHF");
  }


```

* Moneyに変える

``` Money.java

  static Money dollar(int amount){
    return new Money(amount, "USD");
  }

  static Money franc(int amount){
    return new Money(amount, "CHF");
  }


```

* 他のテストで網羅できるか、テストコードを見直す

``` DollarFrancTest.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 testFrancMultiplication() {
  Money five = Money.franc(5);
  assertEquals(Money.franc(10), five.times(2));
  assertEquals(Money.franc(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.dollar(5).equals(Money.franc(5)));
}

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

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

```

* 残りは先ほど追加したテストDifferentClassEquality...はFrancクラスが存在するときに必要だったものなので削除できる
* timesのテストはロジックが共通化され、違いがないのでtestFrancMultiplicationも削除できる
* 等価性のテストも重複分を削除

## この章で行ったこと

1. サブクラスの内容を空にして削除した

1. 古いコードで必要だったが、新しいコードでは冗長・不要なテストを削除した


``` DollarFrancTest.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)));
  assertFalse(Money.dollar(5).equals(Money.franc(5)));
}

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

```

``` Money.java

abstract class Money {

  Money(int amount, String currency){
    this.amount = amount;
    this.currency = currency;
  }

  protected int amount;

  protected String currency;

  String currency(){
    return currency; 
  }

  static Money dollar(int amount){
    return new Money(amount, "USD");
  }

  static Money franc(int amount){
    return new Money(amount, "CHF");
  }

  Money times(int multiplier){
    return new Money(amount * multiplier, currency);
  }

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

}

```

``` Dollar.java

-- 削除

```
``` Franc.java

-- 削除

```