LoginSignup
1
1

More than 5 years have passed since last update.

TDD入門自分用メモ-20141121

Last updated at Posted at 2014-11-21

Part 1-8

  • 構造が似ているメソッドの...
Dollar.java

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

Franc.java

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

  • シグニチャを一致させる
Dollar.java

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

Franc.java

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

  • サブクラスへの直接参照を減らしたい
DollarFrancTest.java

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

  • Moneyにファクトリメソッドを導入し...
Money.java

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

  • Moneyを抽象クラスにしてtimesメソッドを定義する
Money.java

abstract class Money {

    protected int amount;

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

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

    abstract  Money times(int multiplier);
}

  • テストを修正する
DollarTest.java

    @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(){
        assertTrue(Money.dollar(5).equals(Money.dollar(5)));
        assertFalse(Money.dollar(5).equals(Money.dollar(6)));
        assertTrue(new Franc(5).equals(new Franc(5)));
        assertFalse(new Franc(5).equals(new Franc(6)));
        assertFalse(new Franc(5).equals(Money.dollar(5)));
    }

  • Francへの対応
FrancTest.java

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

DollarTest.java

    @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(){
        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.java

abstract class Money {

    protected int amount;

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

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

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

    abstract  Money times(int multiplier);
}

この章で行ったこと

  1. 徐々に重複を取り除いた

  2. ファクトリメソッドを導入し、サブクラスの存在をテストから分離した

Part 1-9

通貨概念の導入

DollarFrancTest.java

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

  • currency()の実装
Money.java

    abstract String currency();

Dollar.java

class Dollar extends Money {

    private String currency;

    Dollar(int amount){
        this.amount = amount;
        currency = "USD";
    }

    String currency(){
        return currency;
    }

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

Franc.java

class Franc extends Money{

    private String currency;

    Franc(int amount){
        this.amount = amount;
        currency = "CHF";
    }

    String currency(){
        return currency;
    }

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

  • サブクラス間の重複する実装をスーパークラスに移動
Money.java

    protected String currency;

    String currency(){
        return currency;
    }

Dollar.java

class Dollar extends Money {

    Dollar(int amount){
        this.amount = amount;
        currency = "USD";
    }

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

Franc.java

class Franc extends Money{

    Franc(int amount){
        this.amount = amount;
        currency = "CHF";
    }

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

  • 通貨文字列をファクトリメソッドに移動し、コンストラクタを共通化したいが...

  • コンストラクタに引数を追加すると

Franc.java

    Franc(int amount, String currency){
        this.amount = amount;
        this.currency = "CHF";
    }

  • Francをnewしているところの修正が必要
Money.java

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


  • ここはファクトリメソッド使うべきでは?
Franc.java

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

  • timesがコンストラクタを使っていることに気づいたので、ファクトリメソッドを使うよう変更する
Franc.java

    Money times(int multiplier){
        return Money.franc(amount * multiplier);
    }

  • ファクトリメソッドが文字列を渡せるようになる
Money.java

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


Franc.java

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

  • 大きな変更を細かな変更に分割し、ミスを減らす
  • Dollarに同じ変更を適用し、問題ないことを確認する
Money.java

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

Dollar.java

class Dollar extends Money {

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

    Money times(int multiplier){
        return Money.dollar(amount * multiplier);
    }
}

  • これでコンストラクタの実装が共通かできた
    ``` Money.java

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


``` Franc.java

    Franc(int amount, String currency){
        super(amount,currency);
    }

Dollar.java

    Dollar(int amount, String currency){
        super(amount,currency);
    }

この章で行ったこと

  1. コンストラクタの共通化

  2. 小さなステップでリファクタリングした

DollarTest.java

public class DollarTest {

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

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

FrancTest.java

public class FrancTest {

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

Money.java

abstract class Money {

    protected int amount;

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

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

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

    abstract  Money times(int multiplier);

    protected String currency;

    String currency(){
        return currency;
    }

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

Dollar.java

class Dollar extends Money {

    Dollar(int amount, String currency){
        super(amount,currency);
    }

    Money times(int multiplier){
        return Money.dollar(amount * multiplier);
    }
}

Franc.java

pclass Franc extends Money{

    Franc(int amount, String currency){
        super(amount,currency);
    }

    Money times(int multiplier){
        return Money.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