TDD入門自分用メモ-20141120


# Part 1-5

## フラン(CHF)も扱えるようにする

``` TODOList.md
レートが2:1の場合、$5+10CHF=$10
Moneyの丸め処理
hashCode()
nullとの等価性
オブジェクトとの等価性
5CHF * 2 = 10CHF
```

* 新しいテスト

``` FrancTest.java

public class FrancTest {

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

```

* リファクタリングする前提でコピペ実装

``` Franc.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;
    }
}


```

* コピペした罪悪感を持ちつつ、コピペによってあらたに発生したタスクTODOListに加えておく

``` TODOList.md
レートが2:1の場合、$5+10CHF=$10
Moneyの丸め処理
hashCode()
nullとの等価性
オブジェクトとの等価性
DollarとFrancの重複
equalsの一般化
timesの一般化
```

*コピペはよくある話なのでこれをどう改善していくか*

## この章で行ったこと

1. バリエーションに対してコピペした

1. コピペはリファクタリングする前提でTODOList書いた

# Part 1-6

## 共通化に向けて

* DollarとFrancに共通なスーパークラスを作成していく

``` Money.java

class Money {
}

```

``` Dollar.java

class Dollar extends Money {

  private int amount;

}

```
* 次にインスタンス変数を移動する

``` Money.java

class Money {
    
    protected int amount;
    
}

```

``` Dollar.java

class Dollar extends Money {

}

```

* ここまで、テストは失敗しないことを確認する

* equalsの修正にとりかかる

``` Dollar.java

    public boolean equals(Object object){
        Money dollar = (Money)object;
        return amount == dollar.amount;
    }

```

* equalsをMoneyに移植できるようになる

``` Money.java

class Money {

    protected int amount;

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

```

* Francのequalsを削除したいが、等価性のテストを行っていない
* ここでFrancのequalsに対するテストを追加しておく

``` DollarFrancTest.java

    @Test
    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)));
    }

```

* FrancにもDollarと同じ修正を行い、equals実装をMoneyにまとめる

## この章で行ったこと

1. 共通コードをスーパークラスへ移動

1. 冗長な実装を削除する前にequals実装を一致させた

# Part 1-7

## 共通化の結果...

* DollarとFrancが同様に扱われてしまう...

``` DollarFrancTest.java

    @Test
    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)));// 失敗する
    }

```

* とりあえずクラスの比較結果を追加する

``` Money.java

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

```

## この章で行ったこと

1. おかしな状態をテストに変換した

1. テストを動作させるようにした


``` DollarTest.java

public class DollarTest {

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

    @Test
    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)));
    }
}

```
``` FrancTest.java

public class FrancTest {

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

```

``` Money.java

class Money {

    protected int amount;

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

```

``` Dollar.java

class Dollar extends Money {

    Dollar(int amount){
        this.amount = amount;
    }

    Dollar times(int multiplier){
        return new Dollar(amount * multiplier);
    }
}


```
``` Franc.java

class Franc extends Money{

    Franc(int amount){
        this.amount = amount;
    }

    Franc times(int multiplier){
        return new Franc(amount * multiplier);
    }
}


```