設計に関するFAQ
この項では、Preferences APIの設計についてよくある質問への回答を示します。
トピック:
- Preferences APIには、Properties APIとどのような関連性がありますか。
- Preferences APIには、JNDIとどのような関連性がありますか。
- すべてのgetメソッドに対して呼出し側がデフォルトを渡す必要があるのはなぜですか。
- どのメソッドがBackingStoreExceptionをスローするべきかはどのようにして決定されたのですか。
- このAPIが複数のVMによる同時アクセスについてより強力な保証を提供していないのはなぜですか。同様に、このAPIが複数のPreferences更新を単一トランザクションに結合することを許可しないのはなぜですか(オール・オア・ナッシング・セマンティクスで)。
- このAPIが大文字と小文字を区別するキーとノード名を持つのはなぜですか。同様の空間(Microsoft WindowsレジストリやLDAPなど)で使用されるほかのAPIはそうではありません。
- このAPIがJava 2 Collections Frameworkを使用しないのはなぜですか。
- putおよびremoveメソッドが古い値を返さないのはなぜですか。
- このAPIはなぜ保存済みデフォルトを許可するのですか(要求しませんが)。
- 任意の直列化可能オブジェクトを読み書きするメソッドがこのAPIに含まれていないのはなぜですか。
- Preferencesがインタフェースでなく、抽象クラスなのはなぜですか。
- デフォルトのバッキング・ストアはどこにありますか。
Preferences APIには、Properties APIとどのような関連性がありますか。
これは、非常によく使用されてきたPropertiesクラスを置き換える目的で設計されており、軽量性を維持しながら、様々な点を訂正しています。Propertiesを使用するときは、各プロパティ・ファイルのパス名を明示的に指定する必要がありますが、標準の場所や名前の規約はありません。プロパティ・ファイルは壊れやすくなっています。手動で編集できますが、不注意な編集によって簡単に破損します。文字列以外のデータ型のサポートは存在しません。Propertiesは、ファイル・システム以外の永続性メカニズムで簡単に使用することはできません。つまり、Propertiesの機能には拡張性がありません。
Preferences APIには、JNDIとどのような関連性がありますか。
JNDIと同様に、永続的なキー/値データへのバックエンド中立的なアクセスを提供します。ただし、JNDIは、はるかに強力で重量です。JNDIは、強力な機能を必要とする企業アプリケーションに適しています。Preferences APIは、単純で、汎用的な、バックエンド中立性を持つ設定管理機能として設計されているため、Javaアプリケーションの動作をユーザーの要望に合せて簡単に調整でき、実行をまたがって一部の状態を保持できます。
すべてのgetメソッドに対して呼出し側がデフォルトを渡す必要があるのはなぜですか。
これによって、アプリケーション作成者は強制的に相応のデフォルト値を提供することになり、リポジトリが利用できない場合でもアプリケーションは相応の実行機会を得ることになります。
どのメソッドがBackingStoreExceptionをスローするべきかはどのようにして決定されたのですか。
セマンティックスが絶対的にバッキング・ストアとのやり取りを必要としているメソッドだけが、この例外をスローします。通常のアプリケーションでは、このようなメソッドを呼び出す必要はありません。このようなメソッドを呼び出さないかぎり、バッキング・ストアを利用できない場合でもアプリケーションは実行でき、それが設計の明示的な目標でした。
複数のVMによる同時アクセスについて、このAPIがより強力な保証を提供しないのはなぜですか。同様に、このAPIが複数のPreferences更新を単一トランザクションに結合することを許可しないのはなぜですか(オール・オア・ナッシング・セマンティクスで)。
このAPIは基本的な永続データ・ストレージを提供しますが、それはデータベースの代替を意図したものではありません。このAPIを標準の設定/構成リポジトリ上に実装できることが重要で、そのほとんどはデータベースのような保証および機能を提供しません。このようなリポジトリは、このAPIが意図する目的を十分に満たしています。
このAPIが大文字と小文字を区別するキーとノード名を持つのはなぜですか。同様の空間(Microsoft WindowsレジストリやLDAPなど)で使用されるほかのAPIはそうではありません。
Javaプログラミング言語では、大文字と小文字が区別されるStringキーが一般的です。具体的には、それらはPropertiesクラスによって提供されており、このAPIが置き換える予定です。大文字小文字の区別を要求する方法でPropertiesを使用する人は珍しくありません。たとえば、Javaパッケージ名(大文字小文字を区別)がキーとして使用されることがあります。この設計上の意思決定は、大文字小文字を区別するキーを使用するバッキング・ストア上にPreferencesを実装するシステム・プログラマの寿命を複雑にすると認識されていますが、これは受入れ可能な対価と考えられます。はるかに多くのプログラマがそれを実装するよりPreferences APIを使用するようになるでしょう。
このAPIがJava 2 Collections Frameworkを使用しないのはなぜですか。
このAPIは、かなり特定の目的のために設計されており、その目的のために最適化されています。ジェネリック型がないので(JSR-14を参照)、このAPIは典型的なユーザーにとって便利さに欠けます。Map APIに対して強制的に準拠される場合、コンパイル時型安全性が不足します。また、ほかのMap実装との相互運用性が要求されることは想定していません(この想定が間違っているとわかった場合には、アダプタ・クラスを実装することは簡単です)。Preferences APIは設計上、Mapによく似ているため、後者に習熟しているプログラマは前者を使用することは難しくないはずです。
putおよびremoveメソッドが古い値を返さないのはなぜですか。
それらのメソッドは、バッキング・ストアが利用できない場合でも、実行可能であることが望ましいです。それらが古い値を返す必要がある場合、これはできなくなります。さらに、このAPIが一部の一般的なバックエンド・データ・ストア上に実装されている場合は、パフォーマンスが低下します。
このAPIはなぜ保存済みデフォルトを許可するのですか(要求しませんが)。
この機能は、エンタープライズ全体の設定管理を拡張可能かつコスト効率的にするためにエンタープライズ設定に必要ですが、自己管理される単一ユーザー設定では過剰です。
任意の直列化可能オブジェクトを読み書きするメソッドがこのAPIに含まれていないのはなぜですか。
直列化されたオブジェクトは、やや壊れやすくなっています。そのようなプロパティを読み取るプログラムがそれを書き出すプログラムと異なる場合は、オブジェクトが正しくまたはまったく直列化復元されないことがあります。直列化されたオブジェクトをこのAPIを使用して保存することはできますが、推奨しておらず、便利なメソッドも提供していません。
Preferencesがインタフェースでなく、抽象クラスなのはなぜですか。
上位互換性のある方法で新しいメソッドを追加する機能が、Preferencesを「ミックスイン」として使用できないというデメリットを上回ると判断されました。つまり、任意のクラスをPreferencesオブジェクトとして使用することもできません。また、これによって、staticメソッド用の別個のクラスの必要性がなくなります。インタフェースにstaticメソッドを含めることはできません。
デフォルトのバッキング・ストアはどこにありますか。
システムおよびユーザー・プリファレンス・データは、実装ごとに異なるバッキング・ストアに永続的に保存されます。たとえば、フラット・ファイル、OS固有のレジストリ、ディレクトリ・サーバー、SQLデータベースなどのバッキング・ストアに格納されます。たとえば、Windowsシステムでは、データはWindowsレジストリに格納されます。
Linuxシステムでは、システム・プリファレンスは通常、ネットワーク・インストールのjava-home/.systemPrefs
に格納されるか、ローカル・インストールの/etc/.java/.systemPrefs
に格納されます。両方とも存在する場合は、/etc/.java/.systemPrefs
が優先されます。システム・プロパティjava.util.prefs.systemRoot
を設定して、システム・プリファレンスの場所をオーバーライドできます。ユーザー・プリファレンスは通常、user-home/.java/.userPrefs
に格納されています。システム・プロパティjava.util.prefs.userRoot
を設定して、ユーザー・プリファレンスの場所をオーバーライドできます。