Módulo 2: Branching y Decisiones Avanzadas

If Hell y Cómo Refactorizar

Descripción de la cápsula

"If hell" es el nombre que la comunidad le da al anti-patrón más común en workflows complejos: un nido de IFs anidados, cada uno con su rama, formando una estructura imposible de seguir mentalmente. Empieza inocentemente — un IF, después otro adentro, después otro — y cuando te das cuenta, tu workflow tiene 12 IFs anidados y nadie (ni tú) puede explicar qué hace exactamente.

En esta cápsula vas a aprender a reconocer if hell temprano (los signos antes de que sea grave), 3 técnicas de refactoring para deshacerlo, cómo prevenirlo desde el día 1, y los casos genuinos donde anidación es legítima (rara, pero existe).


Lo que vas a aprender

Al terminar esta cápsula serás capaz de:

  • Reconocer if hell antes de que cause problemas serios
  • Refactorizar estructuras con IFs anidados a alternativas limpias
  • Aplicar 3 técnicas: Switch consolidado, early return, decomposición
  • Prevenir if hell con disciplina de diseño desde el inicio
  • Distinguir if hell genuino vs casos donde anidación es OK

Cómo se ve if hell

[IF: condición A]
   ├─ TRUE
   │   ├─ [IF: condición B]
   │   │   ├─ TRUE
   │   │   │   ├─ [IF: condición C]
   │   │   │   │   ├─ TRUE → proceso 1
   │   │   │   │   └─ FALSE → proceso 2
   │   │   └─ FALSE → proceso 3
   │   └─ [IF: condición D]
   │       ├─ TRUE → proceso 4
   │       └─ FALSE → proceso 5
   └─ FALSE
       ├─ [IF: condición E]
       ...

En el canvas, esto se ve como un árbol con ramas que se ramifican que se ramifican. Algunas ramas tienen 3-5 nodos cada una. Imposible ver el panorama entero.


Señales de que vas hacia if hell

Señal 1: 3+ IFs anidados

Si te encuentras con un IF dentro de un IF dentro de un IF, detente y refactoriza. 2 niveles de anidación es manejable; 3+ es bandera roja.

Señal 2: Lógica duplicada en múltiples ramas

Si la rama TRUE-TRUE-TRUE y TRUE-FALSE-TRUE tienen los mismos nodos al final, hay duplicación. Síntoma claro de mala estructura.

Señal 3: Canvas requiere scroll horizontal/vertical para ver todo

Si no puedes ver tu workflow en una pantalla normal sin scrolllear, probablemente está mal estructurado.

Señal 4: Te cuesta explicarlo verbalmente

Si alguien te pregunta "¿qué hace este workflow?" y tu explicación dura más de 30 segundos, hay un problema de diseño.

Señal 5: Cambios pequeños rompen cosas inesperadamente

If hell tiene dependencias ocultas — cambias una condición y rompes otra rama que dependía indirectamente. Si encuentras esto, refactoriza.


Técnica 1: Switch consolidado

Si tienes IFs en cadena que comparan el mismo campo o conceptos relacionados, es un Switch disfrazado.

Antes (if hell horizontal)

[IF: type === "A"]
├─ TRUE → proceso A
└─ FALSE → [IF: type === "B"]
            ├─ TRUE → proceso B
            └─ FALSE → [IF: type === "C"]
                        ├─ TRUE → proceso C
                        └─ FALSE → [IF: type === "D"]
                                    ├─ TRUE → proceso D
                                    └─ FALSE → fallback

5 IFs en cadena, cada uno comparando type con un valor distinto.

Después (Switch consolidado)

[Switch sobre type]
├─→ "A" → proceso A
├─→ "B" → proceso B
├─→ "C" → proceso C
├─→ "D" → proceso D
└─→ default → fallback

1 nodo. 5 salidas. Lógica clara.

Aplicable siempre que: los IFs comparen el mismo campo con valores diferentes.


Técnica 2: Early return con filtros

Si tienes IFs anidados donde el outer descarta items que no cumplen ciertos prerequisitos, descarta temprano.

Antes

[IF: has_email]
├─ TRUE → [IF: email_valid]
│         ├─ TRUE → [IF: gave_consent]
│         │         ├─ TRUE → procesar
│         │         └─ FALSE → log "sin consentimiento"
│         └─ FALSE → log "email inválido"
└─ FALSE → log "sin email"

3 IFs anidados, cada uno chequeando un prerequisito.

Después (filtros en cadena, cápsula 05)

[Filter: has_email]
   │
[Filter: email_valid]
   │
[Filter: gave_consent]
   │
[procesar]

Los items que no pasan se descartan implícitamente. Si necesitas manejarlos:

[Set: agregar Booleans validez]
   │
[IF: meets_all]
├─ TRUE → procesar
└─ FALSE → [Switch sobre invalid_reason]
           ├─→ "sin email" → log...
           ├─→ "email inválido" → log...
           └─→ "sin consentimiento" → log...

