バージョンによってモジュールの依存性を管理する
APIデザインの極意 Java/NetBeansアーキテクト探究ノート
NetBeans開発プロジェクト10年超の蓄積!API設計の経験や考察をまとめた一冊この記事は、書籍『APIデザインの極意 Java/NetBeansアーキテクト探究ノート』の内容を、Think IT向けに特別公開しているものです。
直線ではないバージョン付け
最もよく使用されているソフトウェアの番号付けの方法は、自然数を基にはしていません。代わりに、ドットで区切られた10進システムを使用します。これは、ソフトウェア開発における非直線、つまり、単一方向への開発ではなく、バグ修正リリースやバグ修正リリースのバグ修正リリースなどを表す多くのブランチへ対応するために必要です。図1で示すように、バージョン2よりも機能が少ないと想定される1.1.1などのバージョンが、実際にはバージョン2より後にリリースされる可能性もあります。
モジュール方式のアプリケーションの個々の部品はバージョン番号を持っており、たいていは、1.34.8などのようにドットで区切られた自然数から構成されます。新たなバージョンがリリースされた場合には、1.34.10、1.35.1、2.0などのように新たな(辞書順に)大きなバージョン番号を持つことになります。
モジュール方式のシステムでは、他のコンポーネントへの依存は、依存先コンポーネントの識別名と必要な最低バージョンを示すことで表現することができます。XML(Extensible Markup Language)パーサ、インストールされているデータベースのドライバ、テキストエディタ、あるいは、ウェブブラウザが存在することを要求できますし、それぞれが提供しているインタフェースの特定のバージョンを要求することもできます。たとえば、機能のある部分は、バージョンが3.0以上のxmlparserや1.5以上のwebbrowserといったものを必要とするかもしれません。これは、完全な互換性を想定しています。すなわち、組み立てられたシステムは、その構成モジュールの新たなバージョンを使用してもうまく機能すると期待されています。
ライブラリ変更の全部の履歴を単一のバージョン番号で表すことは、ちょっとばかばかしく思えます。それにもかかわらず、それは適度に実用的であり、最も重要なことは、各ライブラリの個々の開発者が変更内容を番号付けされたバージョンへまとめる機会を与え、そのバージョンは容易に認識できる一方で、みなさんが完全に無知になることを可能にしてくれることです。
依存状態管理は、何らかの規則に従う場合にだけ機能します。最初の規則は、新たなバージョンがリリースされたなら、前のバージョンで機能していたすべての契約は、同様に新たなバージョンでも機能するということです。もちろん、言うは易く行うは難しです。そうでなければ、品質保証部門を誰も必要としないでしょう。第2の規則は、外部への依存内容が変更になったら、すぐにそのことを伝える必要があるということです。したがって、モジュール方式のシステムの一部がHTMLエディタの新たな機能に依存することになったら、バージョン1.0以上のhtmleditorへ新たに依存していることを付け加える必要があります。また、バージョン1.7で導入されたウェブブラウザの新たな機能を使用し始めたのであれば、1.7以上のwebbrowserが必要であるように依存状態を更新する必要があります。
コンポーネントのバージョンによっては、回避策が必要なバグを含んでいる可能性があります。そのため、実装バージョンである2つの目のバージョンが、たいていはコンポーネントと関連付けられています。仕様バージョンと異なり、これは、多くの場合、Build20050611などの文字列であり、同じ値の文字列であるかを検査できるだけです。多くの場合、これはバグを回避するためには優れています。なぜなら、バグが、(仕様)バージョン3.1に含まれているからと言って、バージョン3.2にも含まれていることを意味していないからです。したがって、ライブラリに実装バージョンを関連付けることが、あるバージョンのバグ修正や特別な扱いのために役立ちます。
バージョンと依存性の管理では、システム内部の全部品のすべての要件が満たされることを保証するためにマネージャを必要とします。そのようなマネージャは、各部品がインストールされた際にシステム内のすべてが一貫性を保っていることを検査できます。DebianパッケージやRPMパッケージが、Linuxディストリビューションで機能しているやり方です。そこでは、dpkgコマンドとrpmコマンドが、ソフトウェアパッケージのインストールとアンインストールで使用されています。しかし、実行中にある種の実行時状態を処理するために依存性を使用することもできます。
たとえば、NetBeansに基づくアプリケーションは、実行時にロードされるモジュールで構成されています。NetBeansのモジュールシステムは、宣言された依存性を使用して、コンポーネントが必要とするものが存在するかを知るだけでなく、各モジュールに対して親クラスローダが必要であるかも決定します。そうすることで、コンポーネントの選択を、コンポーネントのクラスパスの構成から隔離します。このシステムは、各コンポーネントに対して個別のクラスローダも提供し、独立したモジュールのクラスパス隔離を保証しています。また、各コンポーネントの宣言された依存性を強制もしています。つまり、モジュールは、外部モジュールに対する依存性を宣言しなければその外部モジュール内のコードを呼び出すことができず、その依存性のいくつかが満足できなければ全くロードもされません。
この記事のもとになった書籍 | |
---|---|
Jaroslav Tulach 著/柴田 芳樹 訳 |
APIデザインの極意 Java/NetBeansアーキテクト探究ノートなぜ、設計の良くないAPIを持つソフトウェアが量産されるのでしょう。エンジニアが良いAPI・悪いAPIについて分かっていない、あるいは、適切なレビューを受けていないからかもしれません。本書では、NetBeansアーキテクトの著者が遭遇してきた様々な誤りを解説し、APIの発展を考慮した設計について詳しく説明。あまり語られることがなかったAPI設計について、貴重な10年間の経験をベースに幅広くノウハウを披露。API設計の技術や知見の水平線を押し広げることができる稀有な一冊です。 |