SHOEISHA iD

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

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

japan.internet.com翻訳記事

Apache MavenによるJavaプロジェクトポータビリティの向上

ソフトウェア開発のライフサイクル全体を通じてプロジェクトのポータビリティを維持する

  • X ポスト
  • このエントリーをはてなブックマークに追加

ポータビリティのレベル

 これらの基本ツールを押さえておけば、自分のJavaプロジェクトのポータビリティがどの程度のレベルに位置しているかを正しく判別することができます。Mavenでは、Javaポータビリティとそれに対応する問題点を次の4つのレベルで表現します。

  • ワイド(Wide)
  • インハウス(In-house)
  • 環境的(Environmental)
  • 非ポータブル(Non-portable)

ワイド(Wide)

 Mavenの世界で「ポータビリティがワイドである」と言えば、誰でもそのプロジェクトのソースをダウンロードし、修正なしでコンパイルし、POMまたは標準Maven以外の要件にインストールできるということです。これが一番高いレベルのポータビリティです。同じプロジェクトをビルドするユーザーは、余計な作業を実行する必要がほとんどありません。このレベルのポータビリティは、特にオープンソースプロジェクトで重要視されます。オープンソースプロジェクトが成功するためには、コントリビュータになる可能性を持った人が簡単にプロジェクトをダウンロードしてインストールできるようにすることが必要だからです。

 ご想像の通り、一番高いレベルのポータビリティは、手に入れることも一番困難です。ワイドなポータビリティを実現するためには、広く配布されているプロジェクトやツールであっても、ライセンスの問題が考えられるため、それに依存するわけにはいきません(この理由で、市販のソフトウェアパッケージのほとんどは利用不可になります)。また、Mavenの成果物として配布されるソフトウェアコンポーネントについても、同様の問題が考えられます。例えば、皆さんのプロジェクトでMySQLを利用している場合、ユーザーはプロジェクト本体に加えてMySQLもダウンロードしてインストールしなければなりません。これではポータビリティがワイドであるとは言えません(システムを変更せずに使用できるのはMySQLの既存ユーザーだけです)。一方、HSQLDBを使用している場合は、MavenのセントラルリポジトリからHSQLDBを入手できるので、ポータビリティはワイドとなります。

インハウス(In-house)

 ほとんどの重要なソフトウェア開発では、インハウスのポータビリティがおそらく望むことのできる最高レベルのポータビリティです。オープンソースの開発チームにしろ、クローズドソースの製作会社にしろ、ソフトウェアプロジェクトの大多数はこのレベルに位置します。このレベルのポータビリティの中心にあるのが、選ばれたユーザーのみが内部(インハウス)のリモートリポジトリにアクセスできるというプロジェクト要件です。インハウスとは、必ずしも特定の会社を意味するのものではありません。幅広く普及しているオープンソースプロジェクトの中には、特定のツールや接続アクセスを必要とするものがあるかもしれません。このような場合はインハウスに分類されます(このレベルについての詳細は、「補足説明3 インハウスポータビリティの詳細」を参照してください)。

補足説明3 インハウスポータビリティの詳細
 インハウスポータビリティのもう1つの例として、インハウスのメンバが接続できる共通データベースがあります。インハウスのプロジェクトをインハウスのネットワークの外側(例えば、企業のファイアウォールの外側)で一からビルドしようとすると、失敗します。失敗の原因としては、必要なカスタムプラグインが利用できないことや、プロジェクトの依存性が見つからないことが考えられます。従って、このプロジェクトはインハウスでのみポータブルとなります。
 インハウスポータビリティ自体には何も問題がないので、プロジェクトの形を変えて、これを避けようとしないでください。プロジェクトを複数の相互依存関係のあるパーツに分割することに意味がある場合は、分割してかまいません。Mavenのセントラルリポジトリでは入手できないバージョンを使うことに意味がある場合は、使ってかまいません。プロジェクトのPOMのrepository要素を用いて独自のパブリックリポジトリと参照依存性を作成すれば、誰もが切望する「ワイドなポータビリティ」を実現することができます。

