依存性注入:どの時点で新しいオブジェクトを作成できますか?


13

私はPHPアプリケーションをリファクタリングしていますが、可能な限り多くの依存性注入(DI)をしようとしています。

私はそれがどのように機能するかをよく理解しているように感じますし、クラスがかなりスリムで堅牢になっているのを確かに見ることができます。

クラス内に新しいオブジェクトを作成するのではなく依存関係を注入できるようにリファクタリングしていますが、ある時点でいくつかのオブジェクトを作成する必要があります。つまり、dreaded newキーワードを使用します。

私が今直面している問題は、どの時点で実際に新しいオブジェクトを作成できるかということです。私は最終的にトップレベルのクラスになり、他に行く場所がないため、新しいオブジェクトを大量に作成するように見えます。これは間違っているように感じます。

ファクトリクラスを使用してすべてのオブジェクトを作成するブログを読んだ後、ファクトリを他のクラスに注入します。その後、ファクトリメソッドを呼び出すと、ファクトリが新しいオブジェクトを作成します。

これを行うことに対する私の懸念は、今では私のファクトリークラスがnewすべて自由になることです!ファクトリクラスであるため、これで問題ないかもしれませんが、ファクトリパターンとDIを使用する場合に固執するいくつかのルールはありますか、それともここから外れますか?



サービスとポリシーにはIoCをお勧めします。モデルまたはヘルパークラスには、単に使用しますnew。もちろん、IoCコンテナを呼び出す必要があるエントリポイントがいくつかありますが、多くはないはずです。通常、IoCを1回構成してから、リクエストごとに1つのクラスを解決するよう要求します。MVCの場合、通常はコントローラーです。
CodesInChaos

あなたが言及するトップレベルのクラスは、コンポジションルートの一部です。間違いとは程遠い。
顔面比

回答:


12

これについてかなりの時間をかけてグーグルで回った後、(上記のコメントで述べたように)私が話していたトップレベルのクラスはComposition Rootと呼ばれるようです。

実際、このコンポジションルート内のすべてのオブジェクトの作成を追加する(または、ここからIoCコンテナーを参照する)ことは、受け入れられているソリューションのようです。

これに関する私の最初の懸念は、このトップレベルのクラスが少し混乱することになるということでした。これはある程度真実ですが、長所は短所よりも重要です。たとえば、他のすべてのクラスの可読性、テスト容易性、保守性が向上していることがわかります。

トップレベルのクラスには、が散らばっビット厄介であってもよいnewset_property()私は、私は実際に他のクラスを超えるすべての散らばっのではなく、一箇所にすべてこのコードを持つ好む言わなければなりません

このメソッドのパフォーマンスヒットについて説明する別の便利なページはこちら


1
+1「Composition Root」について聞いたことがないので。
c_maker

2

Factoryクラスがnew全体に散りばめられます。それは、あなたが要求しているオブジェクトを作成し、おそらくそのオブジェクトの依存関係を作成します。ファクトリーの仕事はnew、このクラスに適切なオブジェクトをインスタンス化することであるため、悪いことではありません。

DIにより、疎結合設計が可能になります。各オブジェクトに提供される依存関係を変更することにより、アプリケーションに変更を加えることができます。アプリケーションの柔軟性、拡張性、およびテストの容易さを実現します。

最上位レベルには、いくつかの工場をインスタンス化し、サービスへの接続を設定し、応答を送信するコードがあります。newアプリケーションに必要なオブジェクトをインスタンス化するために、かなりの量または静的な呼び出しが行われます。それが属する場所です。


-2

ここに私の2セント:

私はPHPアプリケーションをリファクタリングしていますが、可能な限り多くの依存関係を注入しようとしています

依存性注入フレームワークを使用しているかどうかは述べません。絶対にすべきだと思う。:あなたが必要な機能を提供します何か使用/programming/9348376/guice-like-dependency-injection-frameworks-in-php

私が今直面している問題は、どの時点で実際に新しいオブジェクトを作成できるかということです。最終的にはトップレベルのクラスになり、他に行く場所がないため、新しいオブジェクトを大量に作成するように見えます。これは間違っているように感じます。

通常、アプリケーションを構成する初期オブジェクトのインスタンス化には、構成または中心点を使用します。コンテナがオブジェクトを作成します。

次に、IoCコンテナーを介してオブジェクト(サービス、プロバイダー、コントローラーなど)にアクセスします。必要に応じて透過的にオブジェクトを作成するか、適切な既存のインスタンスへの参照を提供します。

もちろん、オブジェクトの特定の実装内では、DIを必要としない他のオブジェクト(データ構造、カスタムタイプなど)をインスタンス化できますが、それは通常のプログラミングです。

ファクトリクラスを使用してすべてのオブジェクトを作成するブログを読んだ後、ファクトリを他のクラスに注入します。その後、ファクトリメソッドを呼び出すと、ファクトリが新しいオブジェクトを作成します。

通常、IoCフレームワークでファクトリを介してIoCオブジェクトをインスタンス化する場合は、Factoryを使用します(特定のオブジェクトをインスタンス化するには追加の作業が必要な場合に必要です)。「new Object()」を使用してオブジェクトを作成し、いくつかのプロパティを設定できる場合は、必ずしもFactoryパターンを使用する必要はありません。

言い換えれば、クラスまたはクラスのグループにファクトリパターンを使用することは、DIを使用するかどうかではなく、それらのクラスをモデル化する方法に依存すると言います(DI実装が明示的にファクトリを必要とする場合を除きます)。

また、すでにFactoryの使用を必要とするサードパーティのライブラリを使用している場合、IoCフレームワークを設定してFactoryを使用します。この場合、これについて制御することはできず、IoCコンテナに伝える必要があります。「ねえ、これらのインターフェイスの1つを要求するときは、このファクトリを使用して適切なインスタンスを提供する必要があります」。

これを行うことに対する私の懸念は、今では私のファクトリークラスが新しいすべての自由になることです!ファクトリークラスなのでこれは大丈夫かもしれませんが、ファクトリーパターンとDIを使用するときに固執するいくつかのルールがありますか、それともここから外れていますか?

この場合、これらのオブジェクト/サービス/コントローラーなどにFactoryパターンを使用する必要はないと思われます。適切なクラスを「新しい」インスタンス化し、他のすべてを注入するようにIoCを設定するだけです。

役に立てば幸いです。


答えてくれましたが、確かにIoCコンテナは私が参照していた「トップレベルクラス」です。そこにオブジェクトしか作成できない場合、それは適切な混乱になります。
Gaz_Edge

4
doing DI manually beats the whole purpose of using an Inversion of Control container- それが「...構成ファイルに依存関係を集中化することを意味する場合、それは正しいです。なぜなら、それはすべてIoCコンテナが本当にしているからです。DIの本当の目標はデカップリングであり、コンストラクターメソッドで依存関係を提供することでそれを行うことができます。そのためにDIフレームワークはまったく必要ありません。
ロバートハーベイ

うーん、オブジェクトを作成せず、IoCコンテナーに(必要な場所から)要求するか、フィールド/引数注入を使用して、常にIoCコンテナーによって作成された適切なクラスが自動的に注入されるようにします。
jjmontes

1
非常に大規模なアプリケーションはフレームワークが必要であることに同意します。多くのアプリケーションはそれほど大きくなく、DIフレームワークを使用することで複雑さが増すというメリットもありません。
ロバートハーベイ

2
そうだとは言わなかった。私は単にあなたがそれをするためにDIコンテナを必要としないと言った。
ロバートハーベイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.