2009-03-06 12 views
16

Actualmente estoy enfrentando un enigma: ¿Cuál es la forma correcta de unir 2 objetos javascript?¿Cuál es la forma correcta de conectar juntos 2 objetos javascript?

Imagine una aplicación como un editor de texto con varios archivos diferentes. Tengo una página HTML que representa la vista del portátil. Tengo un archivo notebook.js que contiene definiciones de clase para NotebookController y Notebook View.

NotebookControler objeto responsable de llevar a cabo la lógica de negocios en el portátil como "Guardar Notebook", "Cargar Notebook", "Nuevo Notebook". NotebookView es responsable de administrar el HTML que se utiliza para la presentación. Hace cosas de bajo nivel como "obtener/configurar cuerpo de cuaderno" "obtener/configurar nombre de cuaderno". También escucha eventos DOM (onClick) y dispara eventos de negocios (saveNotebook). Este es mi intento en el patrón de Vista pasiva.

Quiero que mi código javascript del lado del cliente esté orientado a objetos, separado de las inquietudes y que pueda ser comprobado por la unidad. Quiero probar NotebookController con un NotebookView simulado y viceversa. Esto significa que no puedo simplemente crear una instancia de NotebookView dentro del NotebookController. Yo también

  • poner un poco de lógica en mis notebook.js que los cables de los 2 juntos
  • tienen una función global en mi aplicación que sabe crear una instancia de uno de cada uno y conectarlos juntos
  • Uso inyección de dependencias, ya sea uno de cosecha propia o algo así como SquirrelIoc

En Java, la elección es natural: use Spring. Pero eso no parece muy JavaScript-y. ¿Qué es lo correcto?

+0

Tal vez me falta algo, pero puede no alcanzar la capacidad de prueba con sólo hacer seguro de que está utilizando la agregación en lugar de composición? –

+0

Esa es la idea. Pero la pregunta es, ¿cuál es la forma correcta de conectar esa agregación de objetos? –

Respuesta

0

Trataré de dar un vistazo a esto, pero será un poco difícil sin ver ningún código real. Personalmente, nunca he visto a nadie hacer un intento tan específico en (M) VC con JavaScript o IoC para el caso.

Antes que nada, ¿con qué vas a probar? Si aún no lo has hecho, revisa el YUI Test video que tiene buena información sobre pruebas de unidades con javascript.

En segundo lugar, cuando se dice "la mejor manera de cablear que la agregación" Probablemente me acaba de hacerlo como un regulador w/controlador

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

Pero esto hace que algunos gran suposición de cómo haya diseñó su controlador y ve objetos ya.

2

diría, simplemente conectarlos juntos:

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

Pero entonces, por supuesto, otra cuestión plantea - ¿cómo se prueba la función wireTogether()?

Por suerte, JavaScript es un lenguaje muy dinámico, por lo que sólo puede asignar nuevos valores para ver y controlador:

var ok = false; 

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

wireTogether(); 

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

La inyección de dependencia es probablemente su mejor apuesta. Comparado con Java, algunos aspectos de esto son más fáciles de hacer en el código JS, ya que puede pasar un objeto lleno de devoluciones de llamada a su NotebookController. Otros aspectos son más difíciles porque no tiene el análisis del código estático para formalizar la interfaz entre ellos.

3

Gracias por la información.Terminé escribiendo una sencilla utilidad de inyección de dependencias de JavaScript. Después de debatir durante un tiempo y sus comentarios, se me ocurrió que la DI fue realmente la respuesta correcta porque:

  1. Es totalmente separadas las preocupaciones de cableado desde la lógica de negocio, manteniendo la lógica de cableado cerca de las cosas que se están cableados .
  2. Me permitió proporcionar genéricamente una devolución de llamada "está todo conectado" en mis objetos para poder hacer una inicialización de 3 fases: crear una instancia de todo, conectarlo todo, llamar a las devoluciones de llamadas de todos y decirles que están conectados .
  3. Fue fácil comprobar si hay problemas de falta de dependencia.

Así que aquí está la utilidad 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

Tengo una inversión de la biblioteca de controles de Javascript, estoy muy contento con él. https://github.com/fschwiet/jsfioc. También es compatible con eventos, por lo que si desea tener un evento de inicio, eso está bien. Se podría utilizar más documentación ...

http://github.com/fschwiet/jsfioc

Otra opción (nuevo?), Que tiene una mejor documentación y apoyo, es RequireJS (http://requirejs.org/).

Cuestiones relacionadas