1 puntos por GN⁺ 2026-02-02 | 1 comentarios | Compartir por WhatsApp
  • Un caso en el desarrollo de una aplicación de generación de reportes en el que se agregó la opción --dry-run para poder simular el resultado de la ejecución
  • Esta opción muestra qué tareas se ejecutarían sin realizar cambios reales, lo que permite pruebas seguras y retroalimentación rápida
  • Gracias a esto, el desarrollador puede verificar de inmediato la configuración, la accesibilidad y el estado del sistema, y usarla como una herramienta cotidiana de validación
  • Se menciona como desventaja un ligero aumento de la complejidad, ya que hay que comprobar la bandera dryRun dentro del código
  • En las aplicaciones imperativas, la función --dry-run es muy útil, y cuanto antes se incorpore al proyecto, mayor será la eficiencia del desarrollo

Contexto

  • La nueva aplicación de generación de reportes que se estaba desarrollando genera reportes cada día hábil, los comprime, los sube a un servidor sftp, revisa las respuestas de error y envía correos de notificación
    • Los archivos generados y los archivos de retroalimentación de cada etapa se mueven a distintos directorios según la fase
  • Al inicio del desarrollo, se tomó como referencia Subversion y la opción --dry-run de varios comandos de Linux para agregar la misma funcionalidad
    • Esta opción muestra qué ocurriría al ejecutarse sin hacer cambios reales
  • Al ejecutar --dry-run, se muestran por etapas los reportes que se generarían y los que se excluirían, los archivos que se comprimirían y moverían, y los archivos objetivo de subida y descarga por sftp

Uso y beneficios

  • Es una función tan útil que se usa todos los días durante el desarrollo y las pruebas
  • Al usarla para revisar el estado antes de la ejecución, permite verificar de inmediato la configuración, la accesibilidad y el estado del sistema
    • Como no hay cambios reales, puede ejecutarse de forma segura
  • Tras cambiar la fecha del archivo de estado de un reporte, se puede comprobar de inmediato si ese reporte se generará o no
    • La generación real del reporte toma tiempo, pero dry-run ofrece retroalimentación rápida
  • Incluso en las pruebas de todo el sistema, proporciona un ciclo de validación rápido

Desventajas

  • Como hay que comprobar repetidamente la bandera dryRun dentro del código, se genera una ligera contaminación del código
    • En cada etapa principal se revisa la bandera y, en lugar de ejecutar la acción real, solo se imprime el registro
  • Sin embargo, esta comprobación no está profundamente integrada, y no se necesita un manejo adicional dentro de la lógica de generación de reportes
    • Solo se comprueba en la capa superior que decide si se ejecuta o no

Conclusión

  • Las aplicaciones que se ejecutan de forma imperativa y producen resultados encajan muy bien con la opción --dry-run
    • En cambio, no es adecuada para aplicaciones reactivas que esperan mensajes
  • Haberla agregado al inicio del proyecto ayudó mucho a mejorar la eficiencia del desarrollo
  • No es una función necesaria en todos los casos, pero se considera una herramienta muy útil cuando se aplica en el contexto adecuado

