La versión PDF de la dirección de descarga de PPT: http://www.slideshare.net/jibyjohnc/jqquerysummit-largescale-javascript-application-architecture
Nota: Durante el proceso de recopilación, descubrí que los pensamientos del autor se repitieron, por lo que eliminó algunos de ellos. Si su inglés es bueno, lea el PPT inglés directamente.
Los siguientes son los principales capítulos de este artículo:
1. ¿Qué es el "programa grande JavaScript"?
2. Considere la arquitectura del programa actual
3. Consideración a largo plazo
4. Lluvia de ideas
5. Arquitectura sugerida
5.1 Patrón de diseño
5.1.1 Teoría del módulo
5.1.1.1 Descripción general
5.1.1.2 Modo del módulo
5.1.1.3 Tamaño de autofacio de objeto
5.1.1.4 Módulo CommonJS
5.1.2 Modo de fachada
5.1.3 Modo mediador
5.2 Aplicar a su arquitectura
5.2.1 Fachada - Abstracción de núcleo
5.2.2 Mediador - Programa Core
5.2.3 funcionando de cerca
6. Publicar pub/subtensión: eventos de registro automático
7. Preguntas y respuestas
8. Agradecimientos
¿Qué es el "programa grande JavaScript"?
Antes de comenzar, definamos qué es un sitio grande de JavaScript. Muchos expertos en desarrollo de JS también han sido desafiados. Algunas personas dicen que más de 100,000 líneas de código JavaScript se consideran grandes, y algunas personas dicen que el código JavaScript debe tener más de 1 MB de tamaño. De hecho, ninguno de los dos es correcto, porque la cantidad de código no se puede medir como el número de códigos instalados. Muchos código JS trivial pueden superar fácilmente las 100,000 líneas.
Mi definición de "grande" es la siguiente. Aunque puede no ser correcto, debe estar relativamente cerca:
Personalmente, creo que los grandes programas de JavaScript deberían ser muy importantes e incorporar muchos esfuerzos de desarrolladores sobresalientes para procesar datos de peso pesado y mostrarlos al navegador.
Revise la arquitectura del programa actual
No puedo enfatizar lo importante que es este problema. Muchos desarrolladores experimentados a menudo dicen: "Los patrones creativos y de diseño existentes funcionan muy bien en mi proyecto mediano anterior, por lo que debería estar bien usarlos nuevamente en un programa ligeramente más grande, ¿verdad?", Es cierto en ciertos programas, pero no olvide que, dado que es un gran programa, generalmente debería haber grandes preocupaciones que necesitan desglosar y prestar atención. Explico brevemente cómo lleva tiempo revisar la arquitectura del programa que se ha estado ejecutando durante mucho tiempo. En la mayoría de los casos, la arquitectura del programa JavaScript actual debería verse así (tenga en cuenta que es una arquitectura JS, no lo que todos a menudo llaman ASP.NET MVC):
widgets personalizados
modelos
vistas
Controladores
plantillas
Bibliotecas/kits de herramientas
un núcleo de aplicación.
También puede encapsular el programa en múltiples módulos solo, o usar otros patrones de diseño, lo cual es excelente, pero si estas estructuras representan completamente su arquitectura, puede haber algunos problemas potenciales. Echemos un vistazo a algunos puntos importantes:
1. ¿Cuántas cosas en su arquitectura se pueden sacar y reutilizar de inmediato?
¿Hay algunos módulos separados que no dependen de otro código? ¿Es autónomo? Si voy a la base de código que está usando y luego seleccione algunos códigos de módulo de módulo y los pongo en una nueva página, ¿se puede usar de inmediato? Puede decir que el principio está bien. Te sugiero que planifiques durante mucho tiempo. Si su empresa ha desarrollado muchos programas importantes antes, de repente algún día alguien dijo que el módulo de chat en este proyecto es bueno, sácalo y lo pongamos en otro proyecto. ¿Puedes usarlo sin modificar el código?
2. ¿Cuántos módulos necesitan el sistema para confiar en otros módulos?
¿Todos los módulos del sistema están bien acoplados? Antes de tomar esta pregunta como preocupación, lo explicaré primero. No es que todos los módulos no tengan ninguna dependencia. Por ejemplo, una función de grano fino puede extenderse desde la función base. Mi problema es diferente de esta situación. Estoy hablando de las dependencias antes de diferentes módulos funcionales. En teoría, todos los diferentes módulos funcionales no deberían tener demasiadas dependencias.
3. Si algo sale mal con una parte de su programa, ¿seguirán funcionando las otras partes?
Si crea un programa similar a Gmail, puede encontrar que muchos módulos en Gmail se cargan dinámicamente, como el módulo de chat de chat, que no se carga al inicializar la página, e incluso si se produce un error después de la carga, otras partes de la página se pueden usar normalmente.
4. ¿Puedes probar tus módulos de una manera muy simple?
Cada uno de sus módulos puede usarse en sitios grandes con millones de usuarios, o incluso varios sitios lo usan, por lo que sus módulos deben soportar la prueba, es decir, ya sea dentro o fuera de la arquitectura, deberían poder probarse de manera muy simple, incluidas la mayoría de las afirmaciones que se pueden pasar en diferentes entornos.
Consideración a largo plazo
Al estructurar programas grandes, lo más importante es ser con visión de futuro. No solo puede considerar la situación un mes o un año después. ¿Debería considerar la posibilidad de cambios en un período de tiempo más largo? Los desarrolladores a menudo vinculan el código de operaciones DOM y el programa con demasiada fuerza, aunque a veces han encapsulado la lógica separada en diferentes módulos. Piense por qué no es muy bueno a largo plazo.
Un colega mío dijo una vez que una arquitectura precisa puede no ser adecuada para escenarios futuros, y a veces es correcto, pero cuando necesite hacerlo, pagará mucho dinero. Por ejemplo, es posible que deba elegir reemplazar a Dojo, JQuery, Zepto y Yui por ciertas razones de rendimiento, seguridad y diseño. En este momento, hay un problema. La mayoría de los módulos tienen dependencias, que requieren dinero, tiempo y personas, ¿verdad?
Está bien para algunos sitios pequeños, pero los sitios grandes necesitan proporcionar un mecanismo más flexible sin preocuparse por varios problemas entre varios módulos. Esto ahorra dinero y tiempo.
Para resumir, ¿puede asegurarse ahora de que puede reemplazar algunas bibliotecas de clase sin reescribir todo el programa? Si no, entonces de lo que vamos a hablar a continuación es más adecuado para usted.
Muchos desarrolladores de JavaScript experimentados han dado algunas notas clave:
Justin Meyer, autor de JavaScriptMVC, dijo:
El mayor secreto para construir programas grandes es que nunca construye grandes programas, pero divide los programas en módulos pequeños para hacer que cada pequeño módulo sea comprobable, considerable y luego los integre en el programa.
Sitios web de JavaScript de alto rendimiento Autor Nicholas, Zakas:
"La clave es reconocer desde el principio que no tiene idea de cómo crecerá. Cuando acepta que no sabe todo, comienza a diseñar el sistema a la defensiva. Identifica las áreas clave que pueden cambiar, lo que a menudo es muy fácil cuando tiene un poco de tiempo. -
Muchos problemas de texto son demasiado problemáticos. Para resumir, todo se puede cambiar, por lo que debe ser abstracto.
JQuery Fundaments Autor Rebecca Murphey:
Cuanto más cerca sea la conexión entre cada módulo, menos reutilizable es y mayor será la dificultad de cambiarlo.
Las vistas importantes anteriores son los elementos centrales de construir la arquitectura y debemos recordarlos todo el tiempo.
Idea genial
Vamos a hacer una lluvia de ideas. Necesitamos una arquitectura acoplada libremente, sin dependencias entre los módulos, cada módulo y programa se comunican, y luego la capa intermedia se hace cargo y procesa los mensajes correspondientes.
Por ejemplo, si tenemos un JavaScript construyendo un programa de panadería en línea, un módulo envía un mensaje que podría ser "hay 42 rondas que deben entregarse". Utilizamos diferentes capas de capa para procesar mensajes enviados por el módulo y hacemos lo siguiente:
Los módulos no acceden directamente al núcleo del programa
Los módulos no llaman directamente ni afectan otros módulos
Esto nos impedirá cometer errores en todos los módulos debido a errores en un determinado módulo.
Otro problema es la seguridad. La situación real es que la mayoría de las personas no creen que la seguridad interna sea un problema. Decimos en nuestros corazones que los programas están construidos por mí mismo. Sé cuáles son públicos y privados. No hay problema con la seguridad, pero ¿tiene una forma de definir qué módulo acceder al núcleo del programa? Por ejemplo, hay un módulo de chat de chat que no quiero que llame al módulo de administración, o no quiero que llame a un módulo con permisos de escritura de DB, porque hay una fragilidad entre ellos y es fácil causar ataques XSS. Cada módulo no debería poder hacer todo, pero el código JavaScript en la mayoría de las arquitecturas actualmente tiene este problema. Proporcione una capa intermedia para controlar qué módulo puede acceder a esa parte autorizada, es decir, el módulo solo puede lograr la mayor parte de la parte que autorizamos.
Arquitectura sugerida
El enfoque de nuestro artículo es que esta vez la arquitectura que proponemos utiliza patrones de diseño que todos somos conocidos: módulo, fachada y mediador.
A diferencia de los modelos tradicionales, para desacoplar cada módulo, solo dejamos que el módulo publique algunos eventos de eventos. El modo mediador puede ser responsable de suscribirse a mensajes de mensajes de estos módulos y luego controlar la respuesta de notificación. Los usuarios del modo fachada restringen los permisos de cada módulo.
Las siguientes son las partes a las que debemos prestar atención:
1 patrón de diseño
1.1 Teoría del módulo
1.1.1 Descripción general
1.1.2 Modo del módulo
1.1.3 Tamaño de autofacio de objeto
1.1.4 Módulo CommonJS
1.2 Modo de fachada
1.3 Modo mediador
2 Aplicar a su arquitectura
2.1 Fachada - Abstracción del núcleo
2.2 Mediador - Programa Core
2.3 Trabajar en estrecha colaboración
Teoría modal
Todos pueden haber usado código modular más o menos. El módulo es parte de una arquitectura de programa completa y robusta. Cada módulo se crea para un propósito separado. Volviendo a Gmail, tomemos un ejemplo. El módulo de chat de chat parece ser una parte separada, pero de hecho tiene muchos submódulos separados. Por ejemplo, el módulo de expresión en el interior es en realidad un submódulo separado, que también se usa en la ventana para enviar correos electrónicos.
Otra es que los módulos se pueden cargar, eliminar y reemplazar dinámicamente.
En JavaScript, tenemos varias formas de implementar módulos. Todos están familiarizados con los patrones de módulos y los literales de objetos. Si ya está familiarizado con estos, ignore esta sección y salte directamente a la parte CommonJS.
Modo de módulo
El patrón del módulo es un patrón de diseño relativamente popular. Puede encapsular variables privadas, métodos y estados a través de aparatos ortopédicos. Al envolver estos contenidos, no se puede acceder directamente a los objetos generalmente globales. En este patrón de diseño, solo se devuelve una API y todos los demás contenidos están encapsulados como privados.
Además, este patrón es similar a las expresiones de funciones autoexecutadas. La única diferencia es que el módulo devuelve un objeto, mientras que la expresión de la función autoexecutada devuelve una función.
Como todos sabemos, JavaScript no quiere que otros idiomas tengan modificadores de acceso, y no pueden declarar modificadores privados y públicos para cada campo o método. Entonces, ¿cómo implementamos este patrón? Es para devolver un objeto, incluidos algunos métodos públicos, que tienen la capacidad de llamar a objetos internos.
Eche un vistazo al código a continuación. Este código es un código de auto-ejecución. La declaración incluye un objeto global BatteryModule. La matriz de canasta es privada, por lo que todo su programa no puede acceder a esta matriz privada. Al mismo tiempo, devolvemos un objeto que contiene 3 métodos (como Additem, GetItemCount, GetTotal). Estos 3 métodos pueden acceder a la matriz de canasta privada.
var basketModule = (function () {var canasta = []; // privateReturn {// expuesto a public addItem: function (valores) {bestion.push (valores);}, getItemCount: function () {return Basket.length;}, getToTal: function () {var q = this.getItemCount (), p = 0; while (q-)} [q]. } return p;}}} ());También tenga en cuenta que el objeto que devolvemos se asigna directamente al BankSmodule, por lo que podemos usarlo como lo siguiente:
// BasketModule es un objeto con propiedades que también puede ser MethodsBasketModule.Additem ({item: 'Bread', Price: 0.5}); BasketModule.additem ({item: 'Butter', Price: 0.3}); console.log (BastónModule.GetItemCount ()); console.log (BasketModule.GetTotal ()); // Sin embargo, lo siguiente no funcionará: console.log (bestymodule.basket); // (indefinido como no dentro del objeto devuelto) console.log (canasta); // (solo existe dentro del alcance del cierre)Entonces, ¿cómo lo hace en varias bibliotecas de clases populares (como Dojo, jQuery)?
Dojo
Dojo intenta usar dojo.declare para proporcionar métodos de declaración de estilo de clase. Podemos usarlo para implementar el patrón del módulo. Por ejemplo, si desea declarar un objeto de cesta en el espacio de nombres de la tienda, puede hacer esto:
// Store Wayvar tradicional = Window.Store || {}; store.basket = store.basket || {}; // usando dojo.setObjectDojo.setObject ("store.basket.object", (function () {var basket = []; function privateMethod () {console.log (bestion);} return {publicMethod: function () {privateMethod ();}};} ());Es muy poderoso cuando se combina con dojo.provide.
Yui
El siguiente código es la implementación original de YUI:
Yahoo.store.basket = function () {// variables "privadas": var myprivatevar = "Solo se puede acceder dentro de yahoo.store.basket."; // método "privado": var myPrivateMethod = function () {yahoo.log ("Solo se puede acceder desde yahoo.store.basket"); } return {myPublicProperty: "Soy una propiedad pública", myPublicMethod: function () {yahoo.log ("Soy un método público"); // Dentro de la canasta, puedo acceder a Var and Métodos "privados": yahoo.log (myPrivateVar); Yahoo.log (myPrivateMethod ()); // El alcance nativo de myPublicMethod es tienda para que podamos // acceder a miembros públicos usando "esto": yahoo.log (this.mypublicProperty); }};} ();jQuery
Hay muchas implementaciones del patrón del módulo en jQuery. Echemos un vistazo a un ejemplo diferente. Una función de biblioteca declara una nueva biblioteca. Luego, al crear la biblioteca, el método init se ejecuta automáticamente en document.ready.
funciones biblioteca (módulo) {$ (function () {if (módulo.init) {módulo.init ();}}); return módulo;} var myLibrary = biblioteca (function () {return {init: function () { /*implementación* /}};} ());Tamaño de autofacio de objeto
La medición del objeto autofacio se declara en aparatos ortopédicos, y la nueva palabra clave no es necesaria al usarla. Si no le importa mucho el público/privado de los campos de atributos en un módulo, puede usar este método, pero tenga en cuenta que este método es diferente de JSON. Tamaño de autofacio del objeto: var item = {nombre: "Tom", valor: 123} json: var item = {"name": "tom", "valor": 123}.
var mymodule = {myProperty: 'someValue', // Los literales de objetos pueden contener propiedades y métodos. // Aquí, otro objeto se define para la configuración // propósitos: myconfig: {usecaching: true, lenguaje: 'en'}, // un método muy básico mymethod: function () {console.log ('¿puedo haz funcionality?'); }, // emite un valor basado en la configuración actual mymethod2: function () {console.log ('el almacenamiento en caché es:' + (this.myconfig.useCaching)? 'habilitado': 'discapacitado'); }, // anula la configuración actual mymethod3: function (newConfig) {if (typeof newConfig == 'object') {this.myconfig = newConfig; console.log (this.myconfig.language); }}}; mymodule.mymethod (); // puedo haze funcionalityMymodule.mymethod2 (); // salidas habilitadasmymodule.mymethod3 ({lenguaje: 'fr', usecaching: false}); // frCommonjs
No hablaré sobre la introducción de CommonJS aquí. Muchos artículos lo han introducido antes. Lo que queremos mencionar aquí es que hay dos parámetros importantes exportaciones y requieren en el estándar CommonJS. Las exportaciones representan el módulo que se cargará, y requieren significa que estos módulos cargados deben confiar en otros módulos y también deben cargarse.
/*Ejemplo de logro de compatibilidad con AMD y CommonJS estándar colocando la placa en torno al formato de módulo CommonJS estándar:*/(function (define) {Define (function (requerir, exports) {// contenido del módulo var dep1 = requirir ("dep1"); exports.somexportedfuntion = function () {...}; // ...});}) (typeOF Define == "función"? Define: function (fábrica) {fábrica (requerir, exports)});Hay muchas implementaciones de carga de módulos estándar de CommonJS. Lo que prefiero es requerirjs. ¿Puede cargar módulos y módulos de dependencia relacionados muy bien? Tomemos un ejemplo simple. Por ejemplo, si necesita convertir la imagen en código ASCII, primero cargamos el módulo del codificador y luego obtenemos su método Encodetoascii. Teóricamente, el código debe ser el siguiente:
var encodetoascii = require ("codificador"). Encodetoascii; Exports.EncodesOmesource = function () {// Después de otras operaciones, luego llame a Encodetoascii}Sin embargo, el código anterior no funciona, porque la función EncodetoCoascii no se usa para adjuntar al objeto de la ventana, por lo que no se puede usar. Esto es lo que debe hacer la mejora del código:
Definir (función (requerir, exportar, módulo) {var encodetoChii = require ("codificador"). Encodetoascii; exports.encodesomesource = function () {// Process y luego llamar a Encodetoascii}});CommonJS tiene un gran potencial, pero dado que el tío no está muy familiarizado con él, no lo presentaré mucho.
Modo de fachada
El modelo de fachada ocupa un papel importante en la arquitectura de este modelo. Muchas bibliotecas o marcos de clase JavaScript se reflejan en este modelo. La función más grande es incluir la API del alto nivel para ocultar implementaciones específicas. Esto significa que solo exponemos las interfaces, y podemos tomar las decisiones de las implementaciones internas por nosotros mismos, lo que también significa que el código de implementación interna se puede modificar y actualizar fácilmente. Por ejemplo, hoy usa jQuery para implementarlo, y mañana desea cambiar Yui, lo cual es muy conveniente.
En el siguiente ejemplo, podemos ver que proporcionamos muchos métodos privados y luego exponemos una API simple para permitir que el mundo exterior ejecute y llame a métodos internos:
var module = (function () {var _private = {i: 5, get: function () {console.log ('valor actual:' + this.i);}, set: function (val) {this.i = val;}, ejecutar: function () {console.log ('running');}, saltar: function.log.log ('salto};};};};}; función (args) {_Private.set (args.val);La diferencia entre la fachada y de lo que estamos hablando a continuación es que la fachada solo proporciona funciones existentes, mientras que los mediadores pueden agregar nuevas funciones.
Modo mediador
Antes de hablar sobre el modiador, damos un ejemplo. El sistema de control de vuelo del aeropuerto, que es la legendaria torre, tiene una potencia absoluta. Puede controlar el tiempo y el tiempo de aterrizaje y el lugar de cualquier avión. El avión y el avión no pueden comunicarse antes, lo que significa que la torre es el núcleo del aeropuerto, y el mediador es equivalente a esta torre.
El mediador se usa para tener múltiples módulos en un programa y no desea que cada módulo tenga dependencias, entonces el modo mediador puede lograr el propósito del control centralizado. En escenarios reales, el mediador encapsula muchos módulos que no quieren hacer, lo que permite que se conecten a través de mediadores, y también los acoplen libremente, para que deben comunicarse a través de mediadores.
Entonces, ¿cuáles son las ventajas del modo mediador? Eso es desacoplamiento. Si antes tiene una buena comprensión del patrón del observador, será relativamente simple comprender el diagrama de mediador a continuación. La siguiente figura es un diagrama de patrones de mediador de alto nivel:
Piénselo, cada módulo es un editor, y el mediador es tanto un editor como un suscriptor.
El módulo 1 transmite algo real al mediador, diciendo que hay que hacer algo
Después de que el mediador captura el mensaje, inicie inmediatamente el módulo 2 que debe usarse para procesar el mensaje. Después de completar el procesamiento del módulo 2, devuelva la información al mediador.
Al mismo tiempo, el mediador también inicia el Módulo 3, y inicia sesión automáticamente al Módulo 3 al recibir el mensaje de retorno del Módulo 2.
Se puede ver que no hay comunicación entre los módulos. Además, el mediador también puede implementar la función de monitorear el estado de cada módulo. Por ejemplo, si hay un error en el módulo 3, el mediador solo puede querer temporalmente otros módulos, luego reiniciar el módulo 3 y luego continuar ejecutando.
Mirando hacia atrás, podemos ver que la ventaja de Mediator es que el módulo acoplado libremente está controlado por el mismo mediador. El módulo solo necesita transmitir y escuchar eventos, y no hay necesidad de una conexión directa entre los módulos. Además, se pueden usar múltiples módulos para procesar información a la vez, lo que también nos facilita agregar nuevos módulos a la lógica de control existente en el futuro.
Es cierto que dado que todos los módulos no pueden comunicarse directamente, puede haber una ligera disminución en el rendimiento relativamente, pero creo que vale la pena.
Usemos una demostración simple basada en la explicación anterior:
var mediator = (function () {var suscribe = function (canal, fn) {if (! Mediator.channels [canal]) mediator.channels [canal] = []; mediator.channels [canal] .push ({context: this, callback: fn}); return this;}, publish = function (canal) {ifs Mediator.channels Array.prototype.slice.call (argumentos, 1); suscríbete: suscríbete, instalación: function (obj) {obj.subscribe = suscripción;Luego hay 2 módulos llamados:
// pub/sub en un mediador centralizado mediador.name = "tim"; mediator.subscribe ('namechange', function (arg) {console.log (this.name); this.name = arg; console.log (this.name);}); mediator.publish ('namechange', 'David'); // tim, David // pub/sub a través de terceros mediator var obj = {name: 'sam'}; mediator.installto (obj); obj.subscribe ('namechange', function (arg) {console.log (this.name); this.name = arg; console.log (this.name);}); obj.publish ('Namechange', 'John'); // Sam, JohnFachada de aplicación: la abstracción del núcleo de la aplicación
Una fachada funciona como resumen del núcleo de la aplicación y es responsable de la comunicación entre el mediador y el módulo. Cada módulo solo puede comunicarse con el núcleo del programa a través de esta fachada. La responsabilidad como resumen es garantizar que estos módulos puedan proporcionar una interfaz consistente en cualquier momento, que es similar al papel del controlador SendBox. Todos los componentes del módulo se comunican con los mediadores a través de él, por lo que la fachada debe ser confiable y confiable. Al mismo tiempo, en función de proporcionar una interfaz al módulo, la fachada debe desempeñar otro papel, es decir, el control de seguridad, es decir, para determinar a qué parte del programa puede acceder mediante un módulo. Los componentes del módulo solo pueden llamar a sus propios métodos y no pueden acceder a ningún contenido no autorizado. Por ejemplo, un módulo podría transmitir DataValidationCompletedWriteTodb, donde las verificaciones de seguridad deben garantizar que el módulo tenga permisos de escritura a la base de datos.
En resumen, el mediador solo puede realizar el procesamiento de la información después de la detección de autorización de la fachada.
Mediador de la aplicación: el núcleo de la aplicación
El mediador funciona como un papel central para la aplicación, hablemos brevemente sobre sus responsabilidades. El trabajo más central es administrar el ciclo de vida del módulo. Cuando este núcleo captura cualquier información, debe juzgar cómo el programa lo maneja, es decir, decidir qué módulo comenzar o detener. Cuando se inicia un módulo, debería poder ejecutarse automáticamente, sin el núcleo de la aplicación para decidir si debe ejecutarse (por ejemplo, si debe ejecutarse cuando DOM esté listo), por lo que el módulo en sí debe determinarse.
Puede tener una pregunta, ¿en qué circunstancias se detendrá un módulo? Cuando el programa detecta que un módulo falla o comete un error, el programa debe tomar una decisión para evitar que el método en el módulo continúe ejecutando para que el componente pueda reiniciarse, con el objetivo principal de mejorar la experiencia del usuario.
Además, el núcleo debe poder agregar o eliminar dinámicamente módulos sin afectar ninguna otra función. Un ejemplo común es que un módulo no está disponible al comienzo de la carga de la página, pero después de que el usuario opera, necesita cargar dinámicamente el módulo y luego ejecutarlo. Al igual que la función de chat en Gmail, debería ser fácil de entender desde el propósito de la optimización del rendimiento.
El manejo de errores de excepción también es manejado por el núcleo de la aplicación. Además, cuando cada módulo transmite información, también transmite cualquier error al núcleo para que el núcleo del programa pueda detener/reiniciar estos módulos de acuerdo con la situación. Esta es también una parte muy importante de la arquitectura libremente acoplada. No necesitamos cambiar manualmente ningún módulo. Podemos hacer esto utilizando Publicar/suscribirse a través del mediador.
Armar
Cada módulo contiene varias funciones en el programa. Cuando tienen información para procesarse, emiten información que notifica al programa (esta es su principal responsabilidad). La siguiente sección de control de calidad mencionó que los módulos pueden confiar en algunos métodos de operación de herramienta DOM, pero no deben depender de otros módulos del sistema. Un módulo no debe prestar atención al siguiente contenido:
1. ¿Qué objeto o módulo se suscribe a la información publicada por este módulo?
2. ¿Son estos objetos de clientes o objetos del lado del servidor?
3. ¿Cuántos objetos se han suscrito a su información?
El núcleo de la aplicación de abstracción de la fachada evita la comunicación directa entre los módulos. Se suscribe a la información de cada módulo y también es responsable de la detección de autorización, asegurando que cada módulo tenga su propia autorización separada.
Mediator (Aplicación Core) utiliza el modo Mediator para desempeñar el papel de Publish/Subscribe Manager, responsable de la administración del módulo y la ejecución del módulo de inicio/detener, y puede cargar y reiniciar dinámicamente los módulos con errores.
El resultado de esta arquitectura es que no hay dependencia entre los módulos, debido a las aplicaciones libremente acopladas, se pueden probar y mantener fácilmente, cada módulo se puede reutilizar fácilmente en otros proyectos, o se puede agregar y eliminar dinámicamente sin afectar el programa.
Publicar pub/subtensión: registro automático de eventos
Con respecto al registro automático de eventos, se deben seguir ciertas especificaciones de nombres. Por ejemplo, si un módulo publica un evento llamado MessageUpdate, entonces todos los módulos con el método MessageUpdate se ejecutarán automáticamente. Hay beneficios, ventajas y desventajas. Para métodos de implementación específicos, puede ver otra publicación mía: la versión mágica actualizada de JQuery Custom Binking.
QA
1. ¿Es posible no usar fachada o modo de sandbox similar?
Aunque el esquema de la arquitectura propone que la fachada puede implementar las funciones de verificación de autorización, en realidad es completamente posible que los mediadores puedan hacerlo. Lo que la arquitectura de luz debe hacer es casi lo mismo, es decir, desacoplar y garantizar que cada módulo se comunique directamente con el núcleo de la aplicación está bien.
2. Ha mejorado que el módulo no puede depender directamente. ¿Significa que no puede confiar en ninguna biblioteca de terceros (como jQuery)?
Este es en realidad un problema de dos lados. Como mencionamos anteriormente, un módulo puede tener algunos submódulos, o módulos básicos, como clases básicas de herramientas de operación DOM, etc. En este nivel, podemos usar una biblioteca de terceros, pero asegúrese de que podamos reemplazarlos fácilmente.
3. Me gusta esta arquitectura y quiero comenzar a usar esta arquitectura. ¿Hay alguna muestra de código a la que se pueda usar?
Planeo hacer una muestra de código para su referencia, pero antes de eso, puede consultar el JavaScript modular de Andrew Burgees.
4. ¿Es factible si el módulo necesita comunicarse directamente con el núcleo de la aplicación?
Técnicamente, no hay ninguna razón por la cual los módulos no puedan comunicarse directamente con el núcleo de la aplicación ahora, pero para la mayoría de las experiencias de aplicación, todavía no está permitido. Como ha elegido esta arquitectura, debe cumplir con las reglas definidas por la arquitectura.
Expresiones de gratitud
Gracias a Nicholas Zakas por la publicación original, para resumir las ideas juntos, a Andree Hansson por su revisión técnica, a Rebecca Murphey, Justin Meyer, John Hann, Peter Michaux, Paul Irish y Alex Sexton, todos proporcionaron mucha información relacionada con esta sesión.