¿Los eventos solo se usan para la programación GUI?


57

¿Los eventos solo se usan para la programación GUI?

¿Cómo se maneja en la programación de backend normal cuando algo le sucede a esta otra cosa?


66
Por cierto, Event Source es un concepto completamente ortogonal a la programación de eventos. El concepto básico de Event Sourcing es que almacena "eventos" o "cambios" en su sistema, en lugar de almacenar el "estado" de su sistema. Por ejemplo, podría modelar su cuenta bancaria como a) Su saldo (ESTADO) ob) Una serie de Transacciones (FUENTE DE EVENTOS).
ArTs

44
Dependiendo del uso, un "evento" generalmente es solo una forma de devolución de llamada envuelta con azúcar. Las devoluciones de llamada se utilizan en todas partes; si está interesado, es probable que sea una buena palabra clave para comenzar una búsqueda.
J ...

10
También señalaré que incluso si va tan bajo como un microcontrolador, encontrará que las interrupciones de hardware son una característica útil y discutiblemente esencial. Ideal para sistemas de control o IO básico como una cafetera. Estas interrupciones de hardware realmente no son esencialmente diferentes de los eventos.
Dan

¡No! Ejemplo práctico: eventos de Nodejs
sampathsris

2
¿Estás en Windows? Echa un vistazo al Visor de eventos. Que te diviertas.
Marc.2377

Respuestas:


106

No. Son realmente útiles para implementar Observadores y asegurarse de que las clases estén cerradas a modificaciones.

Digamos que tenemos un método que registra nuevos usuarios.

public void Register(user) {
    db.Save(user);
}

Entonces alguien decide que se debe enviar un correo electrónico. Podríamos hacer esto:

public void Register(user) {
    db.Save(user);
    emailClient.Send(new RegistrationEmail(user));
}

Pero acabamos de modificar una clase que se supone que está cerrada a modificaciones. Probablemente esté bien para este pseudocódigo simple, pero probablemente sea el camino a la locura en el código de producción. ¿Cuánto tiempo hasta que este método tenga 30 líneas de código apenas relacionadas con el propósito original de crear un nuevo usuario?

Es mucho más agradable dejar que la clase realice su funcionalidad principal y generar un evento que indique a quien esté escuchando que un usuario estaba registrado, y pueden tomar cualquier acción que necesiten tomar (como enviar un correo electrónico).

public void Register(user) {
    db.Save(user);

    RaiseUserRegisteredEvent(user);
}

Esto mantiene nuestro código limpio y flexible. Una de las piezas de OOP que a menudo se pasan por alto es que las clases se envían mensajes entre ellas. Los eventos son estos mensajes.


37
Leí esto y pienso en nuestro código de "crear reserva" y lloro por un tiempo y anhelo por un lugar mejor: '(
sara

1
+1, gran respuesta. Solo una pregunta tangencial (esto me molestó un poco): ¿hay alguna razón especial para que haya comenzado los nombres de sus métodos (Registrarse, Guardar y Enviar) con letras mayúsculas? Por supuesto, esto no afecta la utilidad de esta respuesta, sin embargo.
Pedro A

14
@Hamsteriffic Soy principalmente un desarrollador de C # y esa es la convención generalmente aceptada. No hay otro motivo.
RubberDuck

66
@Hamsterifficas una adición, lo que usted llama lowerCase pero contiene una mayúscula en el medio a menudo se llama camelCase, porque tiene jorobas en el medio. Eso lo distingue de snake_case, donde las palabras en minúsculas están separadas por guiones bajos, lo cual es familiar para Python y la mayoría de los lenguajes de shell, por nombrar algunos.
Aaron

55
Los eventos son un tipo de estos mensajes, diría. Se supone que las llamadas a métodos también se consideran transmisión de mensajes.
jpmc26

53

No.

Un ejemplo clásico de los eventos que se utilizan en la lógica sin GUI son los desencadenantes de la base de datos.

Los disparadores son códigos que se ejecutan cuando ocurre un evento determinado (INSERT, DELETE, etc.). Me parece un evento.

Esta es la definición de evento de Wikipedia:

