Definición
Piensa en cómo funciona una sala de redacción de noticias. Cuando sucede algo importante, un anuncio de una celebridad, un marcador deportivo, noticias de última hora, el evento se transmite a todos los que les importa. El equipo de TV crea un paquete de video, el equipo web publica un artículo, el equipo de redes sociales publica actualizaciones, y el equipo de notificaciones envía alertas a los suscriptores. Nadie está coordinando a todos estos equipos en tiempo real; cada uno sabe su trabajo y reacciona independientemente cuando se enteran de un evento. Eso es la Arquitectura Orientada a Eventos en esencia.
La Arquitectura Orientada a Eventos (EDA por sus siglas en inglés) es una forma de diseñar sistemas de software donde los componentes se comunican produciendo y reaccionando a eventos en lugar de llamarse directamente entre sí. Un “evento” es simplemente algo que sucedió: un usuario se registró, se realizó un pedido, falló un pago, se subió un archivo. Cuando estos eventos ocurren, se transmiten a través del sistema, y cualquier componente que le importe puede escuchar y responder. El componente que genera el evento no necesita saber quién está escuchando ni qué harán con la información.
Este enfoque hace que los sistemas sean increíblemente flexibles y escalables. Agregar una nueva funcionalidad es tan simple como crear un nuevo componente que escuche los eventos relevantes, sin necesidad de modificar código existente. Si un componente es lento o falla, los demás siguen funcionando independientemente. Y como los eventos típicamente se almacenan (al menos temporalmente), puedes reproducirlos para depurar problemas, recuperarte de fallos o poner al día a nuevos sistemas con datos históricos.
Ejemplo
Escenario Real 1: Procesamiento de Pedidos en E-commerce Cuando haces un pedido en Amazon, el sistema genera un evento “PedidoRealizado”. De forma independiente y simultánea: el servicio de inventario reserva tus artículos, el servicio de pagos cobra a tu tarjeta, el servicio de envíos calcula opciones de entrega, el servicio de email envía confirmación, el motor de recomendaciones anota lo que compraste, y el servicio de analytics registra la venta. Estos servicios no se llaman entre sí, todos simplemente reaccionan al único evento.
Escenario Real 2: Notificaciones en Redes Sociales Cuando alguien da like a tu publicación de Instagram, se genera un evento “PublicaciónGustada”. El servicio de notificaciones lo ve y te envía una notificación push. El servicio de feed de actividad actualiza tu pestaña de actividad. El servicio de analytics incrementa el contador de likes. El servicio de moderación verifica patrones de actividad sospechosa. El sistema de reportes para anunciantes actualiza métricas de engagement. Un like, muchas reacciones independientes.
Escenario Real 3: Detección de Fraude Bancario Cuando pasas tu tarjeta de crédito, se dispara un evento “TransacciónIniciada”. El servicio de autorización decide aprobar/rechazar. El servicio de detección de fraude analiza la transacción contra tus patrones. El servicio de notificaciones te envía una alerta. El servicio de recompensas calcula tu cashback. La app de presupuesto (mediante open banking) categoriza tu gasto. Cada servicio es independiente, y la detección de fraude puede disparar su propio evento “ActividadSospechosa” al que otros servicios reaccionan.
Escenario Real 4: Automatización de Hogar Inteligente Cuando tu termostato inteligente detecta que has salido de casa, genera un evento “UsuarioSalióDeCasa”. El sistema HVAC ajusta la temperatura para ahorrar energía. El sistema de iluminación apaga las luces innecesarias. El sistema de seguridad se activa. El robot aspirador empieza a limpiar. La cámara de mascotas se activa. Cada dispositivo inteligente actúa sobre el mismo evento sin un controlador central orquestando todo.
Analogía
El Servicio de Noticias por Cable: Cuando algo sucede en el mundo, agencias de noticias como Reuters publican la historia en su cable. Cada periódico, estación de TV y sitio web se suscribe al cable y decide cómo cubrir la historia según sus propias prioridades. Reuters no le dice a CNN cómo cubrir las noticias, simplemente reportan lo que sucedió, y todos reaccionan según su rol.
El Pregonero del Pueblo: En tiempos medievales, cuando algo importante sucedía, el pregonero lo anunciaba en la plaza. El panadero podía escucharlo y ajustar su producción de pan. El mercader podía cambiar sus precios. Los guardias podían aumentar las patrullas. El posadero podía prepararse para viajeros. Un anuncio, muchas reacciones independientes, sin necesidad de coordinación.
El Sistema de Alarma contra Incendios: Cuando una alarma de incendio se activa en un edificio, muchas cosas suceden automáticamente sin que nadie coordine: los aspersores se activan, los ascensores bajan a planta baja, las puertas se desbloquean para evacuación, se notifica a los bomberos, los sistemas HVAC se ajustan para controlar el humo, y las luces de emergencia se encienden. Cada sistema reacciona al mismo evento independientemente.
La Respuesta del Ecosistema: En la naturaleza, cuando llueve (un evento), todo en el ecosistema responde independientemente. Las plantas absorben agua. Los animales salen a beber. Los arroyos se llenan. Las lombrices salen a la superficie. Los hongos se esparcen. Nadie coordina estas respuestas: cada organismo reacciona al evento según su naturaleza. EDA funciona de la misma manera.
Ejemplo de Código
// Productor de eventos
class OrderService {
async createOrder(orderData) {
const order = await db.orders.create(orderData);
// Emitir evento
await eventBus.publish('OrderPlaced', {
eventId: uuidv4(),
timestamp: new Date(),
data: {
orderId: order.id,
userId: order.userId,
items: order.items,
total: order.total
}
});
return order;
}
}
// Consumidores de eventos (diferentes servicios)
class InventoryService {
constructor() {
eventBus.subscribe('OrderPlaced', this.handleOrderPlaced);
}
async handleOrderPlaced(event) {
await this.reserveStock(event.data.items);
await eventBus.publish('InventoryReserved', {
orderId: event.data.orderId
});
}
}
class EmailService {
constructor() {
eventBus.subscribe('OrderPlaced', this.handleOrderPlaced);
}
async handleOrderPlaced(event) {
await this.sendConfirmation(event.data.userId, event.data.orderId);
}
}
class PaymentService {
constructor() {
eventBus.subscribe('InventoryReserved', this.handleInventoryReserved);
}
async handleInventoryReserved(event) {
await this.chargeCustomer(event.orderId);
}
}