Project Zero開発プラットフォームには使いやすいデータ・アクセス・ライブラリーが組み込まれているため、開発者は最小限の構成作業を行うだけで自分たちのアプリケーション・コードからSQL文を実行できます。実際、データベースをセットアップして接続するのに必要なのは、たった4行の構成ファイルと基本的なSQLの知識だけです。そのどちらも、平均的なWeb開発者の負担になるはずがありません。しかし、これほど単純なデータベース駆動型の開発でも、データベース駆動型コンポーネントのパッケージ化に関しては十分に考慮しなければならない懸念事項がいくつかあります。設計が適切でないとZeroコンポーネントが依存関係を引きずるため、他の開発者たちが容認できない前提を生み出してしまうからです。この記事では、データベース駆動型コンポーネントを他のZero開発者たちが簡単に再利用できるように構成およびパッケージ化するためのベスト・プラクティスを説明します。
始める前に
この記事では、読者がProject Zeroをダウンロード済みであること、そして初心者向けチュートリアル「Developing applications with Project Zero」の手順を完了しているか、または単純なアプリケーションを自分自身で作成した経験があることを前提とします。Zeroのデータ・アクセス・ライブラリー(zero.dataと呼ばれます)およびApache Antについて十分理解していることも必須です。また、開発には以下のデータベース製品のいずれかを使用していなければなりません。
詳細は、「参考文献」を参照してください。
はじめに
Zeroコンポーネントを実動システム用にパッケージ化する際に最大の懸念事項となるのは、データベース構成です。設計が適切でないと、Zeroコンポーネントが依存関係を引きずって他の開発者たちが容認できない前提を設定してしまいます。すべてのコンテンツを抽出して構成ファイルとスクリプトを操作しなければZeroコンポーネントを使用できないとしたら、幅広い再利用は望めません。また、コードの変更がライセンスで許可されているとしても、サードパーティーのコードを変更する責任を敢えて負いたいという開発者はほとんどいないはずです。以降のセクションでは、Zeroコンポーネントの構成ファイル、ライブラリー依存関係、テーブルの作成について検討します。この3つを最適化することで、コンシューマーが簡単に使える、データベースに依存しないZeroコンポーネントを実現できます。
構成ファイルの最適化
Zero構成ファイルは、ドライバー名、データベース・ロケーション、認証情報など、コンポーネントのデータベース接続に関する詳細を指定する場所です。このファイルは、/config/zero.config 配下のアプリケーション・ディレクトリーにあります。リスト1に、Apache Derbyデータベースを使用するブログ・コンポーネントのサンプル zero.config ファイルを記載します。
[/app/db/blog/config] class=org.apache.derby.jdbc.ClientDataSource serverName=localhost portNumber=1527 databaseName=BlogDB
このようなコンポーネントの実装コードは、zero.data のManager.create()
メソッドを呼び出し、データベース構成の名前(例えば、Manager.create("blog")
)を渡してデータベースにアクセスします。
リスト 1のファイルは初期段階の開発とテストには問題ありませんが、実のところ、この実装にはデータベース名とデータベース製品がハードコーディングされています。そのため、このコンポーネントを他の誰かがアプリケーションで再利用するには、既存のデータベースを再利用するのではなく、新しいデータベース・インスタンス("blog"
)を作成せざるを得えません。さらに、選択されているデータベース製品をまだ使用していないとしたら、そのデータベース製品をインストールしてデプロイする必要もあります。たいていの実動環境では、どちらの要件も上手くいく見込みはありません。デプロイヤーがすべてのZeroコンポーネントにそれぞれ固有のデータベースを設定する余裕があることも、たった1つのコンポーネントのためだけに別の製品システムをインストールして管理することもあり得ないからです。要するに、コンシューマーのデータベース環境に適用できるだけの柔軟性を備えた構成にしなければ、コードが再利用されることはないということです。そこで、このセクションでは上記の zero.config ファイルをもっと融通の利くものに変更します。
ハードコーディングされたデータベース名を削除する
柔軟性を実現するための最初の、しかも最も簡単なステップは、ハードコーディングされたデータベース名をデータベース関連のコードから削除することです。リスト 2のスタンザは、ブログ・コンポーネントのdbKeyプロパティーの値を設定しています。この値は、実行時にZeroのGlobalContext APIを使って読み取ることができます。
[/app/blog] dbKey=blog
このプロパティーを設定すれば、Manager.create("blog")
の代わりにManager.create(app.blog.dbKey)
を使用するようにコードを変更できます。データベース名を外部化することで、コンシューマーがコードの隅から隅まで調べなくても簡単にデータベース名を変更できるようになります。
コードの改善はこれで終わったわけではありません。dbKey
プロパティーの値はデータベースの名前にすることも、defaultDBにすることもできます。後者は特殊な値で、zero.dataライブラリーに対して、このライブラリー自体が含まれるアプリケーションのデータベース構成を使用するよう指示します。これこそが、目的とするところです。つまり、他のZero開発者が独自のアプリケーションにブログ・コンポーネントを追加する際にdbKey
の値をdefaultDBに設定すれば、そのアプリケーションの zero.config ファイル内でdbKey
の値を再定義できるというわけです(リスト 3を参照)。
[/app/blog] dbKey=defaultDB
これでバランスは完璧です。コンポーネントは開発とテストの段階ではblogデータベースを使用する一方、デプロイメントの段階ではコンシューマーが zero.config ファイル内でこのデータベース名をオーバーライドして固有のデータベース設定と一致させることができます。
動的データベース構成
データベース名は動的になりましたが、ブログ・コンポーネントの zero.config ファイルにはまだ、元のデータベース設定に固有の情報が残っています。リスト 1にはApache Derbyに極めて限定された設定が含まれていますが、このブログ・コンポーネントはIBM DB2やMySQLで問題もなく動作するようなので、何もその正常な動作を犠牲にする必要はありません。
データベース構成を動的にするための最初のステップは、zero.config ファイルからこの構成を抜き出すことです。リスト 1のテキストを data.config という別のファイルに挿入し、リスト 4の構文を使って、このファイルを元の zero.config ファイルに組み込みます。
[@include data.config]
スタンドアロンのアプリケーションとして使用することのない小さなコンポーネントについては、ここで手順を終わりにできます。必要なデータベース構成はコンシューマーのアプリケーションによって提供されるという前提で、このコンポーネントを再配布用にパッケージ化する前に@include行をコメント・アウトすれば完了です。
ただし、複雑なアプリケーションのビルディング・ブロックとして役立つと同時に、それ自体が完全なアプリケーションとして機能するようなコンポーネントも数多くあります。このブログ・コンポーネントがまさにその例で、ブログ作成だけの処理をするWebサイト(blogger.comなど)が数多くある一方で、ブログ作成はユーザー・エクスペリエンスの一部でしかないというWebサイト(MySpaceなど)も数多く存在します。このようなコンポーネントは、コンシューマーがスタンドアロンのアプリケーションとして使用する場合、コンポーネント自体のデータベース構成を動的に設定する機能を備えていなければなりません。これにぴったりのシナリオは、コンシューマーがZeroコマンドライン・インターフェースを使ってコンポーネントのインストール・プロセスを開始すると、その一環としてコンポーネントが自動的にデータベース要件を構成するという場合です。
データベース情報はすでに別のファイルにあるので、動的データベース構成を追加するのは簡単です。それぞれのZeroコンポーネントにはZeroコマンドライン・インターフェースを呼び出すために使用するApache Antファイル(build.xml)があるので、このファイルを使ってカスタム・ビルドとデプロイメント・ロジックを追加することができます。次のステップは、コンシューマーのデータベース用に適切な data.config ファイルを生成することが可能なAntターゲットを追加することです。このブログ・コンポーネントの build.xml ファイルには、リスト 5のAntターゲットを追加することができます。
<property name="config-file" value="config/data.config"/> <target name="create-derby"> <echo file="${config-file}"> [/app/db/blog/config] class=org.apache.derby.jdbc.ClientDataSource serverName=localhost portNumber=1527 databaseName=BlogDB </echo> </target> <target name="create-mysql"> <echo file="${config-file}"> [/app/db/blog/config] class=com.mysql.jdbc.jdbc2.optional.MysqlDataSource serverName=localhost portNumber=3306 databaseName=BlogDB </echo> </target> <target name="create-db2"> <echo file="${config-file}"> [/app/db/blog/config] class=com.ibm.db2.jcc.DB2DataSource serverName=localhost portNumber=50000 databaseName=BlogDB </echo> </target>
リスト 5では、サポート対象の3つのデータベースそれぞれに1つのターゲットを追加しています。各ターゲットは、ベンダー固有の設定を使って data.config ファイルを作成します。このブログ・コンポーネントをダウンロードしたコンシューマーがApache Derbyでサポートされるスタンドアロン・アプリケーションとしてコンポーネントを実行する場合は、リスト 6のコマンドを実行することになります。
$ zero resolve $ zero create-derby $ zero run
DB2およびMySQLのユーザーは、create-derbyをそれぞれのターゲットに置き換えてください。
このように、データベース構成をできる限り柔軟にして潜在するコンシューマーのニーズに満たすことができるようにしました。次は、不要な依存関係という問題に目を向けます。