2012-10-02 47 views
5

Estoy trabajando dentro de un JavaScript + BackboneJS (un framework MVC) + RequireJS framework, pero esta pregunta es algo OO genérica.Dependencia de inyección frente a dependencias administradas frente al objeto global

Empezaré explicando que en la espina dorsal, sus vistas son una mezcla de vistas y controladores tradicionales, y sus plantillas HTML son los tradicionales Vistas MVC

estado devanando mi cabeza en esto por un tiempo y estoy no estoy seguro de cuál debería ser el enfoque correcto/pragmático.

Tengo un objeto Usuario que contiene las preferencias del usuario (como sistema de unidad, selección de idioma, cualquier otra cosa) de las que depende mucho el código.

Algunas de mis vistas hacen la mayor parte del trabajo sin el uso de plantillas (usando librerías de terceros, como Mapping y Graphing libs), y como tales tienen una dependencia en el objeto User para encargarse de la conversión de la unidad. por ejemplo. Actualmente estoy usando RequireJS para administrar esa dependencia sin romper demasiado la encapsulación.

Algunas de mis vistas trabajan muy poco ellas mismas, y solo transfieren datos de modelo a mi motor de plantillas/plantillas, que hacen el trabajo y también tienen una dependencia en el objeto Usuario, para cosas como la conversión de unidades. La única forma de pasar esta dependencia a la plantilla es inyectándola en el Modelo y pasando el modelo al motor de la plantilla.

Mi pregunta es, ¿cómo manejar mejor una dependencia tan necesaria? - ¿Cree una referencia de toda la aplicación/objeto global que esté accesible en todas partes? (YUK) - Use las dependencias gestionadas RequireJS, aunque generalmente solo se recomienda utilizar la carga de dependencias gestionadas para definiciones de clase/objeto en lugar de objetos concretos. - O, ¿solo utiliza la inyección de dependencia y pasa manualmente esa dependencia a todo lo que la necesita?

Respuesta

4

Desde un punto de vista puramente técnico, yo diría que los globales intercambiables (globales que pueden cambiar), especialmente en javascript, son peligrosos e incorrectos. Especialmente dado que javascript está lleno de partes de código que se ejecutan de forma asíncrona. Considere el siguiente código:

window.loggedinuser = Users.get("Paul"); 
addSomeStuffToLoggedinUser(); 
window.loggedinuser = Users.get("Sam"); 
doSomeOtherStuffToLoggedinUser(); 

Ahora bien, si addSomeStuffToLoggedinUser() ejecuta de forma asíncrona en alguna parte (por ejemplo, que hace una llamada ajax, y luego otra llamada AJAX cuando el primero acaba), que puede muy bien ser la adición de material para el nuevo loggedInUser ("Sam"), cuando llega la segunda llamada ajax. Claramente no es lo que quieres.

Habiendo dicho eso, soy aún menos partidario de tener algún objeto de usuario que entreguemos todo el tiempo de una función a otra, ad infinitum.

Personalmente, al tener que elegir entre estos dos males, elegiría un alcance global para las cosas que "muy raramente cambian" --- a menos que tal vez estaba construyendo una central nuclear o algo así. Por lo tanto, tiendo a hacer que el usuario conectado esté disponible globalmente en mi aplicación, arriesgándome a que si de alguna manera por alguna razón algunas ejecuciones se ejecutan muy tarde, y tengo una situación donde un usuario cierra la sesión y directamente el otro se conecta, algo extraño puede suceder. (De nuevo, si un meteoro se estrella contra el centro de datos que aloja mi aplicación, también puede suceder algo extraño ... Tampoco estoy protegiéndome contra eso). En realidad, una posible solución sería volver a cargar toda la aplicación tan pronto como alguien cierre la sesión.

Por lo tanto, supongo que todo depende de su aplicación. Una cosa que lo hace mejor (y te hace sentir como si estuviera todavía conseguir algunos puntos OO karma) es ocultar los datos de alguna Singleton espacio de nombres:

var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser(); 
doSomethingCoolWith(myuser); 

en lugar de

doSomethingCoolWith(window.loggedinuser); 

aunque es casi lo mismo al final ...

+0

Por lo que vale, puedes encontrar algunos patrones geniales para mitigar este problema mediante el uso de diferidos para sentarte frente a variables globales conmutables que podrían modificarse de forma asíncrona. –

1

Creo que ya respondió su propia pregunta, solo quiere que alguien más lo diga por usted:) Use DI, pero no está realmente "manualmente" pasando esa dependencia a todo, ya que necesita hacer referencia para usar de todos modos.

1

Teniendo en cuenta el enfoque TDD, ¿cómo lo probarías? DI es mejor para un nuevo proyecto, pero JS le ofrece opciones flexibles para tratar con dependencias globales concretas al realizar pruebas, es decir, la construcción del contexto. Yendo mucho atrás, Yahoo estableció un patrón de módulo en el que todos los módulos estaban vagamente acoplados y no dependían el uno del otro, pero estaba bien tener un contexto global. Ese contexto global puede hacer que la construcción de su aplicación sea más pragmática para las cosas que se reutilizan constantemente. Es solo que necesitas aplicarlo juiciosamente/con moderación y es necesario que haya casos muy fuertes para que esas cosas sean dinámicas.

Cuestiones relacionadas