2009-03-06 19 views
16

Mam obecnie do czynienia z zagadką: Jaki jest właściwy sposób połączenia ze sobą 2 obiektów javascript?Jaki jest właściwy sposób łączenia ze sobą 2 obiektów javascript?

Wyobraź sobie aplikację, taką jak edytor tekstu z kilkoma różnymi plikami. Mam trochę strony HTML reprezentującej widok dla notebooka. Mam plik notes.js zawierający definicje klas dla produktu NotebookController i widoku notatnika.

Obiekt NotebookControler odpowiedzialny za prowadzenie logiki biznesowej na notebooku w stylu "Zapisz notatnik", "Załaduj notatnik", "Nowy notatnik". NotebookView jest odpowiedzialny za zarządzanie HTML, który jest używany do prezentacji. Robi rzeczy niskiego poziomu, takie jak "pobierz/ustaw notatniki" "pobierz/ustaw nazwę notatnika". Wysłuchuje również zdarzeń DOM (onClick) i uruchamia zdarzenia biznesowe (saveNotebook). To jest moja próba wzoru pasywnego widoku.

Chcę, aby mój kod po stronie klienta javascript był zorientowany obiektowo, osobno i testowany. Chcę przetestować program NotebookController za pomocą pozorowanego programu NotebookView i na odwrót. Oznacza to, że nie mogę po prostu utworzyć instancji notatnikaView wewnątrz kontrolera NotebookController. Więc mam

  • Włóż logikę w moich notebook.js że przewody od 2 razem
  • mieć globalną funkcję w mojej aplikacji, który wie do wystąpienia jednej z nich i podłączyć je razem
  • użycie Dependency Injection, albo w domu lub coś w rodzaju SquirrelIoc

W języku Java wybór jest naturalny: użyj Spring. Ale to nie wygląda na JavaScript-y. Co należy zrobić?

+0

Może ja czegoś brakuje, ale nie mogą osiągnąć testowalności po prostu upewniając używasz agregację zamiast składu? –

+0

To jest pomysł. Ale pytanie brzmi, jaki jest właściwy sposób na połączenie tej agregacji obiektów? –

Odpowiedz

0

Spróbuję to zrobić, ale będzie to trochę trudne, nie widząc żadnego prawdziwego kodu. Osobiście nigdy nie widziałem nikogo, kto by tak konkretnie próbował (M) VC z JavaScript lub IoC.

Przede wszystkim, z czym zamierzasz przetestować? Jeśli jeszcze tego nie zrobiłeś, sprawdź numer YUI Test video, który zawiera dobre informacje na temat testów jednostkowych za pomocą javascript.

Po drugie, kiedy mówisz „najlepszym sposobem na łączenie się, że agregację” I pewnie właśnie to zrobić jako rozgrywający w/kontrolera

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

Ale to sprawia, że ​​niektóre duże założenie o tym, jak masz zaprojektowałeś swój kontroler i już widziałeś obiekty.

2

Powiedziałbym, wystarczy podłączyć je razem:

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

Ale to oczywiście inna sprawa budzi - jak można przetestować funkcję wireTogether()?

szczęście JavaScript jest naprawdę dynamiczny język, więc można po prostu przypisać nowe wartości do widoku i kontrolera:

var ok = false; 

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

wireTogether(); 

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

wtrysk zależność jest prawdopodobnie najlepszym. W porównaniu z Javą niektóre aspekty tego są łatwiejsze do wykonania w kodzie JS, ponieważ można przekazać obiekt pełen wywołań zwrotnych do kontrolera NotebookController. Inne aspekty są trudniejsze, ponieważ nie masz statycznej analizy kodu, aby sformalizować interfejs między nimi.

3

Dzięki za wgląd.Skończyło się na napisaniu prostego narzędzia do wstrzykiwania zależności JavaScript. Po debaty na chwilę i komentarze, że doszło do mnie, że DI był bardzo dobrym rozwiązaniem, ponieważ:

  1. To całkowicie oddzielone obawy okablowania od logiki biznesowej przy zachowaniu logiki okablowania blisko rzeczy są przewodowy .
  2. Pozwoliło mi to na generalne wywołanie wywołania zwrotnego na moich obiektach, dzięki czemu mogłem wykonać inicjalizację 3-fazową: utworzyć instancję, podłączyć wszystko, zadzwonić do wszystkich wywołań zwrotnych i powiedzieć, że są podłączone .
  3. Łatwo było sprawdzić zależność brakujących problemów.

Więc oto narzędzie 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

Mam inwersję biblioteki sterowania javascript, jestem bardzo z niego zadowolony. https://github.com/fschwiet/jsfioc. Obsługuje również zdarzenia, więc jeśli chcesz mieć zdarzenie uruchamiania, które jest w porządku. To może używać więcej dokumentacji ...

http://github.com/fschwiet/jsfioc

inny (nowszy?) opcja, która ma lepszą dokumentację i wsparcie, jest requireJS (http://requirejs.org/).

Powiązane problemy