web-dev-qa-db-ja.com

依存性注入とクラス内インスタンス化|実用的な制限

依存関係の逆転は良い

依存関係の逆転は良いです、それは:

  • 単体テストを簡素化
  • カップリングを減らし、ソフトウェアコンポーネントを互換的に使用できるようにします
  • 特定のオブジェクトのインスタンス化ロジックをより少ない場所に保持し、コードの繰り返しを防ぎます。

これらの理由により、クラス内でオブジェクトをインスタンス化することは避けています。代わりに、依存関係としてファクトリクラスを渡すことを好みます。ただし、オブジェクトの種類によってはこれが過剰かどうか疑問に思っています。

値オブジェクトは例外ですか?

値オブジェクトは、定義により、単純な構造を持つ単純なオブジェクトです。

私の経験では、インスタンス化ロジックに複雑さはほとんどありません。値オブジェクトは他のデータ型と見なすことができるため、ユニットテストは危険にさらされず、すべてのクラスは何らかの説明のデータ型に依存する必要があるため、結合は問題ではありません(警告、My Concernを参照)。

コレクションオブジェクトも?

関連する特別なケースは、コレクションオブジェクトのケースです。

私の意見では、値オブジェクトのようなコレクションオブジェクトは、実際のインスタンス化を必要としないということです。実際には、特殊な形式の配列です。値オブジェクト。

例:

class PencilCase
{

  private $pencils=[];

  public function construct() 
  {
   // blah blah
  }

  public function emptyPencils()
  {
    $pencils = $this->pencils;
    $this->pencils = [];

    return new PencilsCollection($pencils);
  }
}


class PencilsCollection implements \Traversable
{
  public function __construct($pencils=[])
  {
    // blah blah
  }
}

私の懸念

使用されているデータ型の一部を提供しているパッケージを変更したい場合があるため、一般にこのタイプの結合を回避しました。上記の例では、Dixonによって提供される値オブジェクトを使用していて、Staedtlerによって提供される値オブジェクトに変更する場合があります。

このタイプのリファクタリングは高価になる可能性があります。

質問

ファクトリーと注入された依存関係を持つ値とコレクションオブジェクトをインスタンス化する必要がありますか、それともクラス内でインスタンス化する必要がありますか?

4
Marvin

ファクトリーで値とコレクションオブジェクトをインスタンス化する必要があります[..]。

いいえ、通常、値オブジェクトの作成は非常に簡単で、ファクトリーは必要ありません。

ほとんどの場合、値オブジェクトと必要な依存関係をインスタンス化する Money :: fromString() のような、ある種の静的コンストラクタを使用します。

[..]注入された依存関係、またはクラス内でインスタンス化する必要があります

ユースケースによって異なります。前述のMoneyを使い続けましょう-ちょうど金額があり、Currencyが別のソースから取得されるユースケースがある場合があります。そのような場合-CurrencyMoneyコンストラクターに整数で注入します。

また、通貨コード付きの金額を含む文字列があり、Money::fromStringを使用して、内部でCurrencyインスタンスを作成する場合もあります。

同じことがコレクションにも当てはまります。検証が必要な値オブジェクトの配列よりも特定のインターフェイスを期待する方が簡単だからといって、一部のコレクションがクラス内でインスタンス化されてから注入されるという状況になります。

2
potfur