Apache Ant タスク設計ガイドライン

このドキュメントでは、Ant のディストリビューションに入れるのに必要な基準に従ったAnt タスクの作成法について述べています。 このドキュメントが取り組んでいる問題が今なおあるので、 このドキュメントは個人利用のためにタスクを作成する際に役立つでしょう。

既存のビルドを壊さない

Ant において本当に恐ろしい問題を発見し、それが簡単に修正できるものであったとしても、 あなたの修正が既存のビルドファイルを動作させなくするならば、 我々は困ったことになります。 今ある全てのビルドファイルが動作することを確認することは、 全ての変更の目的の一つです。 このような例として、 Ant 1.5 では、文字列中の一つのドル記号 "$" を読み飛ばします。 Ant 1.4 以前では、それを削除します。 これを修正するために、 まず最初に現在の振舞いを明らかにするために、 テストセットを書かなければなりませんでした。 そして、下位互換性のために一つの $ は読み飛ばし、 二つの "$$" は "$" にマップするように変更しました。

組み込みのヘルパークラスの利用

Ant には、 作業の多くを簡単にするためのヘルパータスクがあります。 これらのヘルパークラスは Ant 1.x 版と Ant 2.0 版のとではとても違いがあるように見えるという注意があります。 しかしながら、開発、保守、およびコードサイズの理由から、 自分で書くよりもそれらを使ったほうが良いでしょう。

Execute

(外部プログラムの)実行では、 Java のバージョンおよびプラットフォームの問題を扱いながら、 Ant がサポートする全てのプラットフォーム上で別のプログラムを生成します。 他のプログラムを起動するためには、常にこのタスクを使います。

Java、 ExecuteJava

これらのクラスは、(実行するのに使う)別の VM 、あるいは、 同じ VM で、 異なるクラスローダーを使ったり、使わなかったりして、 Java プログラムを起動するのに使います。 これからタスクが派生する際に、 ユーザが指定されるクラスパスを許可したり、 オプションの属性であるように起動するために利点があります。

Project および関連するクラス

Project、FileUtils、JavaEnvUtils は全て ファイルにタッチしたりするようなことを行うためにヘルパー関数を持っています。 自分でコーディングしようとしたり、 あまり安定せず、ごまかされたタスクを使おうとせずに、 これらを使ってください。

Sun/Java スタイルガイドラインに従う

Ant のコードベースは一つの統一されたコーディング標準に従うことを目指して いて,その標準は Sun Java コーディングガイドライン です。

他の全ての選択肢よりもそれが良いとはいえませんが、 それは標準であり、それが、他の残りのタスクで一貫的に使われているのです。 これらを満足するまで、コードはデータベースに組み込まれません。

もし、あなたが、個人や組織で利用するためにタスクを書いている場合、 何でも自分の好きな方法を使って構いません。 しかし、Sun Java のスタイルに従えば、 Ant のソースの残りにおいて、あなたを快適にする手助けになるでしょう。 それが、重要なことなのです。

一つの重要な規則は 'タブを使わない' という事です。 代わりに 4 つの空白文字を使ってください。 2 つでも、8 つでもなく 4 つです。 たとえ、自分のエディタが4文字分のタブに設定されていても、 多くの人がそうしていなくてもです。 スペースは、エディタやプラットホームの間でより一貫性があります。 いくつかのIDE(JEditなど)では、タブをハイライトしてくれ、 意図せずにタブを挿入することを防いでくれます。

メインのディレクトリにあるcheck.xmlというantビルドファイルがあり、 これは、antのソースコードに checkstyle を実行します。

属性および要素

全ての属性を setFoo(String) のように実装したり、 自分で整数、ブール値、ファイルなどにマッピングせずに、 Ant のイントロスペクションに基づく属性の Java データ型へのマッピングを使います。 これにより、自分の作業量を減らすことができ、 Java の呼び出し側に対し、安全なデータ型の方法で使わせるようにし、 Xdocs ドキュメント生成において、パラメータが何であるかわかるようになります。

Ant 1.x タスクは、 属性名において、あまり一貫性がありません。- 一部のタスクはsourceを使い、また一部は srcを使っています。 次に推奨される属性名の一覧を示します。
failonerror 実行が失敗したらBuildException例外を発生しなければならないか、 それとも単にエラーを表示すればよいか制御するブール値。 パラメータ確認の失敗は、このフラグにかかわらず常にエラーをスローします。
destdir 出力先ディレクトリ
destfile 出力先ファイル
srcdir ソースディレクトリ
srcfile ソースファイル
もちろん、これは大変短いリストです。 少なくとも、コアタスクと一貫性があるよう心がけて、そして、 大体一貫性があるようにしてください。

