8

プロジェクトで依存性注入を均一に使用するための協調的な取り組みを始めたところですが、問題が発生しました。

MongoDB クエリを処理するクラスを作成しています。問題なく、MongoClient をコンストラクターへの依存関係として渡します。しかし、オブジェクトのインスタンス化に必要な変数がインスタンス化の時点で使用できない場合、依存関係をどのように処理すればよいでしょうか?

特に、MongoCollection メソッド findOne のラッパーがあります。これは、文字列を渡すと、現在 (古いコードでは) その文字列を "new MongoId($_id)" を持つ MongoId に変換し、それを検索機能。

依存性注入について学んだことから、「新しい MongoId」を持つことは悪い考えであり、文字列を MongoId に変換する関数のテスト ケースを作成するのが難しくなることは既にわかっています。

しかし、MongoId クラスがコンストラクターで id 文字列を取得する場合、どのようにインジェクションを処理すればよいでしょうか?

私が考えた唯一のことは、次のようなことを行うクラス コンストラクターにクロージャーを渡すことです。

$getMongoId = function( $id ){
    return new MongoId( $id );
};

class MyMongo
{
   function __construct( MongoClient $client, Closure $mongoIdGetter){...}
}

[この最後の部分を修正するために編集]

しかし、これはそれを処理する正しい方法ですか?もちろん、DiC を使用している場合はそれを行うことができますが、コンストラクターのクロージャーを必要とするのは少し難しいようです。依存関係を注入することについて独断的すぎますか? 新しいクラスで「new MongoId($_id)」を使用することで、これを簡単に修正できると思います。

4

2 に答える 2

2

クロージャーの代わりに、Factory を使用できます。

class MongoFactory
{
    public function createMongoDb($id)
    {
        return new MongoId($id);
    }
}

ファクトリでは、オブジェクトの作成が唯一の目的であり、それらを別のファクトリに簡単に置き換えることができるため、「新しい何か」のハードコードされた依存関係を持つことは問題ないと見なされます。

これで、コンシューマー クラス ( MyMongo) は (または必要に応じてそのインターフェイス) に依存するようMongoFactoryになり、簡単に「注入」できます。

于 2013-01-21T22:14:02.830 に答える
1

しかし、オブジェクトをインスタンス化するために必要な変数がインスタンス化時に使用できない場合、どのように依存関係を処理しますか?

PHPは、自分で処理する前に致命的なエラーになります。型パラメーターを使用する場合、および/またはそれらをデフォルトとして定義しないnull場合、そのパラメーターがどの関数にも渡されない場合、PHPは致命的なエラーを発生させます。

依存性注入について学んだことから、「新しいMongoId」を使用することは悪い考えであり、文字列をMongoIdに変換する関数のテストケースを作成するのが難しくなることはすでにわかっています。

(PHPUnitで)それはありますか?

$this->assertInstanceOf('\MongoId', $getMongoId($id_string));

しかし、MongoIdクラスがコンストラクターでid文字列を受け取る場合、どのようにインジェクションを処理しますか?

それが何を意味するのかわからないが、MongoIds処理の結果のみをテストする必要があります。

あなたの質問の最後のビットは私を少し緩めます、それは本当のPHP(すなわち$__construct)ではないからだと思います。

なぜそのような関数をクラスに押し込む必要があるのか​​わかりません。私が最もよく持っているのは:

function findById($id){
    if(!$id instanceof \MongoId) $id = new MongoId($id);
    return $this->getCollection()->findOne($id);
}

それ以上のものは必要ありません。コンストラクターMongoIdはすでにユニットテストされているため、コンストラクターをテストする必要はありません。代わりに、他の誰かではなく、自分のパブリックAPIをユニットテストする必要があります。

于 2013-01-21T21:48:27.113 に答える