Arquitectura Event-driven en Kotlin: de corrutinas a streams reactivos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Arquitectura Event-driven en Kotlin: por qué no es solo una moda pasajera

\n

Imagina que tu aplicación es un mecanismo perfectamente ajustado. Cada engranaje sabe cuándo girar, cada pistón cuándo moverse. Pero, ¿qué pasa si un día necesitas agregar una pieza nueva sin detener toda la máquina? En la arquitectura síncrona tradicional, esto a menudo se convierte en una pesadilla: reescribir módulos enteros, probar cadenas interminables de llamadas y noches sin dormir.

\n

Aquí entra en escena la arquitectura event-driven en Kotlin — un paradigma donde los componentes se comunican a través de eventos, no mediante llamadas directas. Kotlin, con sus corrutinas y streams reactivos, ofrece herramientas simplemente ideales para esto. En este artículo no solo hablaremos de teoría — escribiremos código real, analizaremos Kotlin Flow y Channels, y te mostraré cómo construir un sistema flexible y escalable que no se desmorone ante la primera carga.

\n\n

Qué es la arquitectura orientada a eventos en palabras sencillas

\n

En el enfoque clásico (imagina microservicios que se llaman entre sí por REST), cada solicitud es un vínculo rígido. El servicio A llama al servicio B, espera una respuesta, y si B falla, todo se rompe. En la arquitectura event-driven es diferente: los componentes publican eventos (por ejemplo, "Pedido creado") y se suscriben a ellos. Nadie espera a nadie, nadie llama a nadie directamente.

\n

La belleza de Kotlin es que permite implementar este modelo de forma nativa, sin necesidad de frameworks pesados. Las corrutinas proporcionan hilos ligeros, y Channel y Flow son buses de eventos listos para usar.

\n

Veamos un ejemplo muy simple: nuestro propio EventBus en Kotlin:

\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.channels.*\n\nclass SimpleEventBus {\n    private val events = Channel<Any>(Channel.UNLIMITED)\n\n    suspend fun publish(event: Any) {\n        events.send(event)\n    }\n\n    suspend fun subscribe(handler: suspend (Any) -> Unit) {\n        for (event in events) {\n            handler(event)\n        }\n    }\n}\n\n// Uso\nfun main() = runBlocking {\n    val bus = SimpleEventBus()\n    \n    launch {\n        bus.subscribe { event ->\n            println("Evento recibido: $event")\n        }\n    }\n    \n    delay(100)\n    bus.publish("¡Hola, Event-Driven!")\n    delay(100)\n}
\n\n

Este código es la base. Creamos un canal que funciona como una cola asíncrona. El publicador coloca un evento, el suscriptor lo recoge. Todo es simple, pero aquí ya se ve la fuerza de la arquitectura event-driven en Kotlin: el suscriptor y el publicador no saben nada el uno del otro.

\n\n

Kotlin Flow: streams reactivos para eventos

\n

Channel está bien, pero para proyectos reales a menudo se necesita más: streams fríos y calientes, transformaciones, manejo de errores. Aquí entra en juego Kotlin Flow — una biblioteca reactiva integrada directamente en el lenguaje.

\n

Flow es ideal para la programación asíncrona en Kotlin, cuando los eventos se generan constantemente. Por ejemplo, actualizaciones del tipo de cambio, feeds de noticias o estados de la interfaz de usuario.

\n\n

Streams fríos vs calientes

\n

Es importante entender la diferencia:

\n
    \n
  • Stream frío (Cold Stream) — solo comienza a funcionar cuando alguien se suscribe. Cada suscriptor recibe su propio flujo de datos.
  • \n
  • Stream caliente (Hot Stream) — funciona constantemente, independientemente de los suscriptores. Los suscriptores tardíos se pierden los eventos antiguos.
  • \n
\n

Para la arquitectura event-driven generalmente se necesitan streams calientes. En Kotlin se implementan mediante SharedFlow o StateFlow.

\n\n

Ejemplo — un sistema de notificaciones:

\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\ndata class Notification(val userId: String, val message: String)\n\nclass NotificationService {\n    private val _notifications = MutableSharedF                

Blogs

Book Recommendations