テスト駆動開発の第8章

Kent Beckのテスト駆動開発を日々読み進めている。

第8章に次のコードが登場した。

package money;

abstract class Money {
    protected int amount;
    abstract Money times(int multiplier);
    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);
    }
}

Moneyクラスがその子のDollarクラスやFrancクラスを生成している。

著者はこれでテストコードから2つの子クラスの存在が消えて良くなったと主張している。なるほどと思ったが、まもなく違和感がやってきた。やがてこの違和感はオープン・クローズドの原則に反していることによるものだと気がついた。

この設計だと、お金の単位を追加するという拡張を行うときに既存のコードを修正しないといけない。オープン・クローズドの原則に従うと、この設計は良くないと言える。

著者の設計方針やその合理性はわかる。オブジェクトを生成する責務をどこかに持たせる必要が出てきて、それを最小限の労力で済ませるために生成用クラスを新設するのではなく親クラスに責務を持たせることにしたのだろう。オブジェクトは数種類だからそれで十分だ。もし生成するオブジェクトが何十種類もあるなら、オブジェクト生成担当のクラスを設ける必要があるだろう。

おたより

おたよりはまだありません。