クラスパスの対応

外部ライブラリが必要な場合、 ANT_HOME\lib ディレクトリに全てを加えさせるより、むしろ、 あなたのタスクに対し利用者がクラスパスを指定できるよう心がけ、 そうなるようにしてください。 これにより、全てのユーザに Ant のシステム設定を変更させずに、 自分の Ant ベースのプロジェクト中に外部ライブラリを置くことができるようになります。

制御された再利用のための設計

メンバ変数をプライベートにしておきます。 サブクラスによる読み取りアクセスが必要な場合は、 メンバのアクセス設定を変更せずに、アクセッサーメソッドを追加してください。 これにより実際の実装から切り離したまま、 サブクラスが内容にアクセスできるようになります。

Ant における他の共通の再利用の機構は、 一つのタスクに対して、作成し、他を設定するということです。

タスク内での依存関係チェックの実行

make には、 統合された依存関係チェックにおいて Ant よりも利点があります: make が起動するコマンドラインアプリケーションは自分で依存関係を処理する必 要はありません. Ant タスクは自分自身で依存関係チェックを行わなければなりません。 しかし、これができたら、うまくいくのです。 優れた依存関係認識タスクは、 ビルドファイル中の明示的な依存関係情報がなくても、 依存関係を解釈することができ、 ちょっとのファイルのパージングにより、 実際の依存関係を調べるのに十分なほど洗練されたものです。 depends タスクはこれに対する最高の例です。 一部の zip/jar タスクも、 必要な場合にアーカイブを更新できるので、かなり良い(例)です。 ほとんどのタスクは、 単にソースおよび出力先のタイムスタンプを比較し、 そこから作業します。 いかなる依存関係チェックも行わないタスクは、 ユーザのためにはなりません。 何故なら、その必要としない作業は、 全体のビルド、テスト、および配備手順から少しずつ漏れることがあるからです。

Java 1.2 から Java 1.4 をサポートする

Ant1.5以前は Java1.1をサポートするように設計されていました。 Ant1.6以降は、Java1.2をサポートするように設計されています。 そのJavaの上でビルド、実行できます。 時として、ある状況によりタスクの機能を縮小しなければならないことがあります。 これは通常、ライブラリの制限によるものです; そのような振る舞いの変更は、常にドキュメントに記されていなければなりません。

問題となるのは、Java 1.3 の機能である java.lang.reflect.Proxy や Java1.4の機能である 例えば、java.io.nioなどに依存したコードです。 それだけではなく、 StringBuffer#append(StringBuffer)のような、 古いクラスの追加メソッドにも注意してください。 これらのコードは直接利用すべきでなく、どんなコードもJava1.2システム上で コンパイル、実行できなければなりません。 もし既存のクラスの新しいメソッドを使う場合には、 リフレクションを通して使われなければならず、 どうにかしてNoSuchMethodExceptionを扱わなければなりません。

コードが単に Java 1.2 で動作しない場合はどうなるでしょうか。 これは、起こり得ることです。 build.xml の変更により、コンパイルを Java 1.3 以降に制限することにより、 そのタスクをオプションタスクとして持てば大丈夫でしょう。 それでもなお、 実行時にクラスへのリンクのためにリフレクションを使った方が良いでしょう。

Java 1.4 では、言語自体への新しいオプションの変更、 assert という予約語が加えられました。 これは、コンパイラが、1.4 版のソースをコンパイルすると指定された場合のみ、 有効になります。 明らかに、1.2 との互換性の要求から、 Ant では、この予約語を使ってはなりません。 その代わりに、 JUnit の assert() メソッドを使い、 assertTrue() を呼び出すように変更しなければなりません。

Java 1.5では(おそらく)新しいキーワード、enumが追加されます。 将来の互換性のためにこのキーワードは避けるべきです。

リファクタリング

