LoginSignup
1
1

More than 5 years have passed since last update.

TDD入門自分用メモ-20141120

Last updated at Posted at 2014-11-19

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. バリエーションに対してコピペした

  2. コピペはリファクタリングする前提で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. 共通コードをスーパークラスへ移動

  2. 冗長な実装を削除する前に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. おかしな状態をテストに変換した

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

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


1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1