Una sola decisión (meets_all), después un Switch para manejar las razones.


Técnica 3: Decomposición con Set

Si tu lógica de decisión es genuinamente compleja (con muchas variables), decompone en Booleans intermedios con Set, después una decisión simple.

Antes (decisión compleja inline)

[IF: ($json.country === "USA" || $json.country === "Canada") && $json.plan === "enterprise" && $json.amount > 1000]

Funciona pero ilegible.

Después (Booleans descompuestos)

[Set:]
- is_key_market: ["USA", "Canada"].includes(country)
- is_enterprise: plan === "enterprise"
- high_amount: amount > 1000
- meets_criteria: is_key_market && is_enterprise && high_amount

[IF: meets_criteria is true]

Beneficio: debuggeable, legible, refactorable.


El proceso completo de refactoring

Cuando enfrentas if hell, sigue este proceso:

Paso 1: Documenta qué hace (no qué dice el código)

Antes de tocar nada, escribe en lenguaje natural qué intención tiene el workflow. Si te cuesta, es señal de que la estructura está mal.

Paso 2: Identifica el patrón subyacente

  • Switch disfrazado? → técnica 1
  • Cadena de validaciones? → técnica 2 (filtros)
  • Decisión compleja con muchas variables? → técnica 3 (decomposición)
  • Mix de varios patrones? → combinar técnicas

Paso 3: Diseña la nueva estructura

En papel o mental, antes de modificar el canvas.

Paso 4: Refactoriza en un workflow duplicado

NO toques el original. Duplica el workflow, refactoriza la copia. Testea contra el mismo input que el original. Cuando estés seguro, reemplaza.

Paso 5: Valida con casos de prueba

Si el original procesaba 100 items con cierto outcome, la versión refactorizada debe producir el mismo outcome.

Paso 6: Documenta el cambio

Sticky Note: "Refactorizado de if-hell el 2026-05-11 — Switch consolidado para type".


Prevención: hábitos de diseño desde el día 1

Hábito 1: Si dudas entre IF anidado y Switch, elige Switch

Por default, si tienes 3+ valores a comparar de la misma variable, Switch.

Hábito 2: Set antes de decisión

Como vimos en cápsulas 04. Calcular Booleans/categorías antes de las decisiones es prevención de if hell.

Hábito 3: Refactor temprano

Cuando notes el segundo IF anidado, considera refactorizar antes de agregar el tercero. Es 10× más fácil refactorizar 2 IFs anidados que 12.

Hábito 4: Code review mental

Antes de hacer commit (o cerrar el workflow), pregúntate: "¿Si un colega abre esto mañana, en cuánto tiempo entenderá qué hace?". Si más de 30 segundos, refactoriza.

Hábito 5: Limit visual

Si tu workflow no cabe en una pantalla, considera dividir en sub-workflows (cápsula 07).


Cuándo anidación es legítima

A veces 2 niveles de anidación son la forma natural del problema, no if hell.

Caso 1: Lógica genuinamente jerárquica

Sí tienes "primero filtrar por categoría general, después por subcategoría":

[Switch: categoria general]
├─→ "A" → [Switch: subcategoría A]
├─→ "B" → [Switch: subcategoría B]
└─→ "C" → [proceso simple]

Esto es diseño correcto, no if hell. 2 niveles de Switch porque hay 2 niveles reales de decisión.

Caso 2: Manejar errores en cada paso

[Procesar X]
├─ TRUE → [Procesar Y]
│         ├─ TRUE → siguiente
│         └─ FALSE → manejar error Y
└─ FALSE → manejar error X

Cada nivel de IF maneja error específico. Si los manejar error X/Y son sustanciales, esto es estructura legítima.

Diferencia con if hell

  • If hell: anidación porque no encontraste el patrón correcto
  • Anidación legítima: la jerarquía refleja la realidad del problema

Ejemplo completo de refactoring

Workflow original (if hell)

[Webhook]
   │
[IF: $json.body.type === "premium"]
├─ TRUE
│  ├─ [IF: $json.body.amount > 1000]
│  │  ├─ TRUE
│  │  │  ├─ [IF: $json.body.country === "USA"]
│  │  │  │  ├─ TRUE → Slack #ventas-usa-premium + Email custom + CRM A
│  │  │  │  └─ FALSE → Slack #ventas-eu-premium + Email standard + CRM B
│  │  │  └─ Slack #ops "premium pero monto bajo"
│  │  └─ FALSE → Slack #monitor "premium sin monto válido"
│  └─ ...
└─ FALSE
   ├─ [IF: $json.body.type === "trial"]
   │  ├─ TRUE → email autorespuesta trial
   │  └─ FALSE → email autorespuesta free
   └─ ...

7+ IFs anidados, lógica esparcida, imposible mantener.

Refactor paso a paso

Paso 1: Set para categorizar

