1

モデルに依存関係を注入するためのベスト プラクティスは何ですか? 特に、 getter が のように非同期の場合はどうなるmongodb.getCollection()でしょうか?

ポイントは、依存関係を一度注入することです

var model = require('./model')({dep1: foo, dep2: bar});

引数として渡す必要なく、すべてのメンバー メソッドを呼び出します。また、非同期ゲッターのウォーターフォールで各メソッドを開始する必要もありません。

最終的に、すべての呼び出しをプロキシし、非同期の依存関係を渡す専用のexportsラッパーになりました。

ただし、これにより多くのオーバーヘッドが発生し、多くの繰り返しが発生するため、一般的には好きではありません。

var Entity = require('./entity');

function findById(id, callback, collection) {
    // ...
    // callback(null, Entity(...));
};

module.exports = function(di) {
    function getCollection(callback) {
        di.database.collection('users', callback);
    };

    return {
        findById: function(id, callback) {
            getCollection(function(err, collection) {
                findById(id, callback, collection);
            });
        },
        // ... more methods, all expecting `collection`
    };
};

依存関係、特に非同期ゲッターを注入するためのベスト プラクティスは何ですか?

4

2 に答える 2

6

単体テストをサポートする必要がある場合、javascript のような動的言語での依存性注入は、おそらく価値があるよりも面倒です。他のモジュールから必要とするモジュールは、Java、.NET、およびその他の静的にコンパイルされた言語で見られる DI のパターンを使用する可能性がほとんどないことに注意してください。

テスト用にコードの特定のユニットを分離するために動作をモックアウトする場合は、「sinon」モジュールhttp://sinonjs.org/を参照してください。メソッド呼び出しをスパイしたり、完全に置き換えたりできるインターセプターのイン/アウトを動的にスワップできます。実際には、モジュールが必要な場所で mocha テストを作成し、コードで利用されるモジュールを必要とします。sinon を使用してそのモジュールのメソッドをスパイまたはスタブすると、コードを分離できます。

サード パーティのコードを sinon で完全に分離できなかったシナリオが 1 つあります。これは、モジュールを require() する行為が、テストで実行したくない動作を実行する場合です。そのシナリオのために、実際のモジュールの代わりに必要なインライン モックを提供できる「mockrequire」 https://github.com/mateodelnorte/mockrequireという非常にシンプルなモジュールを作成しました。sinon のスパイまたはスタブを使用するモックを提供し、残りのすべてのテストと同じ構文とパターンを使用できます。

うまくいけば、これはあなたの投稿の根底にある質問に答えます. ;)

于 2012-09-29T22:41:20.430 に答える
2

非常に単純な状況では、ファイル スコープ内のオブジェクトを変更して実際のエクスポート オブジェクトを返す関数を単純にエクスポートできますが、より可変的に注入する場合 (つまり、アプリから複数回使用する場合) は、一般に、あなたがしたようなラッパーオブジェクト。

オブジェクトを返す関数の代わりにラッパー クラスを使用することで、状況によってはオーバーヘッドとインデントを減らすことができます。

例えば

function findById(id, callback, collection) {
  // ...
  // callback(null, Entity(...));
};

function Wrapper(di) {
  this.di = di;
}
module.exports = Wrapper; // or do 'new' usage in a function if preferred

Wrapper.prototype.findById = function (id, callback) {
  // use this.di to call findById and getCollection
}, // etc

それ以外は、物事を改善するためにできることはそれほど多くありません。私はこのアプローチが好きです。状態diを明示的に保ち、findById の関数本体から分離し、クラスを使用することで、インデントのネストを少なくとも少し減らします。

于 2012-09-29T12:29:38.650 に答える