En informática, un evento es una acción o suceso reconocido por el software que puede ser manejado por el software. Los eventos de la computadora pueden ser generados o activados por el sistema, por el usuario o de otras maneras. Típicamente, los eventos se manejan sincrónicamente con el flujo del programa, es decir, el software puede tener uno o más lugares dedicados donde se manejan los eventos, con frecuencia un bucle de eventos. Una fuente de eventos incluye al usuario, que puede interactuar con el software mediante, por ejemplo, pulsaciones de teclas en el teclado. Otra fuente es un dispositivo de hardware como un temporizador. El software también puede activar su propio conjunto de eventos en el bucle de eventos, por ejemplo, para comunicar la finalización de una tarea. Se dice que el software que cambia su comportamiento en respuesta a eventos es impulsado por eventos, a menudo con el objetivo de ser interactivo.

No todos los eventos son generados por el usuario. Algunos son generados por un temporizador como un crontab de una base de datos INSERT como mencioné anteriormente.

La definición también establece que algunos programas o sistemas están "impulsados ​​por eventos, a menudo con el objetivo de ser interactivos" , de los cuales se puede deducir que el propósito o la utilidad de los eventos no son únicamente, sino más bien a menudo, para proporcionar interactividad (como las GUI) aunque no necesariamente GUI, ya que los programas CLI también pueden ser interactivos).


2
Siempre pienso en esto cuando escucho sobre los desencadenantes de la base de datos: thecodelesscode.com/case/42
Almo

Como ex desarrollador de DBA ahora me estremezco cada vez que escucho a la gente hablar sobre el uso de disparadores sin tener en cuenta el rendimiento más amplio de la base de datos.
Three Value Logic

27

La programación basada en eventos también se usa para la programación de servidores de alto rendimiento.

En una carga de trabajo de servidor típica, la mayor parte del tiempo que procesa un resultado proviene de E / S. Por ejemplo, extraer datos de una unidad de disco duro (7200 RPM) puede demorar hasta 8,3 ms. Para un procesador moderno de GHz, eso equivaldría a ~ 1 millón de ciclos de reloj. Si una CPU esperara los datos cada vez (sin hacer nada), perderíamos MUCHOS ciclos de reloj.

Las técnicas de programación tradicionales evitan esto mediante la introducción de múltiples hilos . La CPU intenta ejecutar cientos de subprocesos al mismo tiempo. Sin embargo, el problema que plantea este modelo es que, cada vez que una CPU cambia de hilo, requiere cientos de ciclos de reloj para cambiar de contexto . Un cambio de contexto es cuando la CPU copia la memoria local del hilo en los registros de la CPU y también almacena el registro / estado del hilo viejo en la RAM.

Además, cada subproceso debe utilizar una cierta cantidad de memoria para almacenar su estado.

Hoy, ha habido un impulso para los servidores que tiene un solo hilo, que se ejecuta en un bucle. Luego, las piezas de trabajo se envían a una bomba de mensajes , que actúa como una cola para el hilo único (al igual que en un hilo de la interfaz de usuario). En lugar de esperar a que termine el trabajo, la CPU establece un evento de devolución de llamada para cosas como el acceso al disco duro. Lo que reduce el cambio de contexto.

El mejor ejemplo de tal servidor es Node.js , que se ha demostrado que es capaz de manejar 1 millón de conexiones simultáneas con hardware modesto, mientras que un servidor Java / Tomcat tendría dificultades en unos pocos miles.


2
El "hardware modesto" es un poco engañoso. Necesitará 8GB + para Node, además de lo que utilice el sistema operativo. Y si tiene tanta memoria, Tomcat puede manejar fácilmente unos pocos miles de conexiones. De acuerdo, hay una gran diferencia, pero no es 1000x.
Paul Draper

@PaulDraper no, no puede. Y no, no lo hace. Necesita 8GB + solo para la pila de 8000 hilos. Esa es la gran diferencia.
ArTs

3
@PaulDraper además de 8GB es muy modesto para los estándares del servidor. He trabajado en máquinas con 128 GB de RAM y ni siquiera están completamente cargadas. Los ram ram cuestan más que toda su máquina.
ArTs

depende del tamaño de tu stack. Oracle / OpenJDK tiene por defecto 1 MB en la mayoría de las plataformas para 64 bits y 512 KB para 32 bits. Si solo toma los valores predeterminados, estaría en lo correcto. Pero los valores predeterminados no son cómo llegar a las conexiones de nodo 1M;) De todos modos, 128K es suficiente; puedes salirte con la tuya con menos. Eso sería 1GB de espacio de pila para 8000 hilos.
Paul Draper

66
Estás equivocado. Incluso con el tamaño de pila predeterminado, solo necesita 8 GiB de memoria virtual . La memoria se confirma sobre la marcha según sea necesario. Por lo general, solo necesita una sola página por pila, a menos que realmente esté utilizando la memoria adicional. Y en la práctica, la mayoría de los subprocesos en dicho sistema solo tienen esas (generalmente) pilas de 64 kiB. El uso de memoria virtual es un gran problema en el sistema operativo de 32 bits, pero no tanto en 64 bits. Te encuentras con otros límites mucho antes, como el agotamiento del puerto TCP, por ejemplo :) ¿Y dónde crees que se almacenan esas "pseudo-pilas" de nodo? Así es, en el montón.
Luaan

10

Los eventos también se usan mucho en la programación de red (por ejemplo, Nginx) para evitar costosos bucles de espera ocupada y, en cambio, proporcionan una interfaz limpia para saber exactamente cuándo está disponible una determinada operación (E / S, datos urgentes, etc.). Esta también es una solución al problema de C10k .

La idea básica es proporcionar al sistema operativo un conjunto de sockets (es decir, conexiones de red) para monitorear eventos, todos ellos o solo algunos que le interesen particularmente (datos disponibles para leer, por ejemplo); cuando el sistema operativo detecte dicha actividad en uno de los sockets de la lista, recibirá una notificación del evento que estaba buscando por la API, que luego tendrá que determinar de dónde proviene y actuar en consecuencia .

Ahora, esta es una vista de bajo nivel y abstracta, además difícil de escalar. Sin embargo, hay muchos frameworks de nivel superior que se ocupan de eso de manera incluso multiplataforma: Twisted para Python, Boost.Asio para C ++ o liberant para C me vienen a la mente.


+1 "costosos bucles de espera ocupada": en otras palabras, es útil en cualquier proceso paralelo que implique cierta inactividad (espera), así como la sincronización entre dichos procesos (mensajes o eventos). Como gran parte del mundo real funciona.
fr13d

Es interesante descubrir que los sockets se diseñaron originalmente como una forma de IPC en una sola máquina, antes de que existieran las redes.

5

Los sistemas integrados casi siempre son inherentemente impulsados ​​por eventos, incluso si no están programados explícitamente como tales.

Estos eventos provienen de cosas como interrupciones de hardware, pulsaciones de botones, lecturas de período de analógico a digital, vencimientos de temporizadores, etc.

Los sistemas integrados de baja potencia tienen aún más probabilidades de estar controlados por eventos; pasan la mayor parte del tiempo durmiendo (CPU durmiendo en un modo de bajo consumo), esperando que algo suceda (ese "algo" es un evento).

Uno de los marcos más comunes y populares para sistemas integrados controlados por eventos es la Plataforma Cuántica (QP) (el QP también funciona bajo Linux, Windows y cualquier sistema operativo similar a Unix). Las máquinas de estado son un ajuste natural para la programación basada en eventos, como el programa no es "secuencial" en el sentido típico, más bien, es un conjunto de "devoluciones de llamada" que se invocan según el estado del sistema y el evento actual.


3

Mensajes del evento Gregor Hohpe.

Arquitecturas dirigidas por eventos Gregor Hohpe.

Arquitectura SEDA , Gales, Culler, Cervecero.

¿Cómo se maneja en la programación de backend normal cuando sucede algo?

La máquina de estados finitos es un enfoque común

Given(State.A)
When(Event.B)
Then(State.C)
    .and(Consequences.D)

2
1, esta no es realmente una respuesta coherente, y 2, FSM no son buenos ejemplos de uso de eventos.
whatsisname

1
FSM. Estoy seguro de que la religión pastafaria observa una serie de eventos ;-)
fr13d

0

En los sistemas integrados, los eventos ocurren durante las interrupciones. Hay muchas fuentes de interrupciones, desde temporizadores hasta E / S.

Además, RTOS también puede tener eventos. Un ejemplo es esperar un mensaje de otra tarea.


0

Para el sistema no incorporado, pero algo que estaba haciendo en C # era el sistema SCADA. Hubo muchos eventos vinculados a lo que estaba sucediendo en el almacén cuando la carga se descargó parte del evento generado por el sistema y otra parte estaba escribiendo un nuevo estado en la base de datos. Por supuesto, teníamos un cliente GUI, pero era solo para mostrar el estado de la base de datos que reflejaba el estado del almacén. Por lo tanto, era un software de servidor de fondo basado en eventos y subprocesos. Bastante desafiante de desarrollar.

https://en.wikipedia.org/wiki/SCADA

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.