Es un paradigma enfocado en el trabajo con flujos de datos finitos o infinitos de manera asíncrona, es decir que las aplicaciones reaccionan a los cambios ejecutando una serie de eventos.
Este paradigma está enfocado principalmente en el manejo de flujos de datos asíncronos y en el uso eficiente de recursos. Los sistemas reactivos reaccionan a los datos que fluyen continuamente ejecutando una serie de eventos, esto es porque siguen el patrón de diseño Observer; cuando hay un cambio de estado en un objeto, los otros objetos son notificados y actualizados. Por lo tanto, en lugar de estar preguntando los cambios, los eventos se realizan de forma asíncrona para que los observadores puedan procesarlos.
La motivación detrás de este nuevo paradigma procede de la necesidad de responder a las limitaciones de escalado presentes en los modelos de desarrollo actuales, que se caracterizan por su desaprovechamiento del uso de la CPU debido al I/O, el sobreuso de memoria (enormes thread pools) y la ineficiencia de las interacciones bloqueantes.
Para el año 2018, la programación reactiva y la programación basada en eventos no eran paradigmas de programación, como la programación imperativa u orientada a objetos, sino que eran ortogonales a ellos. La programación dirigida por eventos se implementa dentro de un paradigma paradigma existente. Por lo tanto, se puede utilizar la programación orientada a eventos con un lenguaje orientado a objetos o un lenguaje funcional. La programación reactiva es un caso específico de la programación de eventos que con el paso de los años ha ido ganando importancia. Esto se puede ver en la siguiente figura:
Flujo de datos: Son datos que se van modificando cada cierto tiempo, y que puede tener interés observar en tiempo real. A diferencia de los procesos por lotes, donde los datos se recopilan y procesan en bloques, el data streaming permite la ingestión y procesamiento continuo de datos a medida que estos se generan.
Observable: Un componente que puede ser observado, y que se encargará de informar cuando ese flujo de datos se modifique.
Observador: Es el elemento que observa esas modificaciones. Cuando el dato se modifica, se notifica al componente que lo está utilizando. Normalmente este observer necesita suscribirse cuando quiere empezar a recibir datos, y desuscribirse cuando ya no le interesan más esos datos.
Dispatchers: En cada framework de programación reactiva se llaman de una forma distinta, pero básicamente son un conjunto de hilos donde se van a ejecutar las operaciones, y unas reglas que optimizan su uso para ser lo más eficientes posibles.
Operadores: Son funciones que se aplican a streams de datos haciendo uso de la programación funcional. Implementan soluciones a problemas comunes en el procesamiento de streams como agregar, filtrar, mapear. Existen montones de operadores que nos permiten modificar y combinar flujos de datos, y conocerlos todos es muy complicado. Dependen de las librerías.
Basado en datos que fluyen continuamente, los sistemas reactivos reaccionan a los datos ejecutando una serie de eventos.
La programación reactiva sigue el patrón de diseño Observer; cuando hay un cambio de estado en un objeto, los otros objetos son notificados y actualizados acorde. Por lo tanto, en lugar de sondear eventos para los cambios, los eventos se realizan de forma asíncrona para que los observadores puedan procesarlos.
Utilizando E/S asíncrona, la idea es simple: disminuir el uso ineficiente de recursos usando recursos que de lo contrario estarían inactivos, ya que permanecen a la espera de actividad de E/S.
Los nuevos datos se notifican a los clientes en vez de tener que solicitarlos, debido a que la E/S asíncrona invierte el diseño normal del procesamiento de E/S. Este enfoque libera al cliente para hacer otras cosas mientras espera nuevas notificaciones.
Existe el riesgo de que demasiadas notificaciones desborden al cliente.
Un aspecto fundamental de control de flujo en sistemas distribuidos es que el cliente debe ser capaz de rechazar el trabajo que no puede manejar. En la programación reactiva, la capacidad del cliente para señalizar cuánto trabajo puede manejar se llama contrapresión.
En este patrón, tenemos un objeto Observable al que podemos suscribirnos, y cada vez que haya un cambio en su valor seremos informados. A esto se le conoce como Publicador-Suscriptor.
Analogía del patrón observador de la vida cotidiana: suscripción al boletín de un portal técnico
El patrón Observer trabaja con dos tipos de actores: por un lado, el sujeto, es decir, el objeto cuyo estado quiere vigilarse a largo plazo. Por otro lado, están los objetos observadores, que han de ser informados de cualquier cambio en el sujeto. Sin el patrón Observer, los objetos observadores tendrían que solicitar al sujeto regularmente que les enviase actualizaciones acerca de su estado (status updates). Cada una de estas solicitudes conllevaría tiempo de computación y requeriría, además, ciertos recursos de hardware.
En la programación asíncrona clásica, un hilo que se ejecuta pasa la mayor parte de su tiempo esperando. El hilo que se ejecuta envía una petición, por ejemplo, a la base de datos, luego espera durante un periodo de tiempo la respuesta con los datos, cuando finalmente obtiene una respuesta, continúa trabajando y al finalizar vuelve a estar disponible para otra ejecución. Lo que hace que este recurso se esté usando de forma ineficiente.
En la programación reactiva cada hilo se centra en enviar la solicitud, y luego vuelve a estar disponible para otra ejecución. Cuando la respuesta llega, este mismo hilo, u otro, puede recoger y procesar la respuesta. En pocas palabras: trata de asegurarse de que todos los hilos estén siempre trabajando en algo, y no esperando.
La utilización eficiente de los recursos deriva en gastar menos dinero en servidores y centros de datos. La promesa de la programación reactiva es que se puede hacer más con menos. Específicamente se puede procesar cargas de trabajo más altas con menos hilos.
La combinación de flujos con potentes operadores resuelve problemas complejos de una manera muy declarativa. El código parecerá conciso y directo; en lugar de ramificaciones verbales y lógica imperativa, se tienen combinaciones de operadores que facilitan hacerse una imagen mental del funcionamiento. Lo cuál, hace más sencillo que cualquier persona diferente al desarrollador original, pueda modificar o mejorar algún aspecto en el código más rápido.
Usando programación reactiva se obtiene una implementación débilmente acoplada, que tiende a aislar los fallos y que tiene la capacidad de escalar horizontalmente y de forma rápida, permitiendo el manejo de grandes cantidades de eventos, que pueden ser millones o billones de eventos, muy útil para “Big Data”.
Se pueden dar situaciones donde un Notificador genere más elementos de los que un Suscriptor puede consumir. Lo cual genera que el proceso de convertir esa entrada en salida se resista de alguna manera. En la mayoría de los casos esa resistencia es la velocidad de cálculo.
Para manejar estas situaciones en la programación reactiva se han establecido los siguientes mecanismos: Los suscriptores pueden indicar el número de datos que quieren o pueden procesar, de manera que el notificador nunca les enviará más de n cantidad de elementos. Los notificadores pueden aplicar diferentes operaciones como buffers o descartar algunos datos, para evitar saturar a los suscriptores lentos.
Backpressure es una solución que implementa el modelo Pull o el patrón de diseño Iterador. Así, hoy día el patrón la programación reactiva implementa dos patrones de diseño : Observer e Iterador
Lograr los comportamientos que se logran de forma fácil en el paradigma reactivo, resultan muy complicados y con el uso de artefactos complicados en otros paradigmas de programación.
Esta facilidad de implementación se puede evidenciar por la relativa rapida acogida de los componentes reactivos en tecnologías de Front-End, interfaces de usuario y hasta gestores de carga y replicacion en entornos de Cloud.
Este paradigma es más costoso en memoria, porque requiere mayor espacio en memoria para almacenar los flujos de datos (ya que se basa en flujos a lo largo del tiempo).
La curva de aprendizaje es grande para dominar la programación reactiva. No sólo se está expuesto a un ecosistema completamente nuevo con nuevas APIs, sino que también se necesita tiempo para procesar este paradigma diferente de programación con streams, que puede ser bastante diferente de un estilo de código de escritura tradicional (por ejemplo, en comparación con la programación imperativa). También puede que se necesite aprender de nuevas herramientas para las pruebas unitarias y dominar conceptos adicionales como los diagramas de mármol, que ayudan a modelar adecuadamente los flujos de datos. Además, hay una falta de recursos buenos y sencillos para aprender.
Del mismo modo que en la programación clásica donde nos podemos encontrar con un espagueti de funciones. En la programación reactiva también se puede encontrar un espagueti de flujos y no saber qué camino tomar. Con las funciones simples suele ser más sencillo hacer una depuración del código, dado que se componen secuencialmente. Con los flujos, puede que no sea tan sencillo porque no existe tal cosa como un flujo que invoca a otro flujo. En su lugar, se tiene un flujo que se conecta con otros flujos de maneras mixtas dependiendo de los operadores que los unen.
Los sistemas reactivos pueden acumular fácilmente retrasos debido a un número excesivo de procesos vinculados al flujo.
Los orígenes de la programación reactiva se remontan, probablemente, a la década de 1970,
pero esta empezó a resonar en la década del 2010, al mismo tiempo que comenzó el auge de
los microservicios y los procesadores multinúcleo.
Desde entonces, dicho paradigma ha evolucionado de manera significativa y, por este motivo,
las librerías que lo implementan pueden clasificarse en generaciones de acuerdo a su grado
de madurez, según la categorización propuesta por el autor
David Karnok en el año 2016, la cual se describe a continuación:
En las primeras aplicaciones de GUI, la interfaz se actualizaba solo después de una acción del usuario,
como hacer clic en un botón. El núcleo de la aplicación era un bucle de eventos que esperaba sincrónicamente la
entrada del usuario, lo que hacía que la aplicación se colgara si no había interacción.
La solución es desacoplar el manejo de eventos de la actualización de la GUI, utilizando una cola de eventos
y un procesamiento paralelo. En este patrón productor-consumidor, un hilo maneja la entrada del usuario y coloca
eventos en la cola, mientras otro hilo consume estos eventos y actualiza la GUI.
Consiste, principalmente, de la API java.util.Observable y de otras API basadas en
callbacks, tal como addXXXListener en Swing, AWT y Android.
Los inconvenientes que presentaban las herramientas de esta generación eran las
deficiencias de composición y el hecho de que, por sí mismas, resultaban bastante limitadas.
Una vez que Erik Meijer y el equipo de Microsoft reconocieron y abordaron las deficiencias,
nació la primera generación de bibliotecas de programación reactiva: Rx.NET alrededor de
2010, Reactive4Java en 2011 y las primeras versiones de RxJava en 2013.
Algunos de los inconvenientes encontrados consistieron en que, al implementar las interfaces
IObservable/IObserver no se podían cancelar las secuencias en ejecución usando
el operador take(), además del problema de la falta de backpressure.
El equipo de RxJava identificó estas deficiencias y se diseñó una nueva arquitectura. En
esta se introdujo: la clase Subscriber, la cual puede decir si está interesada
en más eventos o no; la interfaz Producer, para señalar la cantidad de elementos
que un Subscriber puede procesar a la vez, y el método lift(), que permite una
transformación funcional entre Subscribers.
No obstante, esta solución era un poco torpe y limitaba algunas optimizaciones, además
de que era incompatible con los puntos de vista de otras bibliotecas reactivas que
comenzarían a surgir más adelante.
Ingenieros de varias compañías se juntaron y crearon la especificación Reactive Streams. Algunos ejemplos de librerías que pertenecen a esta generación son RxJava 2.x, Project Reactor y Akka-Streams.
Algunas de estas librerías se reimplementaron, lo cual condujo al establecimiento de la librería reactive-streams-commons, a la construcción de ciertos operadores fundacionales y al diseño de componentes de optimización que pasaron a recibir el nombre de operator-fusion. Comparada con la generación anterior, aunque lucen similares en el exterior, en el interior poseen cambios significativos que permitieron una reducción aún mayor de los gastos generales.
Adicionalmente, este autor especula que, de la quinta generación en adelante, la arquitectura de Reactive-Streams requeriría ciertas extensiones para soportar operaciones reactivas de entrada y salida en la forma de secuencias bidireccionales, entre otros cambios que, en ese punto, estaban abiertos a discusión.
La programación reactiva, al tratarse de un paradigma emergente que está en constante actualización, suele confundirse con otros conceptos que también llevan la partícula "reactive" en su nombre. Este término es muy amplio y, aunque algunas personas pueden creer que las extensiones reactivas, los streams reactivos, los sistemas reactivos, y la programación funcional reactiva (entre otras muchas) sean lo mismo, la verdad es que existen diferencias importantes a considerar en todas ellas.
Es un paradigma de programación que combina los principios de la programación funcional con el manejo de datos que cambian a lo largo del tiempo de manera continua. En lugar de trabajar con valores discretos emitidos a lo largo del tiempo, como en la programación reactiva tradicional, la FRP se enfoca en representar y manipular valores que pueden variar continuamente. Este enfoque permite describir comportamientos dinámicos y sistemas interactivos de forma declarativa, facilitando el desarrollo de aplicaciones como animaciones, simulaciones y gráficos interactivos.
Fue definida en 1997 por Conal Elliott y Paul Hudak. De acuerdo con una presentación que Elliott dio en el año 2015, titulada "The essence and origins of FRP", el término había sido empleado incorrectamente para describir sistemas como Elm, Bacon y extensiones reactivas. La diferencia principal entre la FRP y la programación reactiva es que la primera opera en valores que cambian continuamente a través del tiempo, mientras que la segunda opera en valores discretos que se emiten a través del tiempo. La conferencia puede verse a continuación:
Las extensiones reactivas, mejor conocidas como "ReactiveX" son un conjunto de
herramientas que implementan el paradigma de la programación reactiva (estas se cubrirán
a detalle más adelante).
Sin embargo, debido a que estas contienen una gran variedad de librerías y a la falta
de interoperabilidad entre ellas, surgieron los Reactive Streams. Esta fue una
iniciativa creada para proveer un estándar para las extensiones reactivas y
que lidiara con el procesamiento de flujo (stream) asincrónico con contrapresión
sin bloqueo (non-blocking backpressure); es decir, se buscó unificar las
librerías ya existentes.
of: Crea un stream a partir de una lista de elementos.
from: Convierte varios tipos de datos (arrays, promesas, iterables) en streams.
interval: Emite números secuenciales a intervalos de tiempo específicos.
timer: Emite un valor después de un tiempo determinado.
merge: Combina múltiples streams emitiendo todos los valores a medida que ocurren.
concat: Emite todos los valores de un stream y luego continúa con el siguiente.
combineLatest: Combina múltiples streams emitiendo el último valor de cada uno cada vez que uno de los streams emite.
zip: Combina valores de múltiples streams en forma de tuplas, emitiendo cada vez que cada stream ha emitido un valor.
map: Aplica una función a cada valor emitido por el stream.
scan: Acumula valores emitidos utilizando una función acumuladora, similar a reduce
en arreglos.
buffer: Agrupa los valores emitidos en arrays.
filter: Emite solo los valores que cumplen con una condición específica.
debounceTime: Emite un valor solo si ha pasado una cierta cantidad de tiempo desde la última emisión.
distinctUntilChanged: Emite valores solo si son diferentes del valor anterior.
share: Convierte un stream en un stream multicast compartido entre suscriptores.
publish: Convierte un stream en un connectable observable que puede ser controlado cuándo empezar a emitir.
refCount: Convierte un connectable observable en un observable regular que se suscribe y se desuscribe automáticamente basado en la cantidad de suscriptores.
Los sistemas reactivos son un conjunto de principios de diseño arquitectónico para construir sistemas modernos que estén bien preparados para satisfacer las crecientes demandas que enfrentan las aplicaciones hoy en día. Sus especificaciones se pueden encontrar en línea bajo el nombre de "Manifiesto Reactivo", tal como sigue a continuación:
Los Sistemas Reactivos son:
Responsivos: El sistema responde a tiempo en la medida de lo posible. La responsividad es la piedra angular de la usabilidad y la utilidad, pero más que esto, responsividad significa que los problemas pueden ser detectados con rapidez y tratados efectivamente. Los sistemas responsivos se enfocan en proveer tiempos de respuesta rápidos y consistentes, estableciendo límites superiores confiables para así proporcionar una calidad de servicio consistente. Este comportamiento consistente, a su vez, simplifica el tratamiento de errores, aporta seguridad al usuario final y fomenta una mayor interacción.
Resilientes: El sistema permanece responsivo frente a fallos. Esto es aplicable no sólo a sistemas de alta disponibilidad o de misión crítica - cualquier sistema que no sea resiliente dejará de ser responsivo después de un fallo. La resiliencia es alcanzada con replicación, contención, aislamiento y delegación. Los fallos son manejados dentro de cada componente, aislando cada componente de los demás, y asegurando así que cualquier parte del sistema pueda fallar y recuperarse sin comprometer el sistema como un todo. La recuperación de cada componente se delega en otro componente (externo) y la alta disponibilidad se asegura con replicación allí donde sea necesario. El cliente de un componente no tiene que responsabilizarse del manejo sus fallos.
Elásticos: El sistema se mantiene responsivo bajo variaciones en la carga de trabajo. Los Sistemas Reactivos pueden reaccionar a cambios en la frecuencia de peticiones incrementando o reduciendo los recursos asignados para servir dichas peticiones. Esto implica diseños que no tengan puntos de contención o cuellos de botella centralizados, resultando en la capacidad de dividir o replicar componentes y distribuir las peticiones entre ellos. Los Sistemas Reactivos soportan algoritmos de escalado predictivos, así como Reactivos, al proporcionar relevantes medidas de rendimiento en tiempo real. La elasticidad se consigue de forma rentable haciendo uso de plataformas con hardware y software genéricos.
Orientados a Mensajes: Los Sistemas Reactivos confían en el intercambio de mensajes asíncrono para establecer fronteras entre componentes, lo que asegura bajo acoplamiento, aislamiento y transparencia de ubicación. Estas fronteras también proporcionan los medios para delegar fallos como mensajes. El uso del intercambio de mensajes explícito posibilita la gestión de la carga, la elasticidad, y el control de flujo, gracias al modelado y monitorización de las colas de mensajes en el sistema, y la aplicación de back-pressure cuando sea necesario. La mensajería basada en ubicaciones transparentes como medio de comunicación permite que la gestión de fallos pueda trabajar con los mismos bloques y semánticas a través de un clúster o dentro de un solo nodo. La comunicación No-bloqueante permite a los destinatarios consumir recursos sólo mientras estén activos, llevando a una menor sobrecarga del sistema.
Publicado en septiembre 16 2014. (v2.0) El Manifiesto de Sistemas Reactivos.
Esta es uno de los conceptos que suele causar más confusiones, debido al hecho de que usar
programación reactiva no necesariamente conduce a la formación de sistemas reactivos. Aunque
el paradigma sí es útil para satisfacer ciertos requerimientos enunciados en el manifiesto, hace
falta considerar algunos puntos:
De acuerdo al white paper "Reactive Programming versus Reactive Systems", escrito por
Jonas Bonér y Viktor Clang,
la programación reactiva es, generalmente, dirigida por eventos, mientras que los sistemas
reactivos son dirigidos por mensajes. La principal diferencia entre ambos consiste en que los
mensajes son inherentemente dirigidos (siempre tienen un destino), mientras que los eventos no:
estos son tan solo señales emitidas por un componente al alcanzar cierto estado.
En un sistema dirigido por mensajes, los receptores esperan por la llegada de estos y reaccionan
a ellos, de lo contrario permanecen inactivos. Por otra parte, en un sistema dirigido por eventos,
los detectores de notificaciones están anclados a las fuentes de dichos eventos, de tal forma que
son invocados cuando el evento es emitido. En síntesis, un sistema dirigido por mensajes se centra
en los destinatarios, mientras que uno dirigido por eventos se enfoca en los emisores.
De este modo, el uso exclusivo de programación reactiva puede hacer que la resiliencia sea más
difícil de lograr, pues las callbacks suelen ser anónimas y, por ende, no direccionables.
Es decir que, si falla una de las cadenas del flujo de datos, entonces se debe reiniciar la cadena
y el cliente debe ser notificado (algo que no ocurre en un sistema dirigido por mensajes, que
tendría la capacidad de autorrecuperarse sin involucrar al cliente). Sin embargo, si se integra
este paradigma con una arquitectura reactiva, este termina siendo de gran utilidad a la hora
de construir sistemas reactivos.
Es un conjunto de herramientas que permiten que los programación imperativos operen en secuencias de datos independientemente de si los datos son síncronos o asincrónicos. Proporciona un conjunto de operadores de secuencia que operan en cada elemento de la secuencia. Es una implementación de programación reactiva y proporciona un modelo para que las herramientas se implementen en múltiples programación.
ReactiveX es una combinación de las mejores ideas del patrón Observer, el patrón Iterator y la programación funcional Reactiva.
Los siguientes lenguajes poseen una librería basada en ReactiveX que les permite pertenecer al paradigma de la Programación reactiva
Spring 5 incluye Spring WebFlux, que proporciona soporte de programación reactiva para aplicaciones web.
Spring WebFlux permitirá construir un servicio REST no bloqueante, de tal forma que se puedan hacer varias peticiones simultáneas y estas se procesen en paralelo.
Svelte presenta un enfoque nuevo para crear interfaces de usuario. Mientras los frameworks tradicionales como React y Vue hacen la mayor parte de su trabajo en el navegador, Svelte cambia ese trabajo a un paso de compilación que ocurre cuando se construye la aplicación.
Se podría decir que Svelte es un compilador que toma el código y genera JavaScript nativo que interactúa con el DOM directamente sin necesidad de un intermediario.
El siguiente ejemplo muestra una implementación pura en Java que busca simular un caso de programación reactiva, en el que en un hilo se simula el envío de un correo a una dirección de correo aleatoria y en otro hilo se simula la confirmación de la recepción de dicho email
Ahora, el mismo ejemplo pero usando RxJava
A continuación, veremos un ejemplo simple de reactividad en Javascript
Iniciamos definiendo dos funciones:
El siguiente ejemplo crea un observable que emite números secuenciales, uno cada 2 segundos, luego estos son capturados por el suscriptor y ejecutada la función según el caso
El siguiente ejemplo crea 2 Observables, cada uno de un único elemento, luego los combina realizando la suma de los valores y selecciona la respuesta como String en caso de que la suma sea par, esta combinación se muestra tanto haciendo uso de sintaxis basada en Queries como en sintaxis fluida
En el siguiente enlace se pueden encontrar algunos ejemplos proveidos por el equipo de RxViz.
https://rxviz.com/En el siguiente link se puede acceder a un repositorio que contiene el ejemplo presentado a continuación.
https://github.com/facaslo97/SvelteExampleEn las siguientes imagenes podemos observar como implementar una sencilla interfaz web para un servicio de libreria
Estructura del proyecto
En la carpeta source es donde se van a colocar todos los archivos con extensión .svelte que corresponden a componentes de la interfaz gráfica
Componente libro
La sintaxis de svelte es una extensión de HTML, CSS y JavaScript. Dentro de la etiqueta script se va a añadir toda la funcionalidad reactiva. En este caso declaramos 3 variables que corresponden a los campos título, precio y descripción.
Componente botón
En esta imagen podemos observar como se agregan los estilos CSS dentro de las etiquetas style. Adicionalmente todo lo que no esté dentro de una etiqueta style o una script es inmediatamente interpretado como contenido HTML para el componente. En este caso un botón cuyo atributo on:clic indica que el flujo de datos va a ser cambiado cuando se de un evento de clic. La etiqueta slot indica que se pueden anidar mas componentes svelte dentro de nuestro componente botón.
Componente app
El componente app es el componente central de la aplicación. Dentro de script se observa como se hace un llamado a los otros 2 componentes, libro y botón. De igual forma se declaran unas variables que corresponden a los campos del libro, una lista que va a contener componentes de tipo libro, así como 2 funciones que se van a encargar de actualizar la información según el flujo de datos. Observamos también que para hacer referencia a las variables reactivas del componente libro dentro del contenido HTML se encierra el nombre de la variable dentro de llaves. Svelte también permite usar condicionales y ciclos iterativos como se observa en la 3ra imagen.
Main.js
Este script es el que se encarga de actualizar el DOM de acuerdo al componente app que hemos definido con anterioridad.
Ejecución
Agregar un libro tras llenar los campos y pulsar el botón añadir actualiza inmediatamente la lista de libros sin tener que hacer ninguna petición a un servidor.
En el siguiente link se puede acceder a un repositorio que contiene el ejemplo presentado a continuación.
https://github.com/josmedinaca/calculadora-papiEn las siguientes imágenes podemos observar cómo implementar una Calculadora responsive que se encarga de darnos nuestro PAPI
Estructura del proyecto
Componente SubjectForm
Este componente se encarga de añadir la asignatura, asi como sus créditos, nota y si fue cancelada o no.
Componente SubjectsList
Este componente se encarga de mostrarnos a manera de tabla las asignaturas que hemos ido añadiendo para realizar nuestro cálculo de papi, de igual forma en esta sección se pueden eliminar asignaturas.
Componente app
El componente app es el componente central de la aplicación. Dentro de script se observa cómo se hace un llamado a los otros 2 componentes, SubjectForm y SubjectsList. En esta parte realizamos el cálculo del papi y lo imprimimos en la pantalla del usuario.
Ejecución
Podemos ver el papi despues de añadir 2 asignaturas y 1 de ellas fue cancelada.
Muchas empresas están utilizando esta forma de programación actualmente y con mucha razón. Como ya hemos señalado, permite crear aplicaciónes o sitios web de tal manera que ofrece una mejor experiencia de usuario. Resultados más suaves y rápidos provienen de este paradigma y hace que la interacción del usuario sea mucho mejor. Naturalmente, esto se traduce en clientes más felices y más ventas para el negocio.
Compañías como Netflix llevan años aplicando la programación reactiva para mejorar el rendimiento de sus aplicaciones, superando las limitaciones nativas de múltiples lenguajes. Reactivex y otras librerías les proporcionó la pieza que necesitaban para realizar la orquestación de microservicios, la implementación del patrón circuit breaker y demás mecanismos que permiten a sus desarrollos adoptar los principios descritos por el manifiesto reactivo.
Capital One rediseñó su aplicación de préstamos para automóviles en torno a los principios Reactivos para simplificar la compra y financiación de automóviles en línea. Los clientes pueden navegar por más de cuatro millones de automóviles de más de 12.000 concesionarios y precalificar el financiamiento en segundos, sin afectar las puntuaciones de crédito.
LinkedIn recurrió a los principios Reactivos para crear indicadores de presencia en tiempo real (indicadores en línea) para el medio billón de usuarios de su red social.
Verizon Wireless, operadores de la red 4G LTE más grande en Estados Unidos, redujo los tiempos de respuesta a la mitad utilizando los principios de Reactive en la actualización de su sitio web de comercio electrónico que soporta 146 millones de suscriptores que manejan 2.500 millones de transacciones al año.
Walmart Canada reconstruyó toda su aplicación web y pila móvil como un sistema Reactivo y vio un aumento del 20 por ciento en la conversión a ventas de tráfico web y un aumento del 98 por ciento en los pedidos móviles recortando los tiempos de carga de páginas en más de un tercio.
En Tenea, empresa que se dedica a implantar soluciones de negocio a través de las nuevas tecnologías, están trabajando hace más de 5 años con tecnologías como ActiveMQ, RabittMQ, Fuse Enterprise (componentes OSGI), mongoDB, ElasticSearch o Solr y, por supuesto, en orientación a eventos y en programación reactiva. Concretamente, en su motor de reglas IoT TeneaRules, que han miniaturizado para que corra sobre hardware de dominio público low cost (TP-Llink, Xiaomi), sobre el open source OpenWrt y cuya sintaxis declarativa y funcional les permite programar comportamientos asociados a los eventos del entorno: ES_DE(NOCHE)= , ALARMA(ON)= ; PUERTA,PRINCIPAL(ABIERTA)=, etc.
Jafar Husain, Desarrollador Senior en el equipo de Interfaz de Usuario de TV en Netflix comenta lo siguiente:
"Over the last year, Netflix has reinvented our client-server interaction model. One of the key building blocks of our platform is Microsoft’s open-source Reactive Extensions library (Rx). Netflix is a big believer in the Rx model, because Rx has made it much easier for us to build complex asynchronous programs."
Husain También menciona que actualmente Netflix es de las pocas compañías que utiliza la programación reactiva tanto en el servidor como en el cliente, sin embargo, no son la única: Felipe Lima, Miembro del equipos de desarrollo de Android en Airbnb, menciona por qué decidieron inclinarse hacia la programación reactiva mediante RxJava:
" It’s easy to switch back and forth between threads. It’s built right into the framework, Async can be very cumbersome and error-prone, and RxJava is one reason we you don’t need to do that anymore, and why you can compose different tasks together".
La programación reactiva se ha aplicado durante varios años en el Front-end Mediante el uso de cambios de estado en los diferentes componentes Reactive Programming for React Developers
Tras un periodo de desarrollo de software, la empresa dispondrá de una plataforma que crecerá hasta donde el éxito le acompañe, incrementando la complejidad del ya sofisticado entorno. Tanto si la plataforma es Java, C#, PHP, Python o Perl, el desarrollo corre el riesgo de convertirse en un monolito difícil de mantener y evolucionar. Los procesos inicialmente simples tienden a cubrir cada vez más variantes, en función de las necesidades definidas por Dirección, Marketing o el propio Product Owner.
En una situación como esta la solución más adoptada por los Arquitectos de Desarrollo es la de evolucionar hacia una arquitectura:
La arquitectura reactiva funcional es aquella en la que la inferencia son los EVENTOS. En este caso no hablamos de eventos de sistema, como los subsistemas de ventanas de los entornos gráficos (X11, Windows o Gnome), sino por eventos de negocio.
La reactividad ha aparecido no solo en la parte servidora: Spring, Vert.x, ya que afecta a la arquitectura de ejecución, sino que ha entrado para instalarse de forma definitiva en la parte cliente con implementaciones en Javascript: Reactjs liberada por Facebook al mundo open, Bacon.js o RxJS.
La importancia para las empresas radica en que se puede crear funcionalidad a partir de cualquier evento que se genere: alta_cliente, baja_cliente, venta_producto, así como la gestión de las operaciones: rotura_stock, paquetes_fuera_stock_minimo, alta_empleado, fin_promocion, envio_urgente, etc.
Esto permitirá interceptar el flujo de datos, crear bases de datos/registros y/o funcionalidades que multiplican las capacidades digitales de la empresa, creando una nueva especie de empresas más flexibles, más adaptadas a los nuevos escenarios y, por tanto, más competitivas.
La solución, que ya documentan empresas como Nginx y otros fabricantes, es evolucionar de aplicaciones MONOLITO a microservicios reactivos y funcionales con un roadmap bien definido, que acople el día a día de la empresa con la introducción de la arquitectura reactiva que ya usan empresas como Netflix u otras muchas.
En definitiva, ya estamos en el momento de marcar el rumbo hacia estas nuevas herramientas y entornos de desarrollo.
Aplicación en el backend: manejo de back-pressureSe dice que existe back-pressure cuando una aplicación no es capaz de soportar una gran cantidad de datos por falta de recursos, la mayoria de veces este problema esta relacionado a la velocidad computacional (Se procesando las entradas mas rapido que las salidas), la programación reactiva ayuda a manejar este problema notificando al servicio que nos esta enviando datos cuando el servicio que los recibe se queda sin recursos.
Aplicación en interoperabilidadEl patrón Observer y los sistemas de suscripción y dispatchers son excepcionales en el manejo de mensajes de interoperabilidad entre sistemas y componentes de un mismo sistema
Los mayores exponentes de esto son:
De manera general, la programación reactiva se implementa cuando una aplicación maneje un gran flujo de datos o tenga muchas fuentes de datos y que requiera de alguna manera la propagación de cambio en datos modulos y eventos., sin la programación reactiva estas aplicaciones pueden tener problemas relacionados a la sincronización de los datos y como se muestran en la interfaz grafica. Es comun usar la programación reactiva a la par con la programación orientada a objetos en casos donde la programación asincróna se vuelve dificil de entender y mantener. Es importante mencionar la concurrencia, tema en el cual partes de un programa son ejecutadas con cierta regularidad en desorden o en un orden parcial, estos se pueden comunicar entre ellos mientras se estan ejecutando, con la programación reactiva se mejora la concurrencia de las aplicaciones creando modelos asíncrono, no bloqueantes.
Testing de SoftwareMocks y Stubs Reactivos: En lugar de utilizar mocks tradicionales que imitan comportamientos estáticos, se pueden emplear mocks reactivos que emulen flujos de eventos dinámicos. Esto permite simular condiciones reales y complejas de manera más cercana.
Testing de Streams y Flujos de Datos: Dado que la FRP se centra en la manipulación de flujos de datos continuos, es útil para probar cómo los programas reaccionan a cambios en estos flujos. Los frameworks y herramientas diseñados para FRP facilitan la creación y manipulación de estos flujos durante el testing.
Propiedades y Leyes de Comportamiento: La FRP promueve el diseño de programas en términos de propiedades y leyes de comportamiento, en lugar de pruebas unitarias tradicionales. Esto facilita la especificación y verificación de comportamientos complejos a lo largo del tiempo.
Testing de Interacciones Complejas: En aplicaciones donde múltiples eventos y estados deben coordinarse de manera precisa, la FRP proporciona herramientas para modelar y verificar estas interacciones de manera declarativa y concisa.
Simulación de Entornos Dinámicos: Al simular entornos dinámicos y eventos impredecibles, la FRP puede ayudar a asegurar que los programas reaccionen de manera correcta y predecible ante situaciones reales.
Algunos casos de uso moderno