両方のパターンを揃えたところで、DateColumnのテストコードを変更してフォーマッタの利用法を指定します。
import static org.junit.Assert.*; import java.util.*; import org.junit.*; public class DateColumnTest { private static final String NAME = "name"; private DateColumn column; ''private DateFormatter formatter;'' @Before public void initialize() { ''formatter = new MySQLDateFormatter();'' ''column = new DateColumn(NAME, formatter);'' } @Test public void create() { assertEquals(NAME, column.getName()); } @Test public void insert() { ''Date date = DateUtil.createDate(2007, Calendar.JULY, 15);'' ''assertEquals(formatter.format(date),'' ''column.insertString(date));'' } }
このテストコードをコンパイルするには、DateFormatterインターフェイスが必要です。
import java.util.*; public interface DateFormatter { String format(Date date); }
MySQLDateFormatterクラスは、このインターフェイスを実装しなければいけません。
public class MySQLDateFormatter implements DateFormatter { ...
このテストを通すためには、DateColumnクラスに2、3簡単な修正が必要です。
import java.util.*; public class DateColumn { private String name; ''private DateFormatter formatter;'' public DateColumn(String name, ''DateFormatter formatter'') { this.name = name; ''this.formatter = formatter;'' } public String insertString(Date date) { return ''formatter''.format(date); } public String getName() { return name; } }
これで完了でしょうか? いえ、まだあります。
OracleDateFormatterが利用できることを確認する必要があります。DateColumnに追加のテストコードを書くか、または、手っ取り早くテストコードを次のように変更します。
@Before public void initialize() { formatter = new ''OracleDateFormatter();'' column = new DateColumn(NAME, formatter); }
この変更に伴い、OracleDateFormatterクラスがDateFormatterインターフェイスを実装するようにします。
public class OracleDateFormatter implements DateFormatter { ...
単体テストを行い、ここまでに実装したものをすべて確認します。DateColumnを使用するクライアントコードについては、ここでは割愛しています。このクライアントコードは、フォーマッタの正確な種類をDateColumnの各インスタンスに渡す役割を果たすものです。おそらくこのロジックはFactoryの一部であり、これに対しては簡単に単体テストを記述できるでしょう。
これで、Strategyパターンに関する作業は完了です。DateColumnクラスは、クライアントから値文字列の提供を求められると、その処理を適切なDateFormatterのインスタンスに委譲します。DateColumnのコードは、処理に使用しているDBMSの種類を意識しません。DateColumnにif文は必要ありません。DateColumnクラスは、少なくとも日付の書式設定ロジックの変更という観点においては、変更に対し「閉じられて」います。
まとめ
こつこつと段階的なステップで進めてきたおかげで、クールなパターンの実装にたどり着くことができました。私がこれを「クール」だと思うのは、パターンを構成するクラスのそれぞれが小さく、理解しやすいからです。また、テストを通じて実装を進めていくことに重点を置いた結果、全体が自然に流れて、かつ大変テストしやすいものとなった点も評価できます。
繰り返しになりますが、テスト駆動型開発(TDD)を通じた単体テストは、優れたデザインに沿ったソリューションを生み出すのに大いに役立ちます。
参考資料
- 『Design Patterns: Elements of Reusable Object-Oriented Software』 Erich Gamma・Richard Helm・Ralph Johnson・John Vlissides 著、Addison-Wesley Professional、1995年、 p315.
この記事は参考になりましたか?
既に会員の方はを行ってください。
- デザインパターンの使い方連載記事一覧
- この記事の著者
-
japan.internet.com(ジャパンインターネットコム)
japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
Jeff Langr(Jeff Langr)
本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
