制御の反転を使用している場合、コンストラクターのサイズは重要ですか?
-
02-07-2019 - |
質問
したがって、おそらく 10 個のオブジェクトがあり、それぞれに 1 ~ 3 個の依存関係 (疎結合に関する限りは問題ないと思います) があり、動作 (タイムアウト、ウィンドウ サイズなど) を定義するために使用できる設定もいくつかあります。
Inversion of Control コンテナの使用を開始する前に、コンストラクターのサイズを推奨される「4 未満」パラメーターに保つために複数の設定を必要とするオブジェクトごとにファクトリと、場合によっては単純な ObjectSettings オブジェクトを作成したでしょう。サイズ。私は現在、制御コンテナーの反転を使用していますが、それがあまり意味がありません。確かに 7 つのパラメーターを持つコンストラクターを取得するかもしれませんが、誰が気にするでしょうか。いずれにせよ、それはすべて IoC によって埋められます。
ここで何かが欠けているのでしょうか、それともこれは基本的に正しいのでしょうか?
解決
クラスの複雑さと IoC コンストラクターのサイズの関係については、この質問を読むまで思いつきませんでしたが、以下の分析によると、IoC コンストラクターに多くの引数があることは問題であることがわかります。 コードの匂い IoC を使用する場合は注意してください。コンストラクターの引数リストを短くするという目標を設定すると、クラス自体をシンプルに保つことができます。続いて、 単一責任の原則 この目標に向かってあなたを導きます。
現在、Spring.NET フレームワークを使用してインスタンス化された 122 個のクラスがあるシステムで作業しています。これらのクラス間の関係はすべて、コンストラクターで設定されます。確かに、このシステムには、いくつかのルールを破った完璧とは言えないコードが少なからずあります。(でも、失敗は学びのチャンスなのです!)
これらのクラスのコンストラクターにはさまざまな数の引数があり、それを以下の表に示します。
Number of constructor arguments Number of classes
0 57
1 19
2 25
3 9
4 3
5 1
6 3
7 2
8 2
引数がゼロのクラスは、具体的な戦略クラス、または外部システムにデータを送信することによってイベントに応答するクラスのいずれかです。
引数が 5 つまたは 6 つあるものはどれもやや洗練されていないため、リファクタリングを使用して簡素化できます。
7 または 8 個の引数を持つ 4 つのクラスは、次の優れた例です。 神オブジェクト. 。それらは分割されるべきであり、それぞれがすでにシステム内の問題点のリストに載っています。
残りのクラス (1 ~ 4 つの引数) は (ほとんど) 単純に設計されており、理解しやすく、 単一責任の原則.
他のヒント
多くの依存関係 (おそらく 8 つ以上) が必要な場合は、設計上の欠陥を示している可能性がありますが、一般的には、設計が一貫している限り問題はないと思います。
また、ロギングや認可などのインフラストラクチャの問題については、コンストラクターの引数を乱雑にするのではなく、サービス ロケーターまたは静的ゲートウェイを使用することを検討してください。
編集:おそらく 8 は多すぎるでしょうが、これには奇妙なケースがあるだろうと思いました。Lee の投稿を見て、通常は 1 ~ 4 が良いことに同意します。
こんにちはジョージ、
まず、オブジェクト間の依存関係は何でしょうか?
「いさ」関係が多い?「はさ」関係がたくさん?
ファンインが多い?それともファンアウト?
ジョージの答えは次のとおりです。「ほとんどの場合、継承に関するアドバイスよりも構成に従おうとしてきました...それがなぜ重要なのでしょうか?」
ほとんど「はさ」なので大丈夫です。
ただし、メモリ リークを防ぐために、コンポーネントの構築 (および破棄) が正しく行われていることを確認することをお勧めします。
また、これが C++ の場合は、必ず仮想デストラクターを使用してください。
これは難しい問題であり、適切なプロパティは変更可能であり、不変プロパティと有用なデフォルトのない必要な依存関係のみがコンストラクターの一部であるハイブリッド アプローチを私が好む理由です。一部のクラスは、必要な要素を使用して構築され、必要に応じてセッターを介して調整されます。
それはすべて、IOC を実行するために使用したコンテナの種類と、コンテナがインスタンス化されるオブジェクトを飽和させるためにアノテーションを使用するか設定ファイルを使用するかどうかに応じて異なります。さらに、コンストラクターのパラメーターが単純なプリミティブ データ型である場合、それは実際には大したことではありません。ただし、非プリミティブ型がある場合、私の意見では、コンストラクターベースの DI ではなくプロパティベースの DI を使用できます。