環境的(Environmental)

 Mavenでは、コードとリソースの生成に主に関係する、環境的なポータビリティレベルのプロファイルが作成されます。例えば、本番データベースとは別のデータベースを使うテスト環境があるとします。本番データベースとテストデータベースが異なるため、テストマシンでビルドした場合は、少なくとも1つのリソースファイルを(または最悪の場合はコードも)修正しなければなりません。ファイルを変更しなければ正しくビルドして特定の環境で実行することができない場合、そのプロジェクトはよくても環境的なポータビリティしか実現していません。例えば、テスト環境内のテストデータベースへの参照と本番環境内の本番データベースへの参照を含むプロジェクトは、環境的なポータビリティを実現しています。ただしこのプロジェクトは、未定義でプロファイルも作成されていない別の環境に移動すると動作しなくなります。従って、定義された環境間でのみポータビリティがあると言えます。

 本稿のサンプルプロジェクトは環境的なポータビリティを実現しています。

非ポータブル(Non-portable)

 非ポータブルなプロジェクトは、特定の状況および条件下(例えば、ローカルマシンなど)でしかビルドできません。プロジェクトを別のマシンに移動する計画が絶対にない場合を除き、非ポータブルにすることは避けてください。非ポータブルということは、定義が1つしかない環境的ポータビリティと同じです。つまり、プロジェクトは1つの環境設定下でしかビルドできません。

 プロジェクトがどのレベルに位置するかを判断する方法については、「補足説明4 ポータビリティレベルの判断方法」を参照してください。

補足説明4 ポータビリティレベルの判断方法
 ビルドのポータビリティは、プログラミングそのものと同様、科学であると同時に芸術でもあります。どのレベルに位置するかは主に各プロジェクトの目標によって決まり、その上、「正しい」答えはまずありません。慣習と、ユーザーの期待によって決まるのです。何が妥当であるかに基づいて最善の判断を下してください。ユーザーがすべてJDK 1.6を実行していることがわかっている場合は、ユーザーに対してワイドなポータビリティを実現していると宣言しても問題ないでしょう。しかし、JDK 1.5を実行しているユーザーの方が多い場合に、ユーザーに1.6のインストールを要求することは妥当ではないので、おそらくポータビリティをインハウスレベルまで下げることになります。これは、ユーザーにまず「JDK 1.6クラブ」のメンバになるよう頼むようなものだと考えてください。
 ターゲットユーザーだけを対象とするようにビルドを調整する必要があります。プロジェクトのポータビリティの調整に悩む前に、次の質問に答えてください。
  • ワイドなポータビリティ
  • できるだけ多くの人がプロジェクトをダウンロードしてビルドできるようにしたいですか? ユーザー間で一般的に使われている最小限の構成で済ませることはできますか?
  • インハウスのポータビリティ
  • 依存コンポーネントのライセンス問題やプロジェクト構造の都合上、プロジェクトにクローズドリポジトリを設ける必要がありますか? 他の開発者はプライベートネットワークへのアクセスを心配していますか?(ネットワークがプライベートでない場合、ポータビリティはワイドになる可能性があります)
  • 環境的なポータビリティ
  • 環境の数が限定されていますか? また、各環境ではどのような特別な変更が必要ですか?(※開発/テストと本番でそれぞれ異なるデータベースを使用する場合、プロジェクトはおそらくこのレベルです)
  • 非ポータブル
  • 他にユーザーがいますか? ポータブルにする必要がありますか?
 繰り返しますが、これらの質問に対する正しい答えはありません。しかし、プロジェクトはポータビリティのレベルを落とす方が簡単であること、およびビルドのポータビリティと柔軟性は反比例することの2点を覚えておきましょう。

Mavenで一般的なポータビリティ問題を解決する

 必要なポータビリティのレベルを定義したら、次の問題はプロジェクトをそのレベルまでまたはそのレベル以上に上げることです。皆さんのプロジェクトが自己完結型で、ユーザーが修正を加えたり標準Maven以外のものをインストールしたりせずにそのプロジェクトをビルドして実行できるのであれば、もう何も言うことはありません。皆さんのプロジェクトは既にワイドなポータビリティを実現しているので、ここで読むのを止めてかまいません。しかし、重要なプロジェクトである場合は、このまま続けてお読みださい。

