Ordénate declarar

Read in English

La programación declarativa es una tendencia transformadora en la industria que no solo mejora el paradigma de programación, sino que además habilita la revolución de la automatización.

Imperativa

En la esquina opuesta, tenemos la programación imperativa , que significa que un programador escribe las instrucciones específicas sobre qué acciones deben ejecutarse y en qué orden. Por ejemplo, si una aplicación necesita copiar un archivo, el desarrollador llamaría a una función como esta:

// pseudocódigo
copiar_archivo(/origen,/destino)

El usuario de copiar_archivo está emitiendo un comando para copiar el archivo desde el origen al destino, y podemos suponer que la intención de la persona es que el archivo esté disponible en la ubicación de destino, pero la intención no es 100% clara en el estilo imperativo. Si estamos implementando el comando imperativo copiar_archivo, tenemos que hacer algunas suposiciones o pedirle a la persona que aclare sus intenciones a través de algunos parámetros adicionales (por ejemplo, no_copiar_si_existe:verdad).

// pseudocódigo
function copiar_archivo(origen, destino)
  origenExiste = archivo_existe(origen)
  folderDestinoExiste = folder_existe(destino)
  si origenExiste entonces
    si no folderDestinoExiste entonces
      crear_folder(destino)
    fin si
    destinoEsIdentico = comparar_tamano_y_fecha(origen,destino)
    si destinoEsIdentico entonces
      retornar exito // Se te pidió copiar, no copiaste... por qué éxito?
    si no entonces
      contenido = leer_archivo(origen)
      escribir_archivo(contenido,destino)
      retornar exito
    fin si
  fin si
  retornar error
fin function

Esto plantea la pregunta si el comando necesitaba argumentos adicionales para aclarar la intención, ¿no tendría más sentido para el usuario expresar la intención sin el comando? Bienvenido al mundo de la programación “declarativa ” o del “estado deseado ”.

Declarativa

La programación declarativa NO reemplaza el estilo de programación imperativo y procedimental [1] , sino que mejora la interfaz para los usuarios al preguntarles sus intenciones en lugar de instrucciones. El modelo declarativo cambia el paradigma y establece que las librerías no deben proporcionar al usuario acciones/verbos, sino que deben permitir que el solicitante afirme el estado final deseado y dejar que la librería o la herramienta descubra cómo llegar allí. Por supuesto, la programación declarativa no es algo nuevo, se ha utilizado durante décadas en el mundo de los datos en la programación SQL, pero está teniendo un gran renacimiento en el mundo de la automatización. Entonces, de nuevo, usando pseudocódigo:

garantizaArchivoDisponible:
  cualArchivo: /origen
  donde: /destino

Inmediatamente podemos ver tres beneficios de este enfoque sobre el estilo imperativo:

  • Intenciones claras. El deseo del usuario está claramente establecido, “garantizar que el archivo esté disponible en la ubicación de destino”, sin ninguna imposición de cómo esto deba suceder. Si ese deseo se cumple, la rutina tiene éxito y, si no, entonces falla, independientemente de las acciones reales requeridas para hacerla realidad.
  • Idempotencia. Los desarrolladores y propietarios de aplicaciones no deben tener miedo de ejecutar código declarativo dos o muchas veces más. En el paradigma imperativo, un procedimiento de empezar_servidor continuará incrementando el número de servidores cada vez que se llame, en declarativo, uno afirma el estado final deseado (garantiza_servidor_listo) y el motor debería poder determinar si ya está allí , o si necesita corregir alguna deriva [2] , o empezar de cero.
  • Portabilidad. Al mantenerse alejado de los detalles de cómo se cumplirá el deseo, la interfaz tiene una mejor oportunidad de conservarse a través de muchas implementaciones diferentes. Por ejemplo, copiar_archivo tiene sentido en un sistema de archivos local, pero si la funcionalidad se extiende a un servidor de archivos, la acción sería una transferencia de archivos aunque todavía se llame copiar_archivo, y si se implementa en un entorno web, será una carga de archivos. Al permitir que el usuario exprese su estado final deseado, la interfaz tiende a estar menos apegada a la implementación presente.

Conclusión

Si estás pensando que todavía hay mucha programación imperativa bajo las sábanas para habilitar mi pequeño ejemplo declarativo, tendrás razón. El estado deseado (juego de palabras) no es librar al mundo de los imperativos, sino mejorar la interfaz con los usuarios. Si eso no fuera suficiente, la programación declarativa es uno de los componentes clave que hacen posible la automatización moderna, sin ella no tendríamos Ansible, Kubernetes o Terraform, todos los cuales dependen de los conceptos de la programación declarativa para ofrecer la asombrosa revolución de la automatización que hemos observado en los últimos años.


[1]: La programación estructural o procedimental es un estilo de programación imperativa donde los “gotos” imperativos puros son reemplazados por funciones y procedimientos.

[2]:  Deriva: en la programación declarativa, se produce una deriva cuando factores externos cambian el estado después de haberse logrado con éxito el estado deseado. La detección de derivas es una técnica comúnmente utilizada para observar cambios en el estado deseado y la reconciliación de derivas es el proceso por el cual el sistema vuelve al estado deseado después de una deriva.