1 comentarios

 
GN⁺ 2026-02-02
Comentarios en Hacker News
  • Al interactuar con sistemas con estado, incluso --dry-run puede tener condiciones de carrera (race conditions)
    La herramienta muestra “qué haría” con el estado actual, pero cuando llega el momento de ejecutar, la situación puede haber cambiado
    Por eso prefiero el enfoque del modo “plan” de Terraform. Ese modo genera un plan ejecutable y, si cambian los supuestos del momento en que se planificó, puede detenerse o hacer rollback
    Además, evita tener que meter if dry_run: por todas partes en el código, y simplifica separando planificación y ejecución en una forma como execute(plan())

    • Un caso anterior de caída de DNS en AWS ocurrió por una condición de carrera similar
      Un problema de timing entre DNS Planner y Enactor hizo que un plan antiguo sobrescribiera uno más reciente
      El tema también se trató en un hilo anterior de HN
    • Al final, esto equivale a implementar un compilador (especificación→plan) y una máquina virtual (plan→ejecución)
    • Es ideal para herramientas de infraestructura como Terraform o Ansible, pero para herramientas simples de reporting puede introducir una complejidad excesiva
      Porque para crear un modo de planificación se necesita un lenguaje específico de dominio o una estructura de datos
    • Yo también estoy creando un script que modifica archivos sensibles, y estoy aplicando este enfoque
      (1) capturar el estado del sistema de archivos y guardar el plan → (2) verificar que el estado no haya cambiado, ejecutar y registrar logs → (3) comparar con el estado previo para validar si hubo pérdida de datos
      Estoy usando las tres etapas separadas en scripts o flags distintos
    • Entonces me pregunto cómo se podría aplicar este modo de planificación al comando rm
  • Cuando una herramienta no tiene --dry-run, a veces lo hago yo mismo
    Por ejemplo, antes de ejecutar un comando sed complejo, uso diff para comparar por adelantado los cambios
    Se puede revisar la diferencia con algo como diff -u <(echo "hello") <(echo "hello" | sed "s/hello/hi/g")
    Lo resumí en mi blog

  • Me gusta el patrón --dry-run, pero el código del camino dry debe comportarse igual que el camino real
    Si solo imprime “esto es lo que haría” y se salta la lógica real, se pueden pasar por alto bugs cuando se ejecute de verdad
    Debería correr igual hasta justo antes de una escritura en base de datos o una llamada a API

    • Pero algunas personas creen que esto confunde pruebas de integración con dry-run
      El dry-run muestra “qué pasaría”, mientras que las pruebas reales son otra cosa
  • Yo prefiero lo contrario: tener flags como --commit o --execute, y que la ejecución por defecto sea solo lectura (dry)
    Así se reduce la posibilidad de provocar cambios reales por accidente

    • Llevo 8 años usando este enfoque, y ha sido seguro porque solo hay cambios cuando se especifica --commit
      En cambio, sí he visto muchos accidentes por olvidar --dry-run
    • Mi herramienta para deduplicar directorios también sigue este patrón
      Por defecto solo compara, y solo reemplaza por hardlinks reales si se usa --execute
    • Algunas herramientas que usé antes pedían escribir una frase específica antes de ejecutar de verdad
      Este tipo de confirmación ayuda a reducir errores
    • Personalmente también me gusta un flag como --wet-run. Según el contexto, a veces el flag con el significado opuesto resulta más intuitivo
    • Un script reciente que hice es de solo lectura por defecto, y para borrar de verdad hay que escribir manualmente DELETE-ACCOUNT
      Hasta ahora no he borrado una cuenta por accidente ni una sola vez
  • Para evitar contaminar el código, hay que separar la persistencia como una estrategia inyectable
    No es buena idea ir dejando if dry_run: por todos lados
    De hecho, puede ser más seguro dejar explícita la ejecución de producción como --wet-run

    • Conviene modelar explícitamente el comportamiento de la aplicación y procesarlo de forma centralizada
      Así solo se decide en un lugar si es dry-run o no — estilo “functional core, imperative shell”
    • Pero tener que escribir siempre algo como rm --wet-run tempfile.tmp sería molesto
      Sería mejor que por defecto ejecutara de verdad, y en cambio hubiera una opción --undo para revertir la última operación
    • No me encanta el nombre --wet-run, pero también he usado el enfoque de dejar dry-run como predeterminado y exigir --no-dry-run para permitir cambios
      En un servicio, lo ideal sería elegir automáticamente el modo seguro según el entorno de ejecución (dev/prod)
    • En estos casos, usar patrones de diseño puede ayudar a mantener una estructura limpia
  • El artículo decía que “agregaron --dry-run al inicio y resultó inesperadamente útil”,
    pero en realidad este tipo de flags muchas veces los proponen automáticamente los agentes de coding con IA (por ejemplo, Claude)
    Hoy en día que muchas herramientas CLI tengan patrones parecidos podría deberse a este fenómeno de convergencia de código impulsado por agentes

    • Pero como el autor mencionó explícitamente que se inspiró en --dry-run de Subversion, también suena a una razón totalmente convincente
  • Yo suelo agregar un flag --really a las utilidades CLI, dejando por defecto el modo de solo lectura
    La idea es exigir un paso de confirmación intencional para evitar errores

    • Antes también vi un comando con un flag --i-meant-that
      Era un comando para borrar una máquina remota, y por defecto esperaba 10 segundos para dar oportunidad de cancelar
      Por suerte, ese flag nunca se usó mal
  • Una de las cosas geniales de PowerShell es que con solo agregar [CmdletBinding(SupportsShouldProcess)]
    ya se habilita automáticamente la función de dry-run con -WhatIf. Es una función muy práctica

    • Además, también se activa -Confirm, y con la función ShouldProcess se puede interactuar con el umbral de confirmación del usuario. Es un diseño realmente elegante
  • En un CLI interno que administro, pongo if not dry_run: dentro de la parte que hace llamadas REST API
    Así, en lugar de ejecutar la llamada real, se deja un log con el comando CURL para revisar qué request saldría
    Pero cuando la integración entre APIs se vuelve compleja, simular eso se hace difícil y termina siendo mucho más complicado que un simple if not dry_run:

    • Si se estructura todo para que la acción real ocurra en un solo lugar, se evita contaminar el código
      Yo también mantengo muchos CLI para pipelines de automatización, y aplico este patrón en casi todas las herramientas
    • Pero también hay quien opina que abusar de REST en herramientas de consola es ineficiente
      Que lo importante es construir bien primero las herramientas locales
  • Si el flag --dry-run está disperso por todo el código, conviene aplicar el patrón de máquina de estados para separar claramente cada etapa