2009-03-06 11 views
16

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

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

"Notebookを保存する"、 "Notebookをロードする"、 "New Notebook"などのノートブックでビジネスロジックを実行するNotebookControlerオブジェクト。 NotebookViewは、プレゼンテーションに使用されるHTMLを管理します。それは、 "get/set notebook body" "get/set notebook name"のような低レベルのものです。また、DOMイベント(onClick)を待ち受け、ビジネスイベント(saveNotebook)を起動します。これはパッシブビューパターンでの私の試みです。

javascriptのクライアントサイドコードをオブジェクト指向、分離した懸念事項、ユニットテスト可能にします。私はNotebookViewを使ってNotebookControllerをテストしたいと思っています。つまり、NotebookController内でNotebookViewをインスタンス化することはできません。だから私

  • が一緒に2
  • がそれぞれのいずれかをインスタンス化し、それらを配線することを知っている私のアプリケーションのグローバル機能を持​​っていることを、ワイヤ私のnotebook.jsにいくつかのロジックを入れてください一緒に
  • 使用依存性注入、自家製のものかSquirrelIocのようなもの

Javaでは、選択肢は自然なものです:Springを使用します。しかし、それはJavaScript-yとは思えません。何が正しいのですか?

+0

たぶん私は何かが足りないんだけど、あなただけのあなたが代わりに組成物の凝集を使用していることによって、テスト容易性を達成することはできませんか? –

+0

それは考えです。しかし、問題は本当にオブジェクトの集約を結ぶ正しい方法は何ですか? –

答えて

0

私はこれで刺すようにしようとしますが、実際のコードを見ることなく少し難しくなります。個人的には、JavaScriptやIoCで(M)VCでこのような具体的な試みを行ったことはありませんでした。

まず、何をテストしますか?あなたがまだ持っていない場合は、YUI Test videoをチェックしてください。これには、javascriptを使った単体テストに関する良い情報があります。あなたは「その凝集をアップ配線するための最良の方法」を言うとき

は第二に、私はおそらくちょうどコントローラ/

// 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()); 

ワットセッターとしてそれを行うだろう。しかし、これは、あなたがきたどのようにいくつかの大きな仮定を作りますあなたのコントローラを設計し、既にオブジェクトを表示する。

2

私はそれらを一緒に配線し、言う:

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

しかし、その後の進路別の質問は提起 - どのようにwireTogether()関数をテストするのですか?

あなただけ見ると、コントローラに新しい値に割り当てることができるように幸運なことに、JavaScriptは、本当に動的言語である:

var ok = false; 

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

wireTogether(); 

alert(ok ? "Test passed" : "Test failed"); 
3

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

3

洞察のためにありがとう。私は単純なJavaScript依存性注入ユーティリティを書いた。有線されているものに近い配線ロジックを維持しながら、それは完全にビジネスロジックからの配線の懸念を分離

  1. :しばらくして、コメントを議論した後、ので、DIは本当に正解だったと私に発生しました。
  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(); 
     } 
    } 

} 
1

私はjavascriptのための制御ライブラリの反転を持って、私はかなりそれに満足しています。 https://github.com/fschwiet/jsfioc。また、イベントをサポートしているので、スタートアップイベントがうまくいけばいいです。それは

http://github.com/fschwiet/jsfioc

...優れたドキュメントとサポートを持っている別の(新しい?)オプションを、より多くのドキュメントを使用することができ、requireJS(http://requirejs.org/)です。