javascript - ¿Diferencia entre declarativo e imperativo en React.js?
Recientemente he estado estudiando mucho sobre la funcionalidad y las formas de usar la biblioteca de JavaScript de Facebook React.js. Al hablar de sus diferencias con el resto del mundo de JavaScript, a menudo se mencionan los dos estilos de programación declarativo e imperativo.
¿Cuál es la diferencia entre ambos?
Respuesta #1
Un estilo declarativo, como el que tiene React, te permite controlar el flujo y el estado en tu aplicación diciendo "Debería verse así". Un estilo imperativo da vuelta eso y te permite controlar tu aplicación diciendo "Esto es lo que deberías hacer".
El beneficio de lo declarativo es que no te enfrentas a los detalles de implementación de la representación del estado. Estás delegando el componente organizativo de mantener las vistas de tu aplicación consistentes, por lo que solo tienes que preocuparte por el estado.
Imagina que tienes un mayordomo, que es una especie de metáfora de un marco de trabajo. Y te gustaría preparar la cena. En un mundo imperativo, le dirías paso a paso cómo preparar la cena. Debes proporcionar estas instrucciones:
Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table
En un mundo declarativo, simplemente describirías lo que quieres
I want dinner with chicken.
Si tu mayordomo no sabe cómo hacer pollo, entonces no puedes operar en un estilo declarativo. Al igual que si Backbone no sabe cómo mutarse a sí mismo para realizar una cierta tarea, no puedes simplemente decirle que haga esa tarea. React puede ser declarativo porque, por ejemplo, "sabe cómo hacer pollo". En comparación con Backbone, que solo sabe cómo interactuar con la cocina.
Ser capaz de describir el estado reduce drásticamente la superficie para errores, lo cual es un beneficio. Por otro lado, podrías tener menos flexibilidad en cómo ocurren las cosas porque estás delegando o abstraiendo cómo implementas el estado.
Respuesta #2
Imagina un componente de interfaz de usuario simple, como un botón de "Me gusta". Cuando lo tocas, se vuelve azul si antes era gris, y gris si antes era azul.
La manera imperativa de hacer esto sería:
if( user.likes() ) {
if( hasBlue() ) {
removeBlue();
addGrey();
} else {
removeGrey();
addBlue();
}
}
Básicamente, tienes que comprobar lo que está en la pantalla actualmente y manejar todos los cambios necesarios para volver a dibujarla con el estado actual, incluyendo deshacer los cambios del estado anterior. Puedes imaginar lo complejo que esto podría ser en un escenario del mundo real.
En contraste, el enfoque declarativo sería:
return this.state.liked ? <blueLike /> : <greyLike />;
Debido a que el enfoque declarativo separa las preocupaciones, esta parte de él solo necesita manejar cómo debería verse la interfaz de usuario en un estado específico, y por lo tanto es mucho más fácil de entender.
Respuesta #3
Es mejor comparar React (declarativo) y JQuery (imperativo) para mostrarte las diferencias.
En React, solo necesitas describir el estado final de tu interfaz de usuario en el método render(), sin preocuparte de cómo pasar del estado anterior de la interfaz de usuario al nuevo estado de la interfaz de usuario. Por ejemplo,
render() {
const { price, volume } = this.state;
const totalPrice = price * volume;
return (
<div>
<Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
<Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
<Label value={totalPrice} ... />
...
</div>
)
}
Por otro lado, JQuery requiere que transiciones el estado de tu interfaz de usuario de manera imperativa, por ejemplo, seleccionando los elementos de etiqueta y actualizando su texto y CSS:
updatePrice(price) {
$("#price-label").val(price);
$("#price-label").toggleClass('expansive', price > 100);
$("#price-label").toggleClass('cheap', price < 100);
// also remember to update UI depending on price
updateTotalPrice();
...
}
updateVolume(volume) {
$("#volume-label").val(volume);
$("#volume-label").toggleClass('high', volume > 1000);
$("#volume-label").toggleClass('low', volume < 1000);
// also remember to update UI depending on volume
updateTotalPrice();
...
}
updateTotalPrice() {
const totalPrice = price * volume;
$("#total-price-label").val(totalPrice);
...
}
En un escenario del mundo real, habrá muchos más elementos de la interfaz de usuario que deberán actualizarse, además de sus atributos (por ejemplo, estilos CSS y detectores de eventos), etc. Si haces esto de manera imperativa usando JQuery, se volverá complejo y tedioso; es fácil olvidar actualizar algunas partes de la interfaz de usuario, o olvidar eliminar manejadores de eventos antiguos (provocando fugas de memoria o que el manejador se ejecute varias veces), etc. Aquí es donde ocurren los errores, es decir, cuando el estado de la interfaz de usuario y el estado del modelo no están sincronizados.
Los estados desincronizados nunca ocurrirán con el enfoque declarativo de React, porque solo necesitamos actualizar el estado del modelo, y React es responsable de mantener sincronizados los estados de la interfaz de usuario y del modelo.
- Bajo el gancho, React actualizará todos los elementos DOM cambiados usando código imperativo.
También puedes leer mi respuesta a ¿Cuál es la diferencia entre el paradigma declarativo y el imperativo en la programación?
PD: a partir del ejemplo de jQuery anterior, puede que pienses, ¿y si ponemos todas las manipulaciones del DOM en un método updateAll(), y lo llamamos cada vez que cambie algún estado de nuestro modelo, y la interfaz nunca estará desincronizada? Tienes razón, y esto es efectivamente lo que hace React, la única diferencia es que updateAll() de jQuery causará muchas manipulaciones innecesarias del DOM, pero React solo actualizará los elementos del DOM que han cambiado usando su Algoritmo de Diferencias del DOM Virtual.
Respuesta #4
Esta es una gran analogía:
*Una respuesta imperativa: Sal por la salida norte del estacionamiento y gira a la izquierda. Incorpórate a la I-15 sur hasta llegar a la salida de Bangerter Highway. Toma a la derecha en la salida como si fueras a Ikea. Sigue recto y gira a la derecha en el primer semáforo. Continúa por el siguiente semáforo y luego toma la próxima a la izquierda. Mi casa es el #298.
Una respuesta declarativa: Mi dirección es 298 West Immutable Alley, Draper Utah 84020*
Fuente: https://tylermcginnis.com/imperative-vs-declarative-programming/
Respuesta #5
El código imperativo instruye a JavaScript sobre cómo debe realizar cada paso. Con el código declarativo, le decimos a JavaScript lo que queremos que se haga y dejamos que JavaScript se encargue de realizar los pasos.
React es declarativo porque escribimos el código que queremos y React se encarga de tomar nuestro código declarado y realizar todos los pasos de JavaScript/DOM para llevarnos a nuestro resultado deseado.
