2009-02-26 13 views
8

大規模なソフトウェアプロジェクトのユーザー設定を管理するクラスがあります。永続ストアからユーザー設定を設定または取得する必要があるプロジェクト内のクラスは、このクラスの静的メソッドを呼び出すことです。この集中管理により、プリファレンスをプログラムで完全に消去することができます。各プリファレンスが使用コードの近くで処理され、プロジェクト全体に振りかざされると不可能になります。「マスタープリファレンス」クラスは良いアイデアですか?

私は、この中で集中化設計の別の含意に遭遇しました。ソフトウェアには公開APIがあります。そのAPIは単独でjarファイルで提供することができます。そのAPIのクラスは、事前管理クラスを参照することがあります。したがって、プレファーカーはAPI jarに入っていなければなりません。

各設定にはデフォルト値が設定されている場合があります。ソフトウェアの起動時に、そのデフォルト値が計算されることがあります。このアルゴリズムは、好みに依存し、従って、使用コードの近くに存在する傾向がある。したがって、プレファーカーがデフォルトを思いつく必要がある場合は、問題のクラスを呼び出します。

しかし、今の県マネージャが存在してはならないAPIジャーにクラスのすべての種類に吸って、「タコクラス」になったこと。そうでなければ、API jarを使用するプログラムはすぐにClassDef例外を実行します。そうであれば、他のクラスのそれぞれがまだ他のクラスを参照しているかもしれないので、API jarは今や膨らんでいます。

一般に、他のJavaプログラマは、集中化されたクラスで自分のプリファレンスを管理しますか?

パブリックAPIの一部として静的な事前管理クラスを配布することは理にかなっていますか?

デフォルトを決定するコードの保守担当者は、そのプレファマネージャであるべきですか?

答えて

11

IMHO、あなたの最初の質問に対する答えは「はい」と「いいえ」と思います。

プリファレンスは、一般的にクラスがプロジェクト内の多くのクラスのための「シンク」であるという意味で、中央集中型のクラスとして扱われます。呼び出し元のコードに近づけようとすると、同じ環境設定が後で他の場所で役に立つ場合、あなたは困っています。私の経験では、環境設定を「あまりにも近く」すると、やはり一貫性のない処理が行われます。それぞれ、モジュールまたはサブモジュールをサポートする複数のプリファレンスクラスまたは「プリファレンスセット」を使用することがしばしば好ましいと言われています。アーキテクチャの主要コンポーネントを見ると、環境設定のセットを論理的に分割できることがよくあります。これにより、各プリファレンスクラスの混乱が軽減されます。さらに重要なことは、将来あなたのプログラムを複数のjarファイルに分割できることです。さて、 "デフォルト値"の計算機はモジュールに置くことができますが、十分なグローバルな領域に置くことができます。

環境設定を静的メソッドとして直接設定するのではなく、いくつかのgetInstance()操作を使用して環境設定の共有インスタンスを取得し、それを操作することもお勧めします。セマンティクスに応じて、そのオブジェクトをしばらくロックすることができます(たとえば、ユーザーがUIでプリファレンスを編集している間など)。実際のオブジェクトがあれば、これは簡単です。

あなたのパブリックAPIには、これらの変更の結果が何であるかを十分に文書化できる場合にのみ、ユーザーがプリファレンスを変更できるようにする必要があります。

「参照マネージャー」を取得するために単一のAPI関数を使用する場合、ユーザーは独自の「デフォルト値計算機」を提供することができます。プリファレンスマネージャーは、あなたがデフォルトで提供したものに頼る前に、まずこの電卓に質問します。

+0

ワウ;素晴らしい答え。私は多分それの10%で小さな屁理屈を持っているが、関連する趣向の分割は良い呼び出しであり、私は考えるべきだった。 –

+0

私はしばしば同じ問題に直面します(幸いなことにEclipseは私に多くの選択肢を与えません)。私はあなたの意見を聞くことに興味があります:) – Uri

+0