タスクに対して行われた変更が扱いにくいものになってしまった場合、 設計が整然とするように分割し、 コードをリファクタリングし、 安定しているだけでなく、整然としたタスクを投稿しなければなりません。 Ant プロセスで起きる傾向にある共通のデザインパターンは、 アダプターパターンの適用です。 例えば、ベースクラス(例えばJavac や Rmi)は最初は簡潔でしたが、 複数のバックエンド javac、jikes、jvc のサポートにより、 難解なものになってしまいました。 設定可能なフロントエンドをバックエンドを提供するクラスから分離するリファクタリングにより、 設計が整理され、新しいバックエンドを加えるのが、 より簡単になりました。 しかしながら、これをやり遂げるには、 フロントエンドのインタフェースおよび振る舞い一意な物にしておくこと、 そして、 データメンバーを直接参照するサブクラスが無いことを確認することが必要です。 なぜなら、これらのデータメンバーは、リファクタリングされた設計では、 存在しないかもしれません。 それが、privateなデータメンバーを持つことが重要なのかという、 理由なのです。

テスト

ant/src/testcases を見ると、 配布されたAntタスクのJUnitテストが見つかるでしょう。 テストを見ると、タスクが何をしているのか、 新しいタスクの動作の期待結果が何であるのかがわかります。 テストの多くは基本的であり、 間違いなくあなたのタスクにとってよく働くでしょう。 気楽にやってみてください。

テストケースを上手に書くと、 実際にコードが完成するまで、開発中のAntタスクを壊していくでしょう。 そして、後に直面する全てのバグは、 その問題を実証するために、テストケースに加えられます。

テストケースは、開発中にあなたのタスクをテストする素晴らしい方法です。 単にAntソースツリーの'build run-test'を呼ぶだけで、すべてのantのテストが実行され、 あなたの変更が何か壊していないかを検証することができます。 単一のタスクをテストするには、単発のant run-single-test -Dtestcase=${testname}を使います。 ${testname}は、あなたのテストクラスの名前です。

テストケースは、 コミッターが変更やパッチが意図した通りに動作しているか、 検証するのにも使われます。 テストケースがあれば、かなりの信頼性を高めることができます。 正確に言うと、テストケースのない投稿は嫌いです。 何故なら、我々が自分で書かなければならないからです。 我々が必要であるか、多くのユーザーにとって全く必要であると認められた場合のみ、 我々はタスクを受け取ります。

また、Ant 1.x は Java 1.2 上でコンパイルされ実行されるように設計されていることを忘れないでください。 従って、使用する全ての最新版と同様に Java 1.2 でもテストしなければなりません。 この目的のために Sun から古い SDK をダウンロードすることができます。

最後に、 不注意で何かを壊していないか確認するために、 自分のプロジェクトを開始する前と後に、 全体の build test を実行します。

ドキュメント

ドキュメントが無ければ、 タスクは使えません。 そのタスクについて既存のタスクと同様のスタイルで記述した、 簡潔で明瞭な HTML (近々 XML になります) ページを提供するのを忘れないでください。 それには属性と要素の一覧、および、 少なくとも一つのタスクの動作例が含まれていなければなりません。 多くのユーザは、手始めに、 この例を自分のビルドファイルにカットペーストします。 従って、その例は実践的なもので、テストされたものにしてください。

提案されているように、xdocs に類するものが使えます/ xdocs とはソースコードの javadocs からドキュメントページを自動生成するためのものです。 これにより、普段の作業が簡単になり、 xdoclet が生成する完全なビルドプロセスのドキュメントへの変換は、 取るに足らない事となります。

使用許諾と著作権

Apache プロジェクトに投稿される全てのコードは、 Apache Software License と互換性がなければなりません。 そして、投稿した事により、暗黙的に、 投稿されたコードの所有権は Apache Software Foundation へと、 移管されたものと見なされます。

これは重要な事です。

Apache のかなり自由放任的なライセンスは、 Free Software Foundation(GNUプロジェクト) の GPL や Lesser GPL と互換性がありません。 これらのライセンスには厳密な用語 "copyleft(著作権の放棄)" が含まれています。これは Apache Software Foundation のライセンスにはありません。 これにより、 Apache、Ant や Jakarta Project という名前を使わずに、 Apache ライブラリやソースを用いて、許可なしで、 個人や組織が商用や組織内でのソースアプリケーションを構築できるようになります。

GNU GPL ライセンスは、すぐに全ての大きなアプリケーション( GLPL の場合はライブラリ)に対応するように組み込まれるものに拡張するので、 Ant チームは GPL や LGPL のソース基づくいかなるタスクも Ant のコードベースに組み入れることはできません。 投稿するのは自由ですが、 礼儀正しくも断固として却下されます。

