3

保険データ変換プラットフォームでGuiceの使用を開始する準備をしていますが、Guiceのドキュメントや見つけた投稿では直接取り上げられていないような興味深いシナリオに遭遇しました。

私たちのプラットフォームは、いくつかの重要な領域でカプセル化されたコンテキスト(EC)パターンを使用しています。たとえば、10個のポリシーのセットを処理していると想像してください。新しいポリシーの処理を開始するときはいつでも、PolicyContextオブジェクトを作成し、ポリシー番号、州、会社などのプロパティを初期化する必要があります。これPolicyContextは、変換プロセスに関係する多くのクラスの依存関係です。

PolicyContext(およびアプリ内の他の*Contextオブジェクト)は、特定のドメイン領域に厳密に焦点を合わせた値オブジェクトであることに注意してください(基本的な、遍在的に必要なポリシー情報を表します)。あなたの間のパターンの達人がまだこれをアンチパターンであると考えているかどうかを知りたいと思います(MiskoHeveryがhttp://misko.hevery.com/2008/07/18/breaking-the-law-で議論したように) of-demeter-is-like-for-a-needle-in-the-haystack /)これらは純粋に価値のあるオブジェクトであり、確かに「台所の流し台」を表すものではありませんが。</ p>

現在、PolicyContext可能な限り最悪の方法で管理しています。静的グローバル変数、policyContextがありpolicyContext.initialize(String company, String state, String policyNum)、新しいポリシーの処理を開始するたびに呼び出されます。

私の目標は、Guiceがこれらのコンテキストオブジェクトをアーキテクチャ的に最適な方法で管理し、概念的には、新しいポリシーの処理を開始するたびに次のことを行うことです。

  1. Guiceは古いものを破棄しPolicyContextます。
  2. Guiceは、データベースからのパラメーターPolicyContextを使用して、新しい不変(臭い初期化メソッドなし)を構築します。company/state/policyNum
  3. Guiceは、すでに構築PolicyContextされているものを、それを必要とするすべてのクラスに注入します。

これが私の暫定的なアプローチです:

  1. カスタムスコープを作成します。これは、 http: //code.google.com/p/google-guice/wiki/CustomScopesにあるGuiceバッチスコープのサンプルに似ています。ここで、バッチの境界は外部で決定されます。このスコープでは、新しいポリシーの処理を開始し、1)前の「バッチ」を終了して新しいポリシーを開始できます。Q:前述のURLにリストされているとおりにGuiceバッチスコープのサンプルを使用できない理由は何ですか?
  2. 依存関係がないため、すべてのPolicyContextコンストラクターパラメーターにAssistedInjectを使用します(これは少し奇妙に思えます)。そのアプローチを採用してを生成すると仮定すると、新しいポリシーの処理を開始すると、次のようなコードが作成されます。PolicyContextFactory

    …
    scope.exit();
    scope.enter();
    @Inject private PolicyContextFactory policyContextFactory; 
    policyContextFactory.create(company, state, policyNum); // the parameters come from a database record.
    // Note that we don’t need to actually store the created instance; it will be injected elsewhere into various class constructors.
    …
    

これは最適だと思いますか?より単純なアプローチがあるかもしれないことを私は知っています(例えばPolicyContext、新しいポリシーを処理するときはいつでも、新しい特定のインジェクターを作成し、それは効果的に新しいものを作成しますPolicyContext)。ただし、これはアーキテクチャの中心的な側面であるため、妥協したくありません。

別のオプションは、このシナリオでDIの使用を控え、個別のメソッドPolicyContextManagerを持つ静的クラスを使用することです。前者のメソッドは現在のメソッドを破棄して新しいメソッドを作成/保存するファクトリであり、後者のメソッドは単に「アクティブ」を返します)。しかし、のようなコードをたくさん書くので、私のコードは手動DIを実行することになります。とにかくGuiceを使い始めるつもりなので、このアプローチは最適ではないようです。creategetPolicyContextPolicyContextmethodThatNeedsPolicyContext(PolicyContextManager.get(), …)

ところで、DIの理解を深めようとする人には、DhanjiPrasannaによる「依存性注入」を強くお勧めします。GuiceとSpringに焦点を当てたこの本は、私が出会った他のどの本よりもはるかに深いので、絶対に不可欠でした。

ご協力いただきありがとうございます!

4

1 に答える 1

3

コンテキストを渡さないようにすることが目的であり、カスタムスコープにより、バインディング(おそらくコンテキストとそのコンテンツのみ)がすでに準備されていることが保証されるため、リンクSimpleScopeはそのままのニーズにほぼ完全に対応しているようです( "@PolicyScopedシード」)。静的参照を静的ThreadLocalに変換するだけでそれらを取得できますが、いくつかの優れたマルチスレッド機能も取得できます。

ポリシースコープのオブジェクトグラフを、呼び出しenterexit呼び出しの間、またはそれらに名前を付けるために選択したものの間に完全に挿入する必要があります。PolicyContextをコンストラクターまたはフィールドに挿入する(オブジェクトの状態に保存する)と、オブジェクトインスタンスがそのポリシーに固有になることに注意してください。これは当たり前のように思えるかもしれませんが、チームメイトが大胆に注入またはキャッシュdueDateCalculatorすると、ポリシー#8675-309に対してのみ期日計算機として暗黙的に構築され、ポリシー#5550-187に対して悪い答えが提供されることに気付かない場合があります。特に@Singleton、ポリシースコープの依存関係を必要とするオブジェクトは、プロバイダーを使用する必要があります。そうしないと、スコープを終了した場合でも、シングルトンがポリシーを「記憶」します。これは「スコープ拡大インジェクション」の例であり、プラザンナはそれについて詳しく話し合っています。

チームメイトが直接注入することはなく、代わりに常に注入することを主張する方が簡単な場合があります(注入可能な場合無料で取得できます)。これにより、オブジェクトが構築されたときにどのポリシーがアクティブであったかを考えるのをやめ、代わりに、そのオブジェクトのメソッドが実行されたときに受け取るPolicyContextを信頼することができます。PolicyContextProvider<PolicyContext>PolicyContext

オブジェクトに依存関係がない場合は、Guiceで作成する必要はありません。それはやり過ぎです。オブジェクトの作成をGuiceに移動するのは簡単です。依存関係が非常に多くなると、手動で作成するのが面倒になります。あなたがしなければならないまでそれをしないでください。

最後に、カプセル化されたコンテキストに関しては、コンテキストにロジックがなく、コンテキストが表示される場所にオブジェクトのバンドル全体が適用可能である限り、ECパターンは有効なリファクタリングであると思います。コンテキスト内のすべてのアイテムがコンテキストを挿入する時間の80%で使用されていることを私に弁護できれば、コードはおそらく短くてわかりやすく、勝ちます。依存性注入の利点の1つは、依存性の追加または削除が非常に簡単であるため、1つの個別にバインドされたContextプロパティの注入から、2つの個別のContextプロパティの注入、コンテキスト全体の直接注入に移行することが非常に簡単になることです。コンテキストの数だけ繰り返します)。

しかし、それは私の見解です。それが役に立てば幸い!

于 2012-12-13T04:56:04.267 に答える