共有マネージャーのインスタンスを取得することについて - 私は本当に(Javaが扱う)ディスク書き込みレベルでは、もちろん、抽象度が高いほど私は気になるはずです。 –

4

あなたは本当に一般的な方法で設定を処理できませんか?永続性を処理するには、環境設定マネージャを使用するだけです。したがって、クラスからは、プリファレンスマネージャーPreferenceManager.setPreference(key、value)にちょうど言っているだけで、データのセマンティクスに関して何が保存されているのかは気にしません。

これをあまりにも単純化していますか?

+0

問題は、たとえば、新規インストールの動作をテストする場合など、すべての設定をクリアしたい場合に発生します。そして、さまざまな開発者がコードベース全体で使用していたすべての設定は、追跡が困難になります。それはただの問題です。 –

1

CocoaのNSUserDefaultsクラスからインスピレーションを受けたい場合があります。ドメインと呼ばれる複数のレイヤーを持つことで、問題を処理します。 "PrintUsingAllCaps"のようなキーの値を調べると、まずユーザーのローカルドメインの値がチェックされます。そこに見つからない場合は、システム全体のドメインまたはネットワークレベルのドメインなどを確認できます。

最終的に確認する場所は「登録ドメイン」と呼ばれ、基本的にハードコードされたデフォルトが行われる場所です。だから、私のコードのどこかで、登録ドメインに優先度を書くことができます。NSUserDefaultsは、ユーザーがそれを上書きしていない場合にのみその値を提供します。

あなたのケースでは、(おそらく)ユーザー定義の値にアクセスする前に、クラスのデフォルト値を設定するメソッドを提供することができます。プリファレンスクラスは、それが提供しているクラスについて何も知る必要はありません。

もっと洗練されたものが必要な場合は、DefaultValueProviderコールバックオブジェクトをストレート値の代わりに設定できます。

2

私はJava Devではありませんが、 "octopus class"全体のことを考えれば、jarへのインタフェースを提供し、インタフェースとprefsマネージャ間の呼び出しを実行時にアプリケーション設定ファイルを使用して、インスタンス化する環境設定マネージャを決定しますか?

.NETプロバイダパターンのようなものはありますか?

そんなやり方で、あなたのjarを環境設定マネージャから切り離すことができます。

0

著者が尋ねていたことを誤解したため、私の最初の回答は削除されました。

実際の質問に実際に答えるためには、環境設定(およびデフォルト値の計算)を使用するコードが意味をなさないようにしたいと思うように感じます。

「グローバル」プリファレンスオブジェクトコレクションに登録すると、その領域のパターンに従う領域ごとにプリファレンスコンテナクラスを使用して両方の要件を満たすことができますか?

グローバルコレクションでは、各プリファレンスのセットを繰り返し実行してデフォルトにリセットすることができますが、プリファレンス自体はローカルで定義され維持され、コードの他の部分には行き渡りません。

私が見ることができる唯一の問題は、インスタンス化時にプリファレンスオブジェクトを登録することを許可すると、まだインスタンス化されていないプリファレンスで「デフォルトにリセットする」というリスクを実行することです。

メインの「プリファレンス」クラスで他のすべてのインスタンスをインスタンス化することでこの問題を解決できるとします。静的なゲッターを使用してローカルのプリファレンス・オブジェクトを取得できます。

これはいくつかのロガーの仕組みとよく似ているようです。ログレベルや出力ストリームなどを維持するための中心的なメカニズムがありますが、各クラスには独自の「ログ」メソッドのインスタンスがあり、ログに記録されます。

これがよりターゲットになることを希望します。ああ、私はまた、受け入れられた答えに同意し、すべてのメソッドをpublic staticにしないでください。常にgetterを使用してください。あなたはいつかはうれしく思います。

0

JSR-10(java.util.prefs.*)APIは、Class<?>パラメータを持つファクトリメソッドを使用してPreferencesインスタンスを作成します。こうすることで、APIは同じパッケージに属する異なるクラスの設定を1つのファイルに格納できます。

関連する問題