Ant 2 に優れた動的なタスクの組込み機能が加えられると、 間接的に[L]GPLコードをサポートするフレームワークを提供することが可能になるかもしれませんが、 それでもなお、GNU ライセンスに直接帰属するタスクは Ant の CVS ツリーには入れることはできません。

import やリフレクションにより、 GPL や LGPL ライブラリにリンクする場合、 作成したタスクも、同じライセンス条件となります。 ですから、(L)GPL コードにリンクするタスクは、 Apache で管理されるコードベースには入れられないのです。 そのようなコードを呼ぶタスクは、 この点でリンクせずに単に実行するだけなので、 プログラムを実行するために、 'exec' や 'java' タスクを使います。

作成したタスクを Apache コードベースに組み込めないとしても、 そのタスクを置いた場所を参照できます。 つまり、単に、作成したタスクを参照する xdocs/external.html への差分を投稿できます。 作成したタスクが直接、所有権のあるコードへリンクしている場合には、 別の問題があります: このタスクをビルドするのはとても難しいです。 リフレクションを使ってください。

車輪の再発明をしない

私たちはみなこれをやってしまいます。 タスクを作り投稿してみると、他のタスクで既に実装されているものであったり、 誰かが投稿してはいたけど、コミットされていなかったということがあります。 日々のソースの更新を取得し続け、 最新の CVS ツリー中に何があるか気づき、 マニュアルの変更を読んだり、 ant-dev メーリングリストを講読することにより、 これを避けることができます。

タスクの作成しようと考えるとき、あなたの考えを投稿してみてください。 他の人々の洞察を得、コードのすべてを書かなくても、 半分書けば、タスクの基本機能を満たすことができるでしょう。

Ant への投稿

Ant タスクを投稿する手順は、 Jakarta ウェブサイトで記述されています。 基本的なことは、 dev メーリングリストへメールすることです。 このリストに投稿すれば、 他の提案や、あなたの提案についての議論が得られるので、 有益でしょう。

次のどれらのアプローチでもパッチを作成することができます。 コミッターは最初のアプローチを薦めています。

パッチは、 [PATCH] というタイトル、および、はっきりわかる一行の要約 をパッチの件名としたメッセージに、 添付ファイルとして送らなければなりません。 ファイル名/タスクおよび、変更点で通常は十分です。 変更を添付ファイルとして入れることが重要です。 多くのメーラーでは、テキストを(本文中に)ペーストしてしまい、 これでは、パッチを壊してしまいます。

そうするのが適切であると感じたならば、 コミッタの一人がパッチをコミットするのを待ちます。 バグ修正はすぐに行われ、 しばしば、他の変更は、 (修正された)コミットが行われるまえに熱い議論となります。

新しい投稿は、[SUBMIT] という件名から始まらなければなりません。 メーラーデーモンは 100KB を超える全てのメッセージを受信拒否します。 ですから、全ての大きな更新は ZIP アーカーブしなければなりません。 投稿がそれよりも大きい場合には、 別々のタスクに分けてください。

無くならないように、 提案をbugzilla に追加するのも歓迎です。 意味ある名前のレポートを最初に書き込んで、 添付ファイルを加えて投稿してください。 CVS diff ファイルを使ってください。

2 週間ほどたっても何も音沙汰無い場合には、 メーリングリストを思い出してください。 時として、他の問題のノイズに、 良い提案が埋もれてしまうことがあります。 これは、特に新しい製品リリースポイントの前によくあります。 そのようなときは、バグ修正の他の事は無視されがちです。

チェックリスト

これらは、 パッチや新しいタスクを投稿する前に、検証しなければならない事です。 これらの事柄は完璧である必要はありません。 パッチや提案がコミットされる前には、 何回かの繰り返しがあります。 これらの項目は手続きの一部なのです。 コードがコミットされる時点では、 ドキュメントや幾つかのテストケースを含む全てが行われていなければなりません。 みんなに見てもらうことにより時間の節約になるでしょう。 ドキュメントによりタスクのメリットがわかるので、 コミッタは、より良いパッチ、 テストケースの提案を探します。

パッチ投稿前のチェックリスト

新しいタスクを投稿する前のチェックリスト


Copyright © 2001-2003 Apache Software Foundation. All rights Reserved.

[訳注:これは漆島賢二、宮本信二が翻訳しました。日本語訳に対するコメントがあれば report@jajakarta.orgに送ってください]