systemスコープを回避する

 dependency要素では、次のようなprovidedスコープとsystemスコープを回避します。

<dependency>
  <groupId>com.closedsource</groupId>
  <artifactId>sometool</artifactId>
  <version>1</version>
  <scope>system</scope>
  <systemPath>/usr/lib/sometool.jar</systemPath>
</dependency>

 systemスコープを回避できない場合は、systemPathのプロパティを使います。これで、ビルド環境ごとにそのプロパティを設定/変更することができます。ただし、一番良い手段は、dependencyをインハウスのMavenリポジトリ(以下参照)にデプロイし、そのdependencyを標準スコープとして使う方法です(前述のステートメントについての詳細は、「補足説明5 絶対値をグループ化する」を参照してください)。

補足説明5 絶対値をグループ化する
 dependencyをインハウスのMavenリポジトリにデプロイし、そのdependencyを標準スコープとして使いたい場合は、プラグイン構成で絶対パスをハードコーディングしないようにしてください。例えば、JBossプラグインでは、JBossインストールを指すようにjbossHomeディレクトリを構成する必要があります。ここで役に立つのがプロパティです。
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jboss-maven-plugin</artifactId>
        <configuration>
          <jbossHome>${jboss.home}</jbossHome>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
  <properties>
    <jboss.home>${env.JBOSS_HOME}</jboss.home>
  </properties>
</project>
 これにより、プラグイン構成全体をオーバーライドしなくても、パスをprofileのproperties要素(または*.propertiesファイル)で簡単に変更することができます。
<profiles>
  <profile>
    <id>my-jboss</id>
    <properties>
      <jboss.home>${user.home}/jboss</jboss.home>
    </properties>
  </profile>
</profiles>
 これで、すべての絶対値をproperties要素という1つの場所から変更できるようになります。

フィルタを活用する

 フィルタは積極的に使用しましょう。Mavenではフィルタを使用することで、プロパティの置き換え(ビルドライフサイクルでは*-processフェーズでマークされます)を外部化し、移動しやすく構成可能なpropertiesファイルにすることができます。次のように、ビルド内でフィルタ処理する必要がある標準Javaのpropertiesファイルのリストを追加するだけです。

<filters>
  <filter>datasource.properties</filter>
</filters>

 本稿のサンプルプロジェクトでは、「datasource.properties」ファイルは基本ビルドディレクトリ(${buildDir})内にあり、「jdbc.url」に関する「名前=値」のペアを含んでいます。

jdbc.url=jdbc:driver://localhost/myDB

 リソースをフィルタ処理する場合、プロジェクトは一致するすべてのプロパティ名を対応する値に置き換えて、フィルタリストを取り入れます。フィルタ処理対象のリソースの定義にはresourcesビルド要素を使います。例えば、次のブロックでは、プロジェクトにフィルタ処理する必要があるXMLリソースがあることと、結果を「META-INF」ディレクトリに挿入することが指定されています。

<resources>
  <resource>
    <filtering>true</filtering>
    <directory>src/main/resources</directory>
    <targetPath>META-INF</targetPath>
    <includes>
      <include>*.xml</include>
    </includes>
  </resource>
</resources>

 サンプルプロジェクトの例を実行するには、コマンドラインでprocess-resourcesフェーズを実行します。これにより、次の「datasource.xml」リソースファイルが、

<datasource>
  <jdbc-url>${jdbc.url}</jdbc-url>
</datasource>

 次のように変換されます(「target/META-INF」ディレクトリ内)。

<datasource>
  <jdbc-url>jdbc:driver://localhost/myDB</jdbc-url>
</datasource>

次のページ
プロファイルによる環境的なポータビリティ

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

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

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

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

Eric Redmond(Eric Redmond)

数百万ドルの価値(と百万行のコード)を持つJava EEプロジェクトのビルドアーキテクトだったが、現在は4人から成るチームのシニアエンジアとして活躍中。余暇には途方もない方法でJavaとRubyを組み合わせることを楽しんでいる。

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/715 2007/06/29 16:21

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング