16

私は現在難問に直面しています: 2 つの JavaScript オブジェクトを結び付ける正しい方法は何ですか?

いくつかの異なるファイルを持つテキスト エディターのようなアプリケーションを想像してみてください。ノートブックのビューを表す HTML ページがあります。NotebookController と Notebook View のクラス定義を含むファイル notebook.js があります。

「ノートブックの保存」、「ノートブックの読み込み」、「新しいノートブック」など、ノートブックでのビジネス ロジックの実行を担当する NotebookController オブジェクト。NotebookView は、プレゼンテーションに使用される HTML の管理を担当します。「ノートブック本体の取得/設定」「ノートブック名の取得/設定」などの低レベルの処理を行います。また、DOM イベント (onClick) をリッスンし、ビジネス イベント (saveNotebook) を起動します。これは、パッシブ ビュー パターンでの私の試みです。

JavaScript のクライアント側コードを、オブジェクト指向で、懸念事項を分離し、単体テストできるようにしたいと考えています。モック NotebookView を使用して NotebookController をテストしたい、またはその逆を行いたい。つまり、NotebookController 内で NotebookView をインスタンス化することはできません。私もそうです

  • 2つを結び付けるロジックをnotebook.jsに入れます
  • それぞれの 1 つをインスタンス化し、それらを一緒に配線することを知っているアプリケーションにグローバル関数を用意する
  • 自家製のものか SquirrelIoc のような依存性注入を使用します。

Java では、Spring を使用するという自然な選択があります。しかし、それはあまり JavaScript 風ではないようです。どうするのが正解?

4

6 に答える 6

3

依存性注入はおそらくあなたの最善の策です。Javaと比較すると、コールバックでいっぱいのオブジェクトをNotebookControllerに渡すことができるため、JSコードでこれを行うのが簡単です。他の側面は、それらの間のインターフェースを形式化するための静的コード分析がないため、より困難です。

于 2009-03-06T20:03:45.710 に答える
3

洞察をありがとう。最終的に、単純な JavaScript 依存性注入ユーティリティを作成しました。しばらく議論した後、あなたのコメントの結果、DI が本当に正しい答えであることがわかりました。理由は次のとおりです。

  1. 配線ロジックを配線対象の近くに保ちながら、配線の問題をビジネスロジックから完全に分離しました。
  2. これにより、オブジェクトに「すべて接続済み」コールバックを一般的に提供できるようになり、3 フェーズの初期化を実行できるようになりました。
  3. 依存関係の欠落の問題を簡単に確認できました。

DIユーティリティは次のとおりです。

var Dependency = function(_name, _instance, _dependencyMap) {
    this.name = _name;
    this.instance = _instance;
    this.dependencyMap = _dependencyMap;
}

Dependency.prototype.toString = function() {
    return this.name;
}

CONCORD.dependencyinjection = {};

CONCORD.dependencyinjection.Context = function() {
    this.registry = {};
}

CONCORD.dependencyinjection.Context.prototype = {
    register : function(name, instance, dependencyMap) {
        this.registry[name] = new Dependency(name, instance, dependencyMap);
    }, 
    get : function(name) {
        var dependency = this.registry[name];
        return dependency != null ? dependency.instance : null;
    },

    init : function() {
        YAHOO.log("Initializing Dependency Injection","info","CONCORD.dependencyinjection.Context");
        var registryKey;
        var dependencyKey;
        var dependency;
        var afterDependenciesSet = [];
        for (registryKey in this.registry) {
            dependency = this.registry[registryKey];
            YAHOO.log("Initializing " + dependency.name,"debug","CONCORD.dependencyinjection.Context");

            for(dependencyKey in dependency.dependencyMap) {
                var name = dependency.dependencyMap[dependencyKey];
                var instance = this.get(name);
                if(instance == null) {
                    throw "Unsatisfied Dependency: "+dependency+"."+dependencyKey+" could not find instance for "+name;
                }
                dependency.instance[dependencyKey] = instance; 
            }

            if(typeof dependency.instance['afterDependenciesSet'] != 'undefined') {
                afterDependenciesSet.push(dependency);
            }
        }

        var i;
        for(i = 0; i < afterDependenciesSet.length; i++) {
            afterDependenciesSet[i].instance.afterDependenciesSet();
        }
    }

}
于 2009-03-06T23:35:37.277 に答える
2

私は、それらを一緒に配線するだけです:

function wireTogether() {
  var v = new View();
  var c = new Controller();
  c.setView(v);
}

しかし、もちろん、別の質問が発生します。wireTogether() 関数をどのようにテストしますか?

幸いなことに、JavaScript は非常に動的な言語であるため、View と Controller に新しい値を割り当てることができます。

var ok = false;

View.prototype.isOurMock = true;
Controller.prototype.setView = function(v) {
  ok = v.isOurMock;
}

wireTogether();

alert( ok ? "Test passed" : "Test failed" );
于 2009-03-06T19:54:30.130 に答える
1

JavaScript 用のコントロール ライブラリの反転がありますが、かなり満足しています。 https://github.com/fschwiet/jsfioc . イベントにも対応しているので、スタートアップイベントがしたい場合でも大丈夫です。より多くのドキュメントを使用できます...

http://github.com/fschwiet/jsfioc

もう 1 つの (より新しい?) オプションは、requireJS (http://requirejs.org/) です。

于 2011-01-06T18:15:40.970 に答える
1

JavaScript の依存性注入のフレームワークもあります: https://github.com/briancavalier/wire

于 2011-12-30T13:37:04.537 に答える
0

これを試してみますが、実際のコードを見ないと少し難しいでしょう。個人的には、(M)VC で JavaScript や IC を使ってそのような特定の試みを行っている人を見たことがありません。

まず、何をテストしますか?まだ行っていない場合は、JavaScript を使用した単体テストに関する優れた情報が含まれているYUI Test ビデオをチェックしてください。

第二に、「その集約を接続する最良の方法」と言うとき、私はおそらくコントローラーを使用してセッターとしてそれを行うでしょう

// Production
var cont = new NotebookController();
cont.setView( new NotebookView() );

// Testing the View
var cont = new NotebookController();
cont.setView( new MockNotebookView() );

// Testing the Controller
var cont = new MockNotebookController();
cont.setView( new NotebookView() );

// Testing both
var cont = new MockNotebookController();
cont.setView( new MockNotebookView() );

しかし、これは、コントローラーとビュー オブジェクトを既にどのように設計したかについて、いくつかの大きな前提を置いています。

于 2009-03-06T19:21:34.313 に答える