[Set:]
- category: {{
    $json.body.type === "premium" && $json.body.amount > 1000 && $json.body.country === "USA" ? "premium_usa" :
    $json.body.type === "premium" && $json.body.amount > 1000 ? "premium_other" :
    $json.body.type === "premium" ? "premium_invalid" :
    $json.body.type === "trial" ? "trial" :
    "free"
  }}
- email_template: {{ ... según category ... }}
- slack_channel: {{ ... según category ... }}

Paso 2: Switch único

[Switch sobre category]
├─→ "premium_usa"     → [Execute Workflow: process_premium_usa]
├─→ "premium_other"   → [Execute Workflow: process_premium_other]
├─→ "premium_invalid" → [Slack #monitor]
├─→ "trial"           → [Email autorespuesta trial]
└─→ "free"            → [Email autorespuesta free]

5 salidas claras. Workflow visualmente limpio.

Comparación:

  • Antes: 7+ nodos IF, 10+ ramas, hard to read
  • Después: 1 Set, 1 Switch, 5 salidas, legible

Trampas comunes durante refactor

Trampa 1: Cambiar comportamiento sin querer

Qué pasa: Refactorizas a Switch. Olvidas un caso edge del original (un IF FALSE que tenía manejo especial). Comportamiento cambia silenciosamente.

Cómo evitar:

  • Documenta exhaustivamente qué hace el original antes de tocar
  • Tests con casos que cubran todas las ramas posibles
  • Compara outputs side-by-side

Trampa 2: Refactorizar en producción

Qué pasa: Refactorizas el workflow productivo directamente. Algo se rompe. Producción interrumpida.

Cómo evitar: siempre refactor en duplicado. Reemplazar producción solo cuando la versión nueva pase tests.


Trampa 3: Sobre-ingeniería

Qué pasa: Tu workflow tiene 2 IFs anidados (no es if hell). Refactorizas a Switch + Set + sub-workflows porque "es mejor práctica". Resultado: más complejo que el original.

Cómo evitar: 2 IFs anidados son OK. Refactor cuando hay 3+, o cuando hay duplicación / dificultad de mantenimiento real.


Trampa 4: Refactor sin entender el código original

Qué pasa: Heredas un workflow if hell de un colega. Lo refactorizas sin entender por qué cada IF está donde está. Inadvertidamente cambias lógica que era importante.

Cómo evitar:

  • Hablar con quien lo escribió si está disponible
  • Documentar cada decisión del original antes de tocar
  • Tests exhaustivos

Ejercicio: identificar y refactorizar

Objetivo: practicar identificación y refactoring.

Tu tarea

Mira mentalmente o en papel este workflow:

[IF: usuario activo]
├─ TRUE: [IF: tiene suscripción]
│        ├─ TRUE: [IF: plan = premium]
│        │        ├─ TRUE: enviar email premium
│        │        └─ FALSE: enviar email standard
│        └─ FALSE: enviar email trial
└─ FALSE: nada
  1. ¿Es if hell? ¿Por qué?
  2. ¿Cómo lo refactorizarías?
Análisis sugerido

¿Es if hell? Marginalmente. 3 niveles de anidación. La lógica jerárquica es legítima (primero activo → después tiene suscripción → después plan). Pero se puede simplificar.

Refactor:

[Set:]
- category: {{
    !$json.active ? "inactive" :
    !$json.has_subscription ? "trial" :
    $json.plan === "premium" ? "premium" :
    "standard"
  }}

[Switch sobre category]
├─→ "inactive" → (nada)
├─→ "trial" → email trial
├─→ "standard" → email standard
└─→ "premium" → email premium

Antes: 3 IFs anidados. Después: 1 Set + 1 Switch.


Resumen y siguiente paso

  • If hell: IFs anidados imposibles de mantener
  • 5 señales tempranas: 3+ anidación, duplicación, scroll necesario, difícil explicar, cambios rompen cosas
  • 3 técnicas refactor: Switch consolidado, early return con filtros, decomposición con Set
  • Proceso de refactor: documentar → identificar patrón → diseñar → duplicar → validar → reemplazar
  • 5 hábitos preventivos: prefer Switch, Set antes de decisión, refactor temprano, code review mental, limit visual
  • Anidación legítima existe (jerarquía real, error handling por paso)
  • 4 trampas en refactor: cambiar comportamiento, refactor en prod, sobre-ingeniería, refactor sin entender

Antes de avanzar deberías poder:

  • Reconocer if hell mirando un workflow
  • Aplicar las 3 técnicas según el patrón subyacente
  • Refactorizar de forma segura (en duplicado, con tests)
  • Distinguir if hell genuino vs anidación legítima

Lo que sigue (cápsula 07):

A veces refactorizar dentro del mismo workflow no es suficiente — algunas ramas son lo suficientemente complejas para merecer su propio workflow. Sub-workflows con Execute Workflow son la herramienta para extraer y reusar lógica.


Recursos adicionales

  1. Replace Nested Conditional with Guard Clauses - Patrón general aplicable.
  2. Code Smells: Long Method - Análogo conceptual.

Creado: Mayo 11, 2026 Versión: 1.0