14

この問題は、例でよりよく説明されています。Javascript (実際には構文上の目的で Coffeescript) を使用しますが、Javascript は別のLISPにすぎないからですよね?

それで、(明らかに) ajax リクエストを行う Web アプリを書いているとします。それを処理する関数を実装します。

ajaxRequest = (url, params, callback) ->
    # implementation goes here

ここで、サーバーからデータを取得するグリッドがあるとします。私のコードのどこかで、次のようなことをしなければなりません:

userGrid.onMustFetch = ->
    ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
        # fill grid with data

ここでの問題は正確には何ですか?onMustFetchの実装をテストしたい場合、onMustFetch内で依存関係が呼び出され、テスト環境が依存関係を制御できないため、テストできません。

この問題を解決するために、テストする関数に依存関係を挿入します。つまり、onMustFetchを次のように変更します。

userGrid.onMustFetch = (ajaxRequest) ->
    ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
        # fill grid with data

これで、テスト コードは ajaxRequest のモックをonMustFetch渡し、動作を正常にテストできるようになりました。

ワンダーバーですよね?違う!これは、 ajaxRequest の適切なインスタンスをonMustFetchの適切なインスタンスにバインドしなければならないという問題です

Java のような言語では、依存性注入フレームワークを使用してこれを行うことができ、私のコードは次のようになります。

class UserGrid {

    private AjaxService ajaxService;

    @Inject
    public UserGrid(AjaxService ajaxService) {
        this.ajaxService = ajaxService;
    }

    public void onMustFetch() {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("surname", "MacGyver");
        ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
            // fill grid with data
        });
    }

}

気味が悪い、私は知っています...しかし、実際にはDIフレームワークがすべての配線を行うので、少なくとも問題のその部分は簡単です.

ここで、Web アプリと Javascript に戻ります。適切なajaxRequest参照を使用して常にonMustFetchを正常に呼び出すことができたとしても(結局のところ、この場合はそれほど難しくありません)、もっと簡単な方法があるはずです。コードが大きくなると、依存関係が増加します。ajaxRequestの参照を渡すことは想像できますが、securityServicebrowserServiceeventBusServiceなどがある場合はどうでしょうか?

ここで本当の質問です: Lisp のような言語は依存関係を管理するというこの問題をどのように解決しますか? (依存関係はアプリケーション全体に渡され続ける必要があるように思えますが、もっと良い方法があるはずです...)

4

2 に答える 2

6

これは通常、クロージャ/カリー化を使用して行われます。依存関係をパラメーターとして渡します。JSでは次のことができます。

buildUserGrid = function(dependency){
    return {
        onMustFetch = function(){
            depenency.doSomething();
        },
        doSomethingElse = function(){
            dependency.doSomethingElse();
        }
    }
}

var userGrid = buildUserGrid(ajaxRequest);
userGrid.onMustFetch();
于 2012-09-17T06:28:20.543 に答える
1

Javascript では、OO 言語と同様の手法を使用できない理由がわかりません。JS での非常に基本的な実装 (申し訳ありませんが、私は Coffescript を知りません)

// expects a function 
var UserGrid = function(ajaxService) {
    this.dependencies = ["ajaxService"];
     // will be overwritten by the DI service, but can also be 
     // assigned manually as in java
    this.ajaxService = ajaxService;
};
UserGrid.prototype.onMustFetch=function() {
    var callback = function() { ... }
    this.ajaxService('/fetch/users',{ surname: 'MacGyver' }, callback);
};

var diController = {
    create: function(constr) {
        var obj = new constr();
        // just look at obj.dependencies to see what should be assigned, and map
        // the implemenations as properties of obj. this could be
        // as simple as a switch or a direct mapping of names to object types
        // ... assign implementations to obj
        return obj;
    }
};

作成:

var userGrid = diController.create(UserGrid);

JavadiController依存性インジェクターと同じことを行います。Java では、リフレクションを使用して必要なオブジェクトのタイプを把握できます。Javascript で行わなければならないリフレクションはあまりないので、何が必要かをシステムに伝える規則を作成します。この場合、「依存関係」と呼ばれる配列を使用しましたが、好きな構成を使用できます。

于 2012-04-17T20:01:47.183 に答える