Javascript permite un estilo de desarrollo tanto declarativo como imperativo, atendiendo asi a qué objetivo se busca alcanzar (declarativo) o extendiéndose sobre cómo se debe alcanzar un objetivo (imperativo).

Si bien las últimas incorporaciones del lenguaje muestran una tendencia hacia un paradigma claramente declarativo, ambos estilos coexisten en la industria actual y suponen diferencias a efectos de optimización, rendimiento, legibilidad o mantenibilidad de nuestras aplicaciones, entre otros.

La relación “declarativo === guay” es errónea: la idoneidad de cada paradigma depende de factores como el contexto en el que se implemente un desarrollo, el volumen de los datos a manejar o las prioridades vigentes en relación al equipo o la organización, entre otros.

¿Te resulta confusa esta introducción? Vuelve a ella tras haber leído este leído el artículo en su totalidad y, voilà! Verás que todo cuadra 🙂

Aplicación práctica: un reductor

Las características que diferencian una implementación imperativa frente a una declarativa son sensibles desde un contexto práctico, por lo que usaremos como base, por ejemplo, un sencillo reductor. Este ejemplo en código es la base perfecta sobre la que construir un concepto más amplio y teórico, asi que vamos a darle fuegote 🔥.

Esta sería una implementación imperativa de un reductor:


const arr = [2, 4, 6]
let acc = 0

for (let i = 0; i < arr.length; i++){
  acc += arr[i]
}

console.log(`El sumatorio resulta en ${acc}`)  
// El sumatorio resulta en 12

Frente a su equivalencia declarativa mediante una función personalizada arrayReduce():


const arr = [2, 4, 6]
const arraySum = arrayReducer(arr)

console.log(`El sumatorio resulta en ${arraySum}`)  
// El sumatorio resulta en 12

O su versión declarativa estándar a través del método .reduce() de ES6:


const arr = [2, 4, 6]
const arraySum = arr.reduce()

console.log(`El sumatorio resulta en ${arraySum}`)  
// El sumatorio resulta en 12

Diferencias entre programación imperativa y declarativa

Tal y como se observa en los ejemplos anteriores, los dos paradigmas persiguen el mismo objetivo, pero profundizar en sus diferencias nos lleva a un interesante análisis que va más allá del evidente ahorro de código:

    Optimización

    • Imperativa: supone un mayor volumen de código ya que la secuencia de instrucciones y estructuras necesarias queda expuesta en su totalidad.
    • Declarativa: dispone de sus procesos lógicos en capas inferiores a la que nos encontramos, resultando en códigos más livianos.

    Legibilidad

    • Imperativa: de baja legibilidad, se vale de recursos básicos del lenguaje que requieren de una curva de aprendizaje para implementarlos o interpretarlos, como es un bucle for.
    • Declarativa: de alta carga léxica, relega en su nombre la funcionalidad que persigue. Declara intencionalidad, haciéndola altamente legible e identificable. No podemos negarlo: el código que canta, nos encanta.

    Reusabilidad

    • Imperativa: la necesidad de replicar la secuencia de instrucciones allá donde su funcionalidad sea requerida le despoja de cualquier atisbo de reusabilidad.
    • Declarativa: la encapsulación de procesos permite reusarlos en múltiples escenarios.

    Abstracción

    • Imperativa: expone en nuestra capa de trabajo la lógica programática a través de la que se alcanza el objetivo.
    • Declarativa: abstrae el desarrollo lógico a capas inferiores, siendo accedido a través de una función con un nombre descriptivo. Podemos despreocuparnos de cómo lo hace, lo importante es qué hace.

    Mutación y efectos colaterales

    • Imperativa: se basa en el estado actual de la aplicación, mutándolo a través de instrucciones secuenciales.
    • Declarativa: se vale de una función pura que recibe argumentos y retorna un resultado predecible.

    Rendimiento

    • Imperativa: suele mostrar un mejor rendimiento por dos motivos: dispone del código estrictamente necesario para atender un único escenario (lo que evita tener que implementar sistemas de seguridad adicionales) y resulta además altamente eficiente por la facilidad de estos sistemas para ser interpretados - como es la estructura iterativa for. Todo sea dicho, esta mejora del performance debe ser obviada si no es frente a grandes cantidades de datos, donde resultaría imperceptible.
    • Declarativa: la alta preconfiguración se vuelve en contra del rendimiento por dos motivos: la necesidad de contemplar diferentes comportamientos de una misma función, así como evitar una reacción impredecible frente a cualquier escenario al que pueda ser expuesta. Me explico: ¿cómo sino el método .reduce() puede recibir un segundo argumento opcional? ¿y qué sucedería si a una nuestra función reduceArray() se le argumentase un valor diferente a un array? Nada bueno. Es por ello que ambos casos deben ser contemplados en su core y resolverlos supone incrementar el coste del proceso en su totalidad.

    Conclusión

    La industria de Javascript presenta en la actualidad una fuerte orientación declarativa que, asentada por incorporaciones como .filter() o .map() e impulsada por librerías como React, estandariza en sus últimas versiones recursos altamente preconfigurados donde las lógicas internas no quedan expuestas.

    Esto permite centrar la energía y atención en los objetivos por encima de los procesos internos que los alcanzan. Y eso mola.

    Si bien la programación imperativa te permite conocer cómo trabaja en lenguaje en su forma más pura, abrazar un estilo declarativo y funcional suele ser la opción elegida por motivos de estilo, optimización, eficiencia durante el desarrollo, identificabilidad en los códigos resultantes, seguridad frente a efectos colaterales o separación implícita de responsabilidades, entre otros.

    Un crecimiento natural como desarrollador/a supone asimilar los conocimientos básicos del lenguaje, aptos para diseñar resoluciones programáticas de forma imperativa a través de recursos y estructuras clásicas, para así continuar aprovechando el potencial declarativo del mismo desde una base lógica profunda y sólida.

    ¿Preguntas? Hablamos en los comentarios 😜