2012年7月10日火曜日

その設計は適切ですか?

大分、咳が収まりつつあります。

みけです。

今週はネガティブになってしまう週(二週間を周期とする気分の波があります)なので、

ネガティブなことをいろいろと書き殴りたい気分ではあるんですが、

思ったことを少しだけ書きます。


共通化関数


まあ、ツイッターで結構出回っているので、

皆さんすでに読まれているかと思います。

日々常々 - 誤った共通化

あのKBNという変数名、嫌ですね。

なんとかならないかと思います。


まあ、そんなことを言っている当の私も数年前はKBNであったし、

エクセル方眼氏をこよなく愛していたわけですが…

指摘されているような過ちを平気でやっていたのですが…


最近だと同じような状況だと、

次のような設計・実装にすることが多いです。


public class Printer {
    private java.io.Writer writer;

    public void setWriter (java.io.Writer writer) {
        this.writer = writer;
    }

    public void writetGreeting (Language language) {
        writer.write (language.getGreeting());
    }
}

public interface Language {
    public String getGreeting();
}

public enum AncientLanguages implements Language {
    LATIN {
        @Override public String getGreeting () { return "Lorem"; }
    },
    GREEK {
        @Override public String getGreeting () { return "Γεια σας"; }
    }

    @Override public String getGreeting();
}

public class LanguageService {
    public void writeGreeting (Writer writer, String language) throws IllegalArgumentException {
        Printer printer = new Printer();
        printer.setWriter(writer);

        Language lang = AncientLanguages.valueOf (AncientLanguages.class, language);
        printer.writeGreeting (lang);
    }
}

enumを一つの状態を表すので、それに何かをさせるのがあるべき姿かと

考えています。なので、enumにメソッドを実装させることが多いです。



設計の適切度の指針としてテストを利用する


上記の例で言えば、比較的テストは簡単に書けます。

public class PrinterTest {
    @Test public void testGreeting {
        StringWriter writer = new StringWriter ("test-");

        Printer printer = new Printer ();
        printer.setWriter(writer);

        Language language = new MockLanguage ();
        printer.writeGreeting(language);

        assertThat(writer.toString(), is("test-hoge");
    }

    private class MockLanguage implements Language {
        @Override public String getGreeting () { return "hoge"; }
    }
}

こんな感じで、モッククラスを二つ準備するだけで、テストが書けます。
  • WriterStringWriter
  • LanguageMockLanguage


しかし、このPrinterクラスが依存するクラスが多かった場合、どうなるでしょうか?

おそらくテストコードは読みづらいものになっていたと思います。

例えば、こんな感じ。




モックするクラスが多いクラスというのは、

一つのクラスでいろんなことをやろうとしているクラスです。

つまり、責務分割がしっかりなされていない設計になっているといえます。


クラスに保持するフィールドは三つ以下にする


これは『プロダクティブプログラマー』に書いてあった

内容です。(間違えているかもしれません)


もし、フィールドがそれ以上増えるようでしたら、

そのクラスの責務が多すぎるようなので、

再設計を検討して下さい。


以下、参考書籍。





読んだことありませんし、持っていませんが…


読みづらいテストコードの元例の書いてあった本。
ちなみにモックの数が多い場合は、責務が大きくなっているので再分割することを検討して下さいとも書いてあった…

0 件のコメント:

コメントを投稿