SHOEISHA iD

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

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

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

japan.internet.com翻訳記事

Jakarta Commonsを使ってJDKクラスを拡張する:パート1

Commons Validator/Collections/Chain/Functors/Langの利用

Functors

 Functors APIの目的は、手続き型プログラム要素をオブジェクトとしてモデル化することです。たとえば、何かの条件に関してVector内またはArrayList内のオブジェクトを評価し、その結果に基づいてアクションをとるようなコードを書いたことはないですか? あるいは、if-elseif-elseif-else文やswitch-case文を書いた経験は? Functorsを使用すると、if-elseswitch-caseのような条件とこれらの条件の中の式を、独立したオブジェクトとしてモデル化することができます。では、なぜそうする必要があるのでしょうか。この手法には次のような利点があります。

  • モジュール型設計になるため、機能の拡張や修正が容易になります。StrategyパターンとCommandパターンを一緒に使って、操作の中のアルゴリズムを条件によって切り替えることができます。
  • 単体テストケースを書くことが容易になります。
  • リフレクションを使って、条件に応じた操作を動的にロードすることができます。

 技術的に見ると、ifwhileforswitchといったプログラム要素の多くはFunctorsを使ってモデル化することができます。この考え方は、連続的なif-else文、switch-case文、およびコレクションに対する操作でよく使われます。

 このAPIに含まれる重要なインターフェイスはPredicateClosureです。Predicateは条件を表現するのに使います。結果がtrueなら、Closureexecuteメソッドが呼び出されます。

 本稿で紹介するFunctorsサンプルは、データベースコマンドを処理する単純なスクリプト処理エンジンです。このサンプルでは、スクリプトコマンドに対してどのコマンドクラスを呼び出すかを定義したswitch-caseディシジョンツリーをFunctorsでモデル化しています。完全なコードは「in.co.narayanan.commons.collections.functors」パッケージに収められています。使用するデータベースコマンドの構文は次のとおりです。

add <tablename>, <column values>
delete <tablename>, <key_column>, <value>
modify <tablename>, <key_column>, <value>, <column name and new values>

 このスクリプトエンジンは、addスクリプトコマンドが呼び出されたときに、データベースに対してSQLのINSERT文を実行する必要があります。他のコマンドも同様に処理する必要があります。ScriptCommandクラスはドメインオブジェクトであり、スクリプトコマンドとその引数を表現します。AddTaskDeleteTaskModifyTaskの各クラスには、スクリプトコマンドのために実行するロジックが含まれています。このエンジンをモデル化するための従来の方法を理解するため、ProcessCommand1クラスから抜粋した次のコードをよく見てください。

public void process(ScriptCommand command) {
   switch(command.getType()) {
      case ADD: {
         executeAdd(command);
      } break;

      case MODIFY: {
         executeModify(command);
      } break;

      case DELETE: {
         executeDelete(command);
      } break;
   }
}

 ここでは、switch-caseブロック内でスクリプトコマンドの種類をチェックし、該当するコマンドを実行しています。

 次のリストはProcessCommand2クラスからのもので、Functorsを使って同じ動作を実現できることを示しています。

public void start() {
   Map predicatesAndClosures = new Flat3Map();
   predicatesAndClosures.put(new AddPredicate(), new AddClosure());
   predicatesAndClosures.put(
      new ModifyPredicate(), new ModifyClosure());
   predicatesAndClosures.put(
      new DeletePredicate(), new DeleteClosure());

   Closure switchClosure =
      ClosureUtils.switchClosure(predicatesAndClosures);
   CollectionUtils.forAllDo(commands, switchClosure);
}

private static class AddPredicate implements Predicate {
   public boolean evaluate(Object object) {
      ScriptCommand command = (ScriptCommand)object;
      return command.getType() == CommandType.ADD ? true : false;
   }
}

private static class AddClosure implements Closure {
   public void execute(Object input) {
      ScriptCommand command = (ScriptCommand)input;
      AddTask add = new AddTask();
      add.add(command.getTableName(), command.getArgs());
   }
}

 AddPredicateはコマンドタイプを評価します。AddClosureにはaddスクリプトコマンドを実行するロジックが含まれています。プレディケイトとクロージャはマップされて、ClosureUtilsユーティリティクラス内のswitchClosureメソッドに渡されます。結果がtrueの場合、返されたSwitchClosure参照は、クロージャにマップされたプレディケイトと呼び出しを評価します。trueが返されるまで、マップ内の各プレディケイトについて、これが繰り返されます。

 このサンプルは、クロージャを併用してプログラムフローを実現する方法を示しています。ここでは、上記のAddClosureとCommons Collections API内のSwitchClosureを一緒に使用しています。たとえば、SwitchClosure参照をIfClosureと使用することができます。

 ビジネスアプリケーションでのFunctorsの一般的な用途は、一群のビジネスルールをドメインオブジェクトインスタンスのコレクションに適用し、ルール結果に関連してアクションをとることです。ルールはプレディケイトとしてモデル化し、アクションはクロージャとしてモデル化する必要があります。Jythonに統合したPythonスクリプティング言語を使用すれば、完全なルールエンジンを構築することができます。その場合、プレディケイトとクロージャを書くためにPythonスクリプトを使用する必要があります。

次のページ
Lang

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

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

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

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

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

Narayanan A.R.(Narayanan A.R.)

テスト駆動開発、アジャイル方法論、Javaテクノロジ、およびデザインパターンの熱烈な擁護者。Javaテクノロジを使ったソフトウェアのデザインおよび開発に携わって数年になる。

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/283 2006/04/11 19:09

イベント

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

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

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

メールバックナンバー