SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine(コードジン) DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンの使い方

デザインパターンの使い方: Strategy

Strategyパターンを利用したSQLジェネレータの作成

 次のイテレーションで、依頼主から、このアプリケーションで今度はOracleをサポートしなければならないと指示されたとします。

 残念ながら、この2つの異なるデータベースシステムには、日付について別々の書式が必要です。互換性とはまた厄介な問題です。私ははるか昔、「現実の」プロジェクトにおいて、実際に似たようなことをしなければならなかった経験があります。そのときは、2つの別々の環境に導入を行う必要がありました。

 心配はいりません。単体テストを使用して、ソリューションの構築と問題回避に役立てていきましょう。ただし、まずは問題に対する最良の解法を調査し、手短に検討することにします。

 Oracleでは日付の書式に少なくとも2つの方式があり、いずれもMySQLのものとは異なります。簡単にWebで検索したところ、Oracle SQLで日付を与える方法の1つは、デフォルトの形式である「DD-MON-YY」を前提にすることです。たとえば、挿入文字列は「30-may-2007」となります。

 もう1つの方法は、日付文字列の書式を指定するTO_DATE関数を提供することです。

TO_DATE('2007-07-15', 'yyyy/mm/dd')

 私はこちらの方が好みです。この方法であれば、「07-may-06」が2007年5月6日なのか2006年5月7日なのか、混乱せずにすみます。

 考えられる解決策としては、insertString内にif文を組み込むという方法があります。たぶんこのやり方では、コードの他の多くの箇所、おそらくselect文字列の生成用途でif文が必要となるでしょう。これはあまり良くありません。if文を無節操に使ったコードは、すぐに手に負えなくなります。

 それよりも、DBMSの種類を特定するための場所を1つ用意した方がよいでしょう。その場所で、さらにDBMS個別のオブジェクトを用意し、それぞれの書式に沿った日付文字列を生成させるようにすることもできます。

 ここで私は、変更された振る舞いを扱うためにDateColumnを変更することに少し不安を感じます。この例に関して言うと、Strategyデザインパターンの全体の考え方は、DBMS個別のフォーマッタオブジェクトをDateColumnオブジェクトに渡すというものです。このフォーマッタオブジェクトのクラスには、目的に合った振る舞いが含まれます。

 実装の観点から、単一のformatメソッドを宣言するDateFormatterインターフェイスを作りたいと思います。さらに、このインターフェイスを実装するMySQLDateFormatterOracleDateFormatterを作成します。その後、DateFormatterの参照を維持するためにDateColumnクラスを変更することにします。

 これでだいたいの道筋はつきました。目標地点まで少しずつ進んでいくことにします。最初に取り組むのは、MySQLDateFormatterに委譲するためにDateColumnを変更することです。次のように変更します。

// DateColumn.java
...
public class DateColumn {
   ...
   public String insertString(Date date) {
      return new MySQLDateFormatter().format(date);
   }
}

// MySQLDateFormatter.java
import java.util.*;
public class MySQLDateFormatter {
   public String format(Date date) {
      return String.format("'%1$tY-%1$tm-%1$td'", date);
   }
}

 その後、テストを実行します。また、DateColumnのテストコードをコピーして修正することで、新規クラス用のテストを新たに作成します。

 何はともあれ、新規クラスを作成する際にテストクラスを追加するのは、よい考え方です。これらの新たなテストクラスは、全部のクラスを単体テストで確認し実証する必要があることを他の開発者に対して穏便に示す、リマインダとしての働きをします。

import static org.junit.Assert.assertEquals;
import java.util.*;
import org.junit.*;

public class MySQLDateFormatterTest {
   @Test
   public void insert() {
      MySQLDateFormatter formatter = new MySQLDateFormatter();
      assertEquals("'2007-07-15'",
            formatter.format(DateUtil.createDate(2007,
            Calendar.JULY, 15)));
   }
}

 それから、Oracleに対応する部分を作成します。

// OracleDateFormatterTest.java:
import static org.junit.Assert.assertEquals;
import java.util.*;
import org.junit.*;

public class OracleDateFormatterTest {
   @Test
   public void insert() {
      OracleDateFormatter formatter = new OracleDateFormatter();
      assertEquals("TO_DATE('2007/07/15', 'yyyy/mm/dd')",
            formatter.format(DateUtil.createDate(2007,
            Calendar.JULY, 15)));
   }
}

// OracleDateFormatter.java:
import java.util.*;

public class OracleDateFormatter {
   public String format(Date date) {
      return String.format("TO_DATE('%1$tY/%1$tm/%1$td',
         'yyyy/mm/dd')", date);
   }
}

次のページ
まとめ

この記事は参考になりましたか?

デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.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件以上執筆しており、そのうちの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2914 2008/09/10 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー