3

私は依存性注入について読んでいますが、私が見つけた例は私には悪いコードのように見えます.より良い例はありますか?

class Photo {
   protected $db;
   public function __construct()
   {
      $this->db = DB::getInstance();
   }
}

したがって、これは悪いコードであり、すべての変数を明示的に設定すると多数のセッターが作成される可能性があるため、依存性注入の提案は次のとおりです。

class Container {
   protected $db;
   public static newPhoto()
   {
      $photo = new Photo;
      $photo->setDB(static::$db);
      $photo->setConfig();
      $photo->setResponse();
      return $photo;
   }
}
$photo = Container::newPhoto();

しかし、間違っている場合は訂正してください。別のクラスを構築することが唯一の責任であるクラスを構築したばかりで、まったく無意味に思えます。明らかに非常に悪い考えである静的メソッドを使用しています。

私が目にする利点の 1 つは、驚くべきことに言及されていないことですが、最初の例ではテストできませんでしたが、setter を使用して Photo クラスを個別にテストできるようになったことです。

このようなものは私にとってより理にかなっています:

class Photo {
   protected $db;
   protected $config;
   protected $response;
   public function __construct($dbConn=null,$config='123',$response=true)
   {
      if(is_null($dbConn))
          $this->db = DB::getInstance();
      else
          $this->db = $dbConn;
      ...etc
   }
}
$photo = new Photo($dbConn);

クラスはそれ自体を構築します。静的メソッドを実際に呼び出す必要はありません。値が使用されている場合、クラスはダミー データでテストできます。コンテナとは対照的に、依存関係はまだいくらか明白です。

4

2 に答える 2

2

依存性注入パターンの目標は、連携して動作するオブジェクトの構築方法を分離することです。あなたの例では、DB インスタンスを構築する方法を知ることは Photo クラスの関心事ではなく、DB インスタンスを使用してその目標を達成することだけです。

既に気づいた明らかな利点は、Photo 機能のみをテストする場合にモック DB インスタンスを簡単に渡すことができるテストです。ただし、たとえばコンテナに DB インスタンスのプールがあり、そのうちの 1 つを Photo オブジェクトに渡して作業を行う接続プーリングについても考えることができます。Photo ライフサイクルが終了すると、DB インスタンスはプールに返され、別の場所で使用されます。

このパターンの実装は、コンストラクターと引数、セッター、注釈 (少なくとも Java では)、さらには XML 構成ファイルを使用して実現できます。注釈または XML 構成ファイルの場合、コンテナーはその情報を解析して、必要な適切なオブジェクトを作成し、それらをクライアント クラスに挿入します。

C1 と C2 で説明しているのは、Photo インスタンスを取得するための静的メソッドを公開するファクトリ クラスです。これは、Java の多くの場所で使用される非常に一般的なパターンです。

于 2013-01-18T21:27:47.567 に答える
1

あなたが DI についてどこに頼ったのかはわかりませんが、リソースは非常に疑わしいようです。代わりに、まずこの講義を見てから、Martin Fowlerの記事を読んでください。たぶん、この短いビデオで補足されます。

class Container {
   protected $db;
   public static newPhoto()
   {
      $photo = new Photo;
      $photo->setDB(static::$db);
      $photo->setConfig();
      $photo->setResponse();
      return $photo;
   }
}
$photo = Container::newPhoto();

これは依存性注入を実装していません。実際には、実装が不十分な静的ファクトリ メソッド (アンチ) パターンの例にすぎません。特に魔法のメソッド$photo->setConfig()$photo->setResponse()、明らかに何らかの機能を果たしますが、パラメーターを受け取りません。

そして、このコードがあります:

class Photo {
   protected $db;
   protected $config;
   protected $response;
   public function __construct($dbConn=null,$config='123',$response=true)
   {
      if(is_null($dbConn))
          $this->db = DB::getInstance();
      else
          $this->db = $dbConn;
      ...etc
   }
}
$photo = new Photo($dbConn);

値を割り当てるだけでなく、その依存関係を非表示にし、値が提供されていない場合はグローバル スコープから取得することにします。そしてもちろん、コンストラクターにはかなりの計算ログが含まれることになります。したがって、テスト不可能になります。

ああ..そして、魔法のブール値があります。そのようなパラメーターがコンストラクターのクラスに割り当てられている場所はいつでも、同じインターフェイスを実装する 2 つの異なるクラスが実際に必要だったことを明確に示しています。

だから..あなたの質問に答えるには:

私は依存性注入について読んでいますが、私が見つけた例は私には悪いコードのように見えます.より良い例はありますか?

いいえ、あなたの例は良くありません。単一のクラス定義で、前のコード例の両方から最悪の部分を組み合わせただけです。

于 2013-01-18T22:51:13.470 に答える