コミュニティではJSR 277(リンク)をめぐって再度論争になっている。JSR 277はJava 7向けに提案された動的モジュールシステムである。今回、論争の発火点となったのは、JSR 277 Java Modules(JAMs)向けに計画されているバージョンのナンバリングシステムである。InfoQではJSR 277の現状とコミュニティによる受け入れ状態を理解すべく、論議と主張を吟味した。
JSR 277のバージョニングシステムに関して最初に疑問を投げかけたのはAlex Blewitt(リンク)で、過去に一貫性のないバージョニング戦略をとったSunを危惧してのことであった。Blewittはまた、4つのバージョン番号と文字列限定子を備えるというJSR 277の戦略はあまりにも冗長に思えるし、Java自体にも、たとえば1.5.0_13というバージョン番号があり、先頭の1はJavaが誕生してからこのかた変わっておらず、0はめったに使われない数字であり、13はJava (5)という所定のバージョン向けのビルド番号に関係している、と指摘している。最後にBlewittは、JSR 277の内部で範囲指定を行う方法が無用に複雑になっているようであると指摘し、さらには、OSGiなどの既存のバージョニング形式が十分理解されて広く利用され、簡略でもあるのに、なぜJSR 277にまったく新しいバージョニング・スキーマを考案する必要があったのかと問いかけている。
この後ほどなくして、JSR 277仕様のリーダーを務めるStanley Ho(リンク)が2部構成の論文という形でBlewittへの返答を発表したが、その1部では4桁のバージョニング・スキーマ(リンク)を選んだ理由を扱い、もう1部でバージョニングの範囲(リンク)を論じている。4桁のバージョニングシステムを支持して、Hoは次のように述べている。
プログラムの中には、バージョン番号が数字3個や、数字2個でもうまくやっていけるプログラムがあるとしても、数字4個に反対する明らかな理由にはなりません。OSGiの数字3個のポリシーでは、3番目の数字がバグ・フィックス用になっているため(OSGi R4.1 3.6.2)、本流のプロダクトバージョンには数字2個しか残りません。これではまったく用をなさないというプログラムもあり、そうしたプログラムのOSGiメタデータでは、本流のバージョンで3個の数字をすべて使い、バグ・フィックスには限定子を使います。限定子は辞書式に比較されるので(OSGi R4.1 3.5.3)、残念ながらこれには注意が必要です。4番目の数字を限定子でシミュレートしようとすると、1.2.3.1と1.2.3.2では、OSGiの方法では1.2.3.10より1.2.3.2の方が上位であり、好ましいとみなされるため、混乱してしまいます。ですから、バグ・フィックス向けに4番目の数字ではなく、限定子を使用すると、本当はうまくいきません。(OSGiが自然な順番の文字列比較を採用していたなら、数字を使う限定子がずっとユーザフレンドリーになり、4番目のバージョン番号に取って代わる合理的な選択肢になったでしょう。)
Hoはまた、JSR 277における限定子セマンティクスも論じている。
Java Module Systemは「限定子が空の文字列になっている場合は、他のいかなる値よりも大きいとみなされる」というポリシーに則っています。すなわち、限定子は「真」のバージョンにどちらかといえば従属するものと考え、限定子のないバージョンは限定子つきの同バージョンより上位になります。1.2.3は1.2.3-alphaや1.2.3-betaより上位になるわけです。これはOSGiと対照的で、OSGiでは1.2.3は1.2.3.alphaや1.2.3.betaより下位にあたります(OSGi R4.1 3.5.3)。
どちらのスキームも、もう片方より「直観的」であるとはおそらく言えませんが、Java Module SystemはJDKによる従来のバージョニングポリシーに従っています。JDKポリシーは吟味する価値があります。(ここで意味しているのは開発者バージョン(リンク)の1.1.xから1.6.xなどで、マーケティング用の「Java 5.0」、「Java SE 6」といった「プロダクト」バージョンではありません。ところで、開発者とプロダクトで分けることが物議をかもしていることは(リンク)承知しています。)
FCS前(First Customer Ship前)のバージョンとFCSバージョンの区別に限定子を使うプロダクトを考えてみましょう。たとえば1.2.3-betaと1.2.3-fcsです。FCSバージョンをインポートしたいプログラマーは、その正確な限定子を知っていなければならず、各ベンダーにはベンダー独自のFCS限定子がある可能性が高いので、正確な限定子の把握は面倒です。もっと簡単なスキームがJDKのポリシーになるわけですが、限定子をつけないバージョンをデフォルトの「許容」バージョンとして標準とし、FCS前のバージョンを示すには限定子をつけます。
FCSバージョンに限定子をつけないなら、FCS後の変更はどのように記述すればいいのでしょうか。JDKポリシーによると、プロダクトがひとたびFCSバージョンを与えられると、そのバージョンのコードが再度変更されることは決してありません。コードにいかなる変更があっても、新しいバージョン番号になります。(限定子がつくことも、つかないこともあるでしょう。)こうしておけば、同一バージョン番号についてFCS前とFCS後の両方に関する情報を限定子で表現するよりも、サポートがしやすくなります。この一対のポリシーによりプログラマーは、FCS前バージョンとFCSバージョンや、FCSバージョンとFCS後バージョンを容易に区別できるようになります。
Hoは最後に、JSR 277でバージョン範囲がどのように機能するかを説明した。
Java Module Systemでは、モジュールが他のモジュールへの依存性や、そうした他のモジュールの特定バージョンへの依存性を記述します。バージョンとバージョン範囲は、構文のあらゆる要素同様、基本的に好みの問題ですが、Java Module Systemでは、通常のバージョニング作業を容易に、そして高度なバージョニング作業を可能にするよう努めました。
[...]
Java Module SystemがOSGiと違うところは、単一バージョンの解釈です。OSGiでは、1.2.3のような単一バージョンを「1.2.3以上」と解釈します(OSGi R4.1 3.2.5)。バージョン1.2.3ちょうどを入手するには、[1.2.3,1.2.3]と書かなければはなりません。暗黙の範囲を採用すれば確かに簡潔ですし、ちょうどのバージョンはほとんど使用しないため、[...,...]によって発生する間接費はそれほど悪くありません。しかし何百万というプログラマーがJava Module Systemを介して初めてバージョンに遭遇するので、あらゆる用語について可能な限り、最も単純な解釈を採用するのがベストです。初めて1.2.3を目にする者が「1.2.3ちょうど」とみなすことに疑いの余地はなく、ですからJava Module Systemではそのように解釈するのです。範囲については、明示的な記号で示します。
Hoのこの論文には多数が反応を示したが、その中の1人のJosh Reedは(リンク)次のように述べている。
「1.2.3.4」の依存性に、バージョン1.2.3.4以外の何ものも意味させないという決定についても、間違った処置であると思います。開発者が記載の依存性を初めて見たとき、1.2.3.4ちょうどのバージョンを想定するだろうという点は認めます。しかし実際は、多数のソースや開発者からのモジュールで構成されるアプリケーションのデプロイ時には、ちょうどのバージョンが欲しいことはほとんどありません。私は怠け者のプログラマーなので、ライブラリXのバージョン1.2.3.4で作業していたら、おそらくそのことを依存性として明示するでしょう。他の誰かのモジュールを統合するとして、その人間もライブラリXに依存していますが、作業に使っているのはバージョン1.2.3.5です。すると突然、アプリケーションに同一ライブラリのコピーを2つ保持しておく必要がでてきますが、99%のケースで、バージョン1.2.3.5が両方の依存性を満たしているのです。イデオロギーの相違と推測しますが、通常の場合は、正確に特定のバージョンというよりは、1.2.3.4以上だと思います。作業しているライブラリが不安定すぎて、正確なバージョンが必要な場合は、余分な手間をかけて、たとえば[1.2.3.4, 1.2.3.4]とするべきだと私は思います。私のように怠け者の可哀想なプログラマーが、(1.2.3.4とそれ以上という)ありふれた状況で楽に仕事できるようにしてください。物事の正しい処理が簡単にできるようにしてください。
この2本のブログ投稿から推察すると、OSGiに近いけれども、十分な相違があり、そのため、新しくて、独特、そして正しいバージョニング・スキームと依存性構文と呼べるものを考案するのに、Hoさんたちが一生懸命頑張ったというところでしょう。あなたの勝ちです。でも、犠牲が多すぎて引き合わない勝利です。なぜなら、考案の必要がないものに対して、これほどの時間を費やした(浪費した?)のに、そのすべてがどのように連携して働くのかが全くわからない手探り状態なのですから。開発者の私にとっては、真価の問われる場なのに、どのように機能するかを示してもらえないし、新しいアプローチが必要ということについてさえ、私は心から納得していないのです。
sorontharという名のユーザもコメント(リンク)している。
Sunを非難しないでください。「3桁を超える」バージョニング・スキームを使っているのはSunだけではないのですから。IBM(そうです。Eclipseを作成しOSGiを後押ししているあのIBMです)はWebsphereとDB2で4桁使い、オラクルはデータベースに5桁使い、Linuxのカーネルは4桁ですし、まだまだ列挙し続けられます。
重要なのは、この提案を激しく非難し、「OSGiがあるナンバリング・スキーマを別のスキーマに優先させて使っているという理由から、この提案はOSGiを非難しようとしているのだ」、と述べるのはまったく非現実的です。なぜなら、成功を収めている他の有名製品が、OSGiプラットフォームの存在期間より長い時間をかけて、「3桁を超えるバージョン・スキーマ」の必要性を実証しているからです。(それはそうと、3桁のバージョニング・スキーマを選んだのは一体誰でしょう?その理由は何でしょう?)JSR 277仕様のリーダーが、新しいバージョニングと現行のOSGiバージョニングが共存するようになる、と明言すれば、この非難はさらに無意味なものとなるでしょう…
Paulus BenedictusはJSR 277のプロセス自体に関して、欲求不満を表現している(リンク)。
このJSRは哲学の授業になってしまっています!!…取るに足らない詳細の討論になっています。わざわざ一からやり直すこと(すなわち、バージョニング)に多大な思考活動を行い、そして開発はすべて秘密に行われています。Hoさん、この作業の秘密主義的・内輪主義的性格が改善されたと思えるようになるまで、大衆があなたをそっとしておくことはありません。それから、このJSRが、いわゆる「より良い仕様」を使っていることを示すために、OSGiと比較するのはやめてください。何が使えるのかを答えてください。
Patrik Benoは(リンク)代替のバージョニング方法を提案している(リンク)。
私が提案するソリューション(バージョンの履歴に基づくバージョンの互換性)を使えば、モジュールシステムは間違っている可能性のある仮定を行わなくてもよく、すべての規定に単一のバージョニングポリシーを強要することもありません…単に柔軟性が高くなっているのです。
重要なのは:
(a)ライブラリのクライアントは、クライアントと互換性を持つことになる将来のバージョンを知らないかも知れませんが、
(b)ライブラリ提供者は、過去のバージョンにはあっても、打ち切りにしたものの有無について、必ず知っています…
ということです。
次のようなバージョニング・シーケンスとすることができます(論点をはっきりさせようとしているだけで、事実として正確なわけではありません)。
- チョウゲンボウ
- コチョウゲンボウ(下位互換性=偽)
- ぴょんぴょん跳ねる動物
- カマキリ
- トラ(下位互換性=偽)
- 6.0(下位互換性=偽)
James Ervin(リンク)は、一段高いレベルから(リンク)バージョニングの理由を考察している。
今回の場合、wikipedia(リンク)によるバージョンの定義が気に入っています。かなり包括的な定義で、こんな感じです -- 「ソフトウェアのバージョニングは、ユニークな状態にあるコンピュータソフトウェアにユニークな名称あるいはユニークな番号を割り当てるプロセスです」。この定義はすべてのケースをカバーしようとしているので、ここで注目すべきポイントは、ソフトウェアのユニークな状態に与えるユニークな識別子ということです。では、ユニークに識別しようとしているのは、どのような状態なのでしょうか。開発者がソフトウェアに加えた変更はもちろんですが、コンポーネントレベルにおいては少なくとも2つのカテゴリーに分類されると思います。1つ目のカテゴリーは、クライアントが依存している外部APIに変更が加えられたため、依存性の管理に影響を与える変更です。2つ目のカテゴリーは、このブログ項目向けにブックキーピングと呼びましょう。なぜブックキーピングと呼ぶかというと、外部APIを使っているクライアントに影響するはず(ここではずを使ったことにご留意ください)ではない内部の変更を意味しているからです。「ブックキーピング」が登場するのはソフトウェア開発者も人間で間違いを犯すからで、変更がクライアントに悪い影響を与えるはずはないのに、与えてしまうからです。「ブックキーピング」によりシステムインテグレータやシステム管理者は、コンポーネントXのバージョンは機能したが、X+1は確実に機能しなかったということに留意できるため、これはサポート担当者がまさに聞いておきたい情報となるのです。一方のカテゴリーがもう片方よりも重要と決めるのは実に難しいです。1番目のカテゴリーにおける変更の場合はシステムの正しい動作を妨害しますし、2番目のカテゴリーの場合は、システムが後になってから混乱した理由を説明するのに役立つでしょう。
Peter Kriens(リンク)もますます拡大した論争に反応し(リンク)、次のように述べている。
既存のスキームを改善する理由は必ずありますが、いかなる改善も、既存および将来のオーディエンスの利害を考慮してバランスをとるべきです。OSGiのバージョンが最高のバージョン・スキームと言っているわけではなく、私たちも皆と同様に、誤りを犯しやすいのです。おそらく私たちは合理主義的すぎたのです。たくさんのスキームを見ましたが、世間の人々もバージョン・スキームの右端に場所を探していて、先頭の数字を増加させることはほとんどなかったのです。標準化すると、できる限り自由にさせることと、それと同時に、提供するバリエーションに依存する実装をできる限り単純にすることの間に、常に対立が存在します。私たちの場合は、単純を選んだのです。
OSGiのスキームは使用に適しているのでしょうか。そうですね、この分野で未解決の要件やバグはなく、JSR 291でも提案されたものはありませんでしたが、このスキームはヘビーユースされています。Maven(達人)と呼ばれているJason van Zylが教えてくれたところによると、Zylらもこのスキームの採用を検討していたそうです。SpringSourceでは400近くのオープンソースプロジェクトをバンドルに変換しましたが、不平はありませんでした。巷には実用的な使用法がたくさんあるようです。
SunがOSGiのスキームを採用してくれさえしたら、私たち全員にとって、より生産的になるのではないでしょうか。モジュールAPIではすべきことがたくさんあるので、既存の仕様を使えるところでは、再利用すればよいのではないでしょうか。そしてOSGiスキームに大変重要な問題がある場合は、バグとして報告するか、変更をリクエストしてはいかがでしょう。結局のところSunはOSGiの著名なメンバーなのです。
Ian Skerrett(リンク)はこの論争の根本的原因について、異なる考え(リンク)をもっている。
オラクルのOSGiグルであるHal Hildebrandが、JSR 277で何が間違っているのかについて、一番鋭く見抜いています(リンク) -- 「駆け引き」です。Sunは時代の先端を行く、開かれた会社である、とSunの重役がいくら語っても、Sunは相変わらず旧態依然としたハードウェアベンダーのような行動をとるのです。実態のないJSR 277の専門家グループは、JCPプロセスにしてみても、どんな人間の「開かれた」という言葉の定義に照らし合わせても、まがい物です。コミュニティを構築して、JSR 277とOSGiの橋渡しをする代わりに、Sunは裏戦術を使ってOSGiとJSR 277間にある種の「妥協」を見つけているのです。
Sunよ、二面性のある議論をやめて、真の仕様リーダーを据えたJSR 277専門家グループ(リンク)を再度立ち上げ、OSGi組織への参加を始めてください。要するに、駆け引きをやめて、OSGiとJSR 277が確実に共存できるように、真の開かれた議論を開始してください。これ以外の何事も、Javaにとって悪材料となるでしょう。
Alex Blewittはプロダクトバージョニングとライブラリバージョニングの違いに注目している(リンク)。
重要なのは、基礎をなしているコンポーネントのバージョニングシステムが、全体としてのプロダクトのバージョン番号とは完全に異なる可能性があるということで、全体としてのプロダクトは(例外なく)下にあるコンポーネントを集合させたものなのです。プロダクトにはユーザフレンドリーな名前(Leopard)や数字のバージョン(10.5.3)、ビルドタグ(9D34)、インストールを表現するまったく別の方法(/System/Library/Frameworks/System.framework/Versions/B)があるかもしれません。ですから、マーケティング(やその他)の目的に使われる可能性のあるバージョニングに基づいた特定のバージョニング・スキームに賛成して議論することは、どちらかというと無駄です。両方が共存し、異なる人々を対象として異なるものを意味することができるのです。Eclipseは3.1の時代にこの教訓を学び、それ以来、Eclipse 3.4にはorg.osgi.util_3.1.300のようなプラグインが入っていますが、これはプロダクト名と完全に区別できます。なぜならバグ・フィックス以外の変更はないからです(すなわち、APIや非互換になる変更は皆無です)。大型システムの維持管理を担当している方には、Eclipseのバージョンナンバリングに関する注記(リンク)を読むようお勧めします。実際Eclipseは、プロダクト用のバージョン番号をやめ、Europa(リンク)やGanymede(リンク)のようなコードネームを使うようになっています。
Blewittはさらに、OSGiの採用が増えていると指摘している(リンク)。
〔Burtonグループが実施した最近のOSGi調査では〕アプリケーションサーバがOSGiバンドルを直接サポートしていたら、そうしたサーバ内で直接バンドルを開発することを検討する、と回答者の10人中9人が述べており、Infiniflow(リンク)やSpringSource Application Platform(リンク)といったツールは将来に向けて準備万端であると結論づけています。
問題は、そうなるとJSR 277はどうなってしまうのか、ということです。右にならう実装には遅すぎるということでしょうか。
Sunでクライアントソフトウェアのチーフアーキテクトを務めるDanny CowardはSD Timesの記事の中で(リンク)、JSR 277はまだ開発の初期段階にある提案にすぎない、と指摘している。Cowardは次のようにも述べている。
特定のOSGiバンドルに対して依存性を表明しているJDK 7内でアプリケーションがデプロイされるとき、OSGiをサポートするJava Module Systemはその依存性を解決するためにそのOSGiバンドルを探し回りますが、その際、Java Module Systemのバージョニングナンバリング・スキームとOSGiバンドル内のナンバリング・スキーム間に変換ステップを作成します。
[...]
JDK 7には、2つのスキーム間のギャップを埋める変換とブリッジをうまく処理するコードを少しばかり入れる予定です。
Peter KriensはJSR 277(リンク)における依存性の管理についてコメントし、粒度の細かいImport-Packageの依存性が粒度の粗いRequire-Bundleの依存性より優れている理由を説明している。
こうした問題を説明する非常に実用的なユースケースが2つあります。Require-Bundleに著しく依存するEclipseは、埋め込みプラットフォームとSEプラットフォーム上でSWT(グラフィックスライブラリ)をサポートする必要がありました。埋め込みプラットフォームはSEプラットフォームのサブセットである必要がありました。残念ながら、SWTの全ユーザがRequire-Bundleを使っていました。これにより、SWTバンドルを2つのバンドルにリファクタリングするという単純なソリューションができたのですが、そうするとEclipiseのあらゆるプラグインが壊れてしまうので、不可能でした。Import-Packageを使ったバンドルなら、この変更に気付いていなかったでしょう。
もう1つのユースケースは、最近のブログ「Catch-22 Logging with OSGI Frameworks(リンク)」(OSGiフレームワークの矛盾したロギング)で説明しています。かなり長い話なのですが、要点を申し上げると、Require-Bundleのロギングに関係する余計な制約が原因で、2つのライブラリを結合できなかったということです。髪の毛にチューインガムがくっついたときのような感覚を味わいたいというマゾ願望がおありなら、このブログをお読みになるよう勧めます。
Sun Microsystemsの上級スタッフエンジニア、Mandy Chung(リンク)も、JSR 277向けOSGiリポジトリのプロトタイプを最近発表している(リンク)。
Java Module SystemでOSGiバンドルをサポートするための仕様の草案(リンク)について、現在JSR 277専門家グループで検討中です。
専門家グループとコミュニティがフィードバックを提供できるようにするために、OpenJDKモジュール(リンク)プロジェクトにOSGiリポジトリのプロトタイプを入れました。このプロトタイプが現在サポートしているのはApache Felix(リンク)のOSGi実装のみで、その目的は「概念の証明」です。まだ解決されていない問題があります。すぐに利用可能なサポートはまだ設計も実装もされていません。その他のOSGi実装のサポートについては、今後調査する予定です。このプロトタイプにより、コミュニティが参加を始め、OSGiの相互運用性サポートに関するフィードバックを提供してもらえるようになればと思っています。
OSGiのサポートに加えてJAMモジュール開発も試して実験できるように、モジュール開発プロジェクトからJDKのバイナリビルドを掲示すべく作業を進めています。それまでは、Mercurialを使ったModulesリポジトリからソースのクローンを作成し、JDKを構築できます。
みなさんはどうお考えだろうか。
原文はこちらです: