2009-06-04 19 views
41

私は手作業のコンストラクタインジェクションDIを少し使っています。私が気づくことの1つは、私のコンストラクタがかなり長くなることです。コンストラクタインジェクション:依存関係の数が多すぎますか?

私は小さなオブジェクトの束に依存するクラスを持っています - 時には6と10の間のどこか。私のアプリケーションを小さな塊に分割し続けていくと、この数は時間の経過とともに増加しています。これは共通の問題ですか?

明らかに、これはプロジェクトに大きく依存することになります。しかし、基本的な質問は次のとおりです。

いつクラスに含まれる依存関係の数に不快感を持ち始めますか?これらの依存関係を減らすために使用する戦略は何ですか?

答えて

10

これは、6-10の依存関係を持つクラス自体をリファクタリングする必要があるという兆候かもしれません。

+1

WWのような複数のクラスにそれらをグループ化する論理的な方法が見つからない場合はどうなりますか?言った?多くの依存関係を持っていることに同意しますか? BMW、OPEL、VWなどの車のブランドが依存関係だと言うことができます。彼らはすべての車です。多分ベストな例ではないかもしれませんが、あなたがそのアイデアを得ることを願っています。 –

+1

@ Darius.V - 50種類のブランド依存性を持つ 'Cars'クラスをお持ちの場合、明らかにSRPに違反しています。あなたのトップレベルの 'Cars'クラスは、それぞれ共通のプロパティとメソッドを持ついくつかの依存関係しか持たないように、それらを共通の特性(つまり、' ElectricCars'、 'HybridCars'、' DieselCars'、 'GasolineCars')にグループ化する必要があります。その下に、[戦略​​パターン](https://stackoverflow.com/a/31971691)を使用して、複数の類似自動車を単一の依存関係に単純化することができます(たとえば、あなたの車に注入される単一の「GasolineCarsStrategy」すべてのガソリン車を管理するクラス)。 – NightOwl888

4

私は3つまたは4つ以上とは思わないでしょう。それ以上のものを手に入れているのであれば、私はあなたのconcernsをどの程度うまく抽象化しているのか考え始めるでしょう。例えば、単一のrepositoryオブジェクトは、問題のクラス内のすべてのデータ取得ニーズを満たす必要があります。

+3

おそらく、オブジェクトがデータベースへのアクセスを必要とし、割り当てられたものから2つの依存関係がすでに存在する外部(例えば、リポジトリとIO)と通信する何らかの方法があれば、それはおそらく、それぞれクラスは単一の責任しか持たない(単一の関心事)より少ないクラスではなく、より多くのクラスに帰結するだろうか?最終的には、これらの小さな部分すべてをオーケストレーションできるクラスが必要です。そのクラスは機能するために多くの依存関係を持ちます。 – Runcible

+0

@Runcible、かなり正しい。そして、あなたが説明している統合が行われると、実際にはコンストラクタに注入するものが少なくなります。 BTWについて説明しているものは、Inversion of Controlコンテナです(例:Windsorのような)。 –

+1

@Runcible、私は最近、注射に対する依存性のこの問題に苦労してきました。私はかなり役に立つ2つの投稿を見つけました。 http://blog.ploeh.dk/2010/01/20/RebuttalConstructorover-injectionanti-pattern/&http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/もう1つの注意点として、私はSRPは1つのことをするクラスを持っているわけではありませんが、ビジネスの観点から変える理由が1つあります。 – GetFuzzy

0

コンストラクタのパラメータを1つのクラスに結合するかどうかを確認することもできます(パラメータがクラスとして意味をなさないと仮定して)。

依存関係の一部に対してServiceLocatorパターンを使用して調べることもできます。これは、依存関係を長いコンストラクタチェーンに渡す必要がある場合に特に当てはまります。

+4

サービスロケータパターンは、Dependency Injectionの原則に反したものです。 Service LocatorはDemeterの法則に違反しています:http://www.youtube.com/watch?v=RlfLCWKxHJ0 – Runcible

+0

非常に素晴らしいビデオ、Runcible。 DI、IOC、サービスロケータの説明は非常に分かりやすい。 – Alexanderius

3

ランチャー、

ここはCastle Windsorプロジェクトへのリンクです。それはInversion of Controlコンテナです。これらのコンテナは、ファクトリクラスが依存関係をまとめてコンストラクタに単一のオブジェクトとして注入することを許可します。

http://www.castleproject.org/container/index.html

私はウィンザーについて良いことを聞いたことがあります。 SpringもIoCコンテナを作成し、there are othersを作成します。

9

私はそれについて心配しません。

代わりに、クラスが複雑すぎるのではないかと心配します。

多くの依存関係を持つクラスで、すべてを使用しますが、ループやif文は問題ありません。私が最近取り組んでいるいくつかのコードでは、クラス内に約14の依存関係がありました。しかし、コードには1つのパスしかなく、依存関係をより良いクラスにグループ化する論理的な方法はありませんでした。

多くの分岐ステートメントまたは複雑なループ条件を含む少数の依存関係を持つクラスは、単純化する必要があります。

1

6-10の依存関係を持つクラスは、コードの匂いです。クラスがSingle Responsibility Principleに違反していることが明らかです。

これらの依存性を減らすために使用する戦略はありますか?

Mark Seemannは、彼の書籍Dependency Injection in .NETの投稿Refactoring to Aggregate Servicesとmoresoでこの作業を明確にしました。あなたのクラスが非常に多くの依存関係を持っているという事実は、クラス内に複数の責任があることを示しています。しばしば暗黙のドメインコンセプトが明示的にになるのを待って、それを特定してそれをそれ自身のサービスにすることによって待つ。一般的に言えば、ほとんどのクラスは4-5個以上の依存関係を必要としません。

関連する問題