He estado pasando devoluciones de llamada o simplemente activando las funciones de otra función en mis programas para hacer que las cosas sucedan una vez que se completen las tareas. Cuando algo termina, disparo la función directamente:
var ground = 'clean';
function shovelSnow(){
console.log("Cleaning Snow");
ground = 'clean';
}
function makeItSnow(){
console.log("It's snowing");
ground = 'snowy';
shovelSnow();
}
Pero he leído sobre muchas estrategias diferentes en programación, y una que entiendo que es poderosa, pero que aún no he practicado, está basada en eventos (creo que un método sobre el que leí se llamaba "pub-sub" ):
var ground = 'clean';
function shovelSnow(){
console.log("Cleaning Snow");
ground = 'clean';
}
function makeItSnow(){
console.log("It's snowing");
ground = 'snowy';
$(document).trigger('snow');
}
$(document).bind('snow', shovelSnow);
Me gustaría comprender las fortalezas y debilidades objetivas de la programación basada en eventos, en lugar de simplemente llamar a todas sus funciones desde otras funciones. ¿En qué situaciones de programación tiene sentido utilizar la programación basada en eventos?
event-programming
Visir
fuente
fuente
$(document).bind('snow', shovelShow)
. No es necesario envolverlo en una función anónima.Respuestas:
Un evento es una notificación que describe una ocurrencia del pasado reciente.
Una implementación típica de un sistema controlado por eventos utiliza un despachador de eventos y funciones de manejo (o suscriptores ). El despachador proporciona una API para conectar controladores a eventos (jQuery's
bind
) y un método para publicar un evento a sus suscriptores (trigger
en jQuery). Cuando habla de eventos IO o UI, también suele haber un bucle de eventos , que detecta nuevos eventos, como los clics del mouse, y los pasa al despachador. En JS-land, el navegador proporciona el despachador y el bucle de eventos.Para el código que interactúa directamente con el usuario, respondiendo a las pulsaciones de teclas y clics, la programación controlada por eventos (o una variación de la misma, como la programación reactiva funcional ) es casi inevitable. Usted, el programador, no tiene idea de cuándo o dónde hará clic el usuario, por lo que depende del marco de la GUI o del navegador detectar la acción del usuario en su bucle de eventos y notificar su código. Este tipo de infraestructura también se usa en aplicaciones de red (cf NodeJS).
Su ejemplo, en el que genera un evento en su código en lugar de llamar a una función directamente, tiene algunas compensaciones más interesantes, que analizaré a continuación. La principal diferencia es que el editor de un evento (
makeItSnow
) no especifica el receptor de la llamada; eso está conectado a otra parte (en la llamada abind
en su ejemplo). Esto se llama disparar y olvidar :makeItSnow
anuncia al mundo que está nevando, pero no le importa quién está escuchando, qué sucede después o cuándo sucede; simplemente transmite el mensaje y se quita el polvo de sus manos.Por lo tanto, el enfoque basado en eventos desacopla al remitente del mensaje del receptor. Una ventaja que esto le brinda es que un evento determinado puede tener múltiples controladores. Puede vincular una
gritRoads
función a su evento de nieve sin afectar elshovelSnow
controlador existente . Tiene flexibilidad en la forma en que su aplicación está conectada; para desactivar un comportamiento, solo necesita eliminar labind
llamada en lugar de buscar el código para encontrar todas las instancias del comportamiento.Otra ventaja de la programación basada en eventos es que le brinda un lugar para plantear inquietudes transversales. El despachador de eventos desempeña el papel de Mediador , y algunas bibliotecas (como Brighter ) utilizan una canalización para que pueda conectar fácilmente los requisitos genéricos, como el registro o la calidad de servicio.
Divulgación completa: Brighter se desarrolla en Huddle, donde trabajo.
Una tercera ventaja de desacoplar el remitente de un evento del receptor es que le brinda flexibilidad cuando maneja el evento. Puede procesar cada tipo de evento en su propio hilo (si su despachador de eventos lo admite), o puede colocar eventos generados en un intermediario de mensajes como RabbitMQ y manejarlos con un proceso asincrónico o incluso procesarlos en masa durante la noche. El receptor del evento podría estar en un proceso separado o en una máquina separada. ¡No tiene que cambiar el código que genera el evento para hacer esto! Esta es la gran idea detrás de las arquitecturas de "microservicios": los servicios autónomos se comunican mediante eventos, con el middleware de mensajería como la columna vertebral de la aplicación.
Para un ejemplo bastante diferente de estilo basado en eventos, mire el diseño controlado por dominio, donde los eventos de dominio se utilizan para ayudar a mantener los agregados separados. Por ejemplo, considere una tienda en línea que recomienda productos basados en su historial de compras. A
Customer
debe tener actualizado su historial de compras cuandoShoppingCart
se paga. ElShoppingCart
agregado puede notificar alCustomer
mediante unCheckoutCompleted
evento; laCustomer
obtendría actualizada en una transacción separada en respuesta al evento.El principal inconveniente de este modelo basado en eventos es la indirección. Ahora es más difícil encontrar el código que maneja el evento porque no puede navegar hasta él usando su IDE; debe averiguar dónde está vinculado el evento en la configuración y esperar que haya encontrado todos los controladores. Hay más cosas para tener en mente en cualquier momento. Las convenciones de estilo de código pueden ayudar aquí (por ejemplo, colocar todas las llamadas
bind
en un archivo). Por el bien de su cordura, es importante usar solo un despachador de eventos y usarlo de manera consistente.Otra desventaja es que es difícil refactorizar eventos. Si necesita cambiar el formato de un evento, también debe cambiar todos los receptores. Esto se exacerba cuando los suscriptores de un evento están en máquinas diferentes, porque ahora necesita sincronizar las versiones de software.
En ciertas circunstancias, el rendimiento puede ser una preocupación. Al procesar un mensaje, el despachador debe:
Esto es ciertamente más lento que una llamada de función normal, lo que solo implica empujar un nuevo marco en la pila. Sin embargo, la flexibilidad que le brinda una arquitectura basada en eventos hace que sea mucho más fácil aislar y optimizar el código lento. Tener la capacidad de enviar trabajo a un procesador asíncrono es una gran victoria aquí, ya que le permite atender una solicitud de inmediato mientras el trabajo duro se trata en segundo plano. En cualquier caso, si está interactuando con el DB o dibujando cosas en la pantalla, los costos de IO reducirán totalmente los costos de procesamiento de un mensaje. Se trata de evitar la optimización prematura.
En resumen, los eventos son una excelente manera de construir software acoplado libremente, pero no están exentos de costos. Sería un error, por ejemplo, reemplazar cada llamada de función en su aplicación con un evento. Use eventos para hacer divisiones arquitectónicas significativas.
fuente
La programación basada en eventos se usa cuando el programa no controla la secuencia de eventos que realiza. En cambio, el flujo del programa está dirigido por un proceso externo como un usuario (por ejemplo, GUI), otro sistema (por ejemplo, cliente / servidor) u otro proceso (por ejemplo, RPC).
Por ejemplo, un script de procesamiento por lotes sabe lo que debe hacer, por lo que simplemente lo hace. Es no basado en eventos.
Un procesador de texto se sienta allí y espera a que el usuario comience a escribir. Las pulsaciones de teclas son eventos que activan la funcionalidad para actualizar el búfer interno del documento. El programa no puede saber lo que desea escribir, por lo que debe estar controlado por eventos.
La mayoría de los programas GUI están controlados por eventos porque se basan en la interacción del usuario. Sin embargo, los programas basados en eventos no se limitan a las GUI, ese es simplemente el ejemplo más familiar para la mayoría de las personas. Los servidores web esperan que los clientes se conecten y siguen un lenguaje similar. Los procesos en segundo plano en su computadora también pueden responder a eventos. Por ejemplo, un escáner de virus a pedido puede recibir un evento del sistema operativo con respecto a un archivo recién creado o actualizado, luego escanear ese archivo en busca de virus.
fuente
En una aplicación basada en eventos, el concepto de oyentes de eventos le dará la capacidad de escribir aún más aplicaciones acopladas libremente .
Por ejemplo, un módulo o complemento de un tercero puede eliminar un registro de la base de datos y luego activar el
receordDeleted
evento y dejar el resto a los oyentes del evento para que hagan su trabajo. Todo funcionará bien, aunque el módulo de activación ni siquiera sabe quién está escuchando este evento en particular o qué debería suceder a continuación.fuente
Una analogía simple que quería agregar que me ayudó:
Piense en los componentes (u objetos) de su aplicación como un gran grupo de amigos de Facebook.
Cuando uno de tus amigos quiere decirte algo, puede llamarte directamente o publicarlo en su muro de Facebook. Cuando lo publican en su Facebook, cualquiera puede verlo y reaccionar, pero mucha gente no lo ve. A veces es algo importante que las personas probablemente necesiten reaccionar, como "¡Vamos a tener un bebé!" o "¡La banda está haciendo un concierto sorpresa en el bar Drunkin 'Clam!". En el último caso, entonces el resto de los amigos probablemente tendrán que reaccionar, especialmente si están interesados en esa banda.
Si su amigo quiere mantener un secreto entre usted y ellos, probablemente no lo publicarán en su muro de Facebook, lo llamarán directamente y se lo dirán. Imagine un escenario en el que le dice a una chica que le gusta que le gustaría encontrarse con ella en un restaurante para una cita. En lugar de llamarla directamente y preguntarle, lo publica en su muro de Facebook para que lo vean todos sus amigos. Esto funciona, pero si tienes un ex celoso, entonces ella podría ver eso y aparecer en el restaurante para arruinarte el día.
Cuando decida si desea construir o no oyentes de eventos para implementar algo, piense en esta analogía. ¿Este componente necesita poner su negocio a la vista de todos? ¿O necesitan llamar a alguien directamente? Las cosas pueden complicarse con bastante facilidad, así que ten cuidado.
fuente
La siguiente analogía podría ayudarlo a comprender la programación de E / S impulsada por eventos dibujando un paralelo a la línea de espera en el mostrador de Recepción del Doctor.
Bloquear E / S es como, si estás parado en la cola, la recepcionista le pide a un chico frente a ti que complete el formulario y ella espera hasta que él termine. Tienes que esperar tu turno hasta que el chico termine su forma, esto está bloqueando.
Si el hombre soltero tarda 3 minutos en completarse, el décimo hombre tiene que esperar hasta 30 minutos. Ahora, para reducir este décimo tiempo de espera, la solución sería aumentar el número de recepcionistas, lo cual es costoso. Esto es lo que sucede en los servidores web tradicionales. Si solicita una información de usuario, la solicitud posterior de otros usuarios debe esperar hasta que se complete la operación actual, ir a buscar desde la base de datos. Esto aumenta el "tiempo de respuesta" de la décima solicitud y aumenta exponencialmente para el enésimo usuario. Para evitar esto, los servidores web tradicionales crean un subproceso (equivalente a un número creciente de recepcionistas) para cada solicitud individual, es decir, básicamente, crea una copia del servidor para cada solicitud, lo cual es costoso en términos de consumo de CPU, ya que cada solicitud necesitará un sistema operativo hilo. Para ampliar la aplicación,
Impulsado por eventos : El otro enfoque para ampliar el "tiempo de respuesta" de la cola es optar por un enfoque impulsado por eventos, donde los que están en la cola recibirán el formulario, se les pedirá que completen y regresen al finalizar. Por lo tanto, recepcionista siempre puede tomar la solicitud. Esto es exactamente lo que ha estado haciendo JavaScript desde su inicio. En el navegador, javascript respondería al evento de clic del usuario, desplazamiento, desplazamiento o búsqueda de la base de datos, etc. Esto es posible en JavaScript inherentemente, porque JavaScript trata las funciones como objetos de primera clase y se pueden pasar como parámetros a otras funciones (llamadas devoluciones de llamada), y se pueden invocar al completar una tarea en particular. Esto es exactamente lo que hace node.js en el servidor. Puede encontrar más información sobre programación dirigida por eventos y bloqueo de E / S, en el contexto del nodo aquí
fuente