Tres horas. Media hora para escribir decisiones y repeticiones sin dejar casos fuera, y dos horas y media traduciendo reglas de negocio a código y resolviendo problemas completos.
Hoy · Hoja de ruta
- 1. Aprende: Cómo se escribe una decisión, por qué el orden de las ramas es parte de la lógica, qué bucle corresponde a cada repetición y cómo se descompone un enunciado antes de programar.
- 2. Haz: Traduce las reglas de tu proyecto, recorre tu catálogo y resuelve cuatro problemas completos.
- 3. Comprueba: Cada programa se prueba con casos normales, límite y absurdos.
Antes de empezar · 5 minutos, sin apuntes
- Escribe en castellano tres reglas de tu proyecto («si el pedido supera 50 €, el envío es gratis»).
- ¿Qué pasa exactamente cuando el pedido vale 50?
- ¿Qué valores hacen que un
ifno entre aunque el dato exista?
Se explica
25 minutos · conceptos y demostración
Los condicionales y los bucles se escriben en diez minutos. Lo que ocupa la sesión es lo que casi nadie hace: comprobar la frontera, el caso vacío y el orden de las ramas. Ahí está prácticamente el total de los errores.
La decisión más simple
const total = 62;
if (total >= 50) {
console.log("Envío gratuito");
} else {
console.log(`Envío: 4,95 € (te faltan ${(50 - total).toFixed(2)} €)`);
}
Con varios casos:
if (stock === 0) {
estado = "Agotado";
} else if (stock < 5) {
estado = "Últimas unidades";
} else {
estado = "Disponible";
}
El orden de las ramas es parte de la lógica
Un else if solo se evalúa si todo lo anterior fue falso. Si pones primero stock < 5, el caso stock === 0 no se alcanza nunca, porque el cero también es menor que cinco.
Ordena siempre de lo más específico a lo más general, y compruébalo con el caso límite: 0, 5, 50, el valor exacto de la frontera.
Los límites, uno por uno
Casi todos los errores de condicionales están en la frontera. Para la regla «envío gratis a partir de 50 €», prueba con 49,99, con 50 y con 50,01. Si la regla dice «a partir de», es >=. Si dice «más de», es >.
| Se dice | Se escribe |
|---|---|
| A partir de 50 | total >= 50 |
| Más de 50 | total > 50 |
| Hasta 50 | total <= 50 |
| Entre 10 y 20, incluidos | n >= 10 && n <= 20 |
Una advertencia: 10 <= n <= 20 no hace lo que parece. Se evalúa por partes y acaba comparando un booleano con un número.
Para elegir entre dos valores está el ternario, que solo mejora la lectura cuando el if no hace otra cosa:
const etiqueta = stock > 0 ? "Disponible" : "Agotado";
Si dentro hay varias instrucciones, o si necesitas anidar ternarios, usa un if.
Las tres formas de repetir
// Un número conocido de vueltas, con índice
for (let i = 0; i < 5; i++) {
console.log(`Vuelta ${i}`);
}
// Recorrer los valores de una colección: el que más usarás
for (const producto of productos) {
console.log(producto);
}
// Repetir mientras se cumpla algo, sin saber cuántas veces
let restante = 100;
while (restante > 0) {
restante -= 30;
}
| Bucle | Úsalo cuando |
|---|---|
for clásico |
Necesitas el índice, o vas de N en N |
for...of |
Solo necesitas cada valor: el caso normal |
while |
No sabes de antemano cuántas vueltas serán |
for...in |
Casi nunca: recorre claves, y trae sorpresas en arrays |
El patrón que más vas a repetir es el acumulador:
const precios = [89.9, 24.5, 199, 12.75];
let total = 0;
for (const precio of precios) {
total += precio;
}
console.log(total.toFixed(2)); // "326.15"
El recuento con condición es una variante del mismo patrón:
let baratos = 0;
for (const precio of precios) {
if (precio < 50) baratos++;
}
Un bucle infinito no es un error de sintaxis
El fichero está bien escrito, el navegador se queda bloqueado y no hay ningún mensaje rojo. Ocurre cuando la condición del while nunca llega a ser falsa, casi siempre porque se olvidó actualizar la variable de control.
Antes de ejecutar un while, responde a esto: ¿qué línea, dentro del bucle, acerca la condición a hacerse falsa? Si no la encuentras, todavía no ejecutes.
El caso vacío
const productos = [];
for (const producto of productos) {
console.log(producto); // no entra ninguna vez, y está bien
}
Un bucle sobre una lista vacía no falla: simplemente no se ejecuta. Lo que falla es el programa que da por hecho que había algo:
const media = total / productos.length; // 0 / 0 → NaN
Ese NaN es el resultado más peligroso de la sesión. No detiene el programa, sino que se propaga en silencio como un número más por todo lo que venga después.
Antes de escribir código
- ¿Qué datos entran, y de qué tipo son?
- ¿Qué reglas se aplican, y en qué orden?
- ¿Qué sale, y en qué formato?
- ¿Qué casos raros existen: vacío, cero, negativo, texto?
Escribir esas cuatro respuestas cuesta dos minutos y ahorra media hora. Es exactamente el mismo hábito de la UD1, cuando antes de marcar una página decidías qué era cada cosa.
Se trabaja
150 minutos · práctica sobre tu propio proyecto
Los dos primeros pasos traducen reglas y recorren datos. El cuarto es el trabajo grande de la sesión, y el quinto es el que hace que lo anterior valga: probar los casos que nadie prueba.
Paso 1 · Las reglas de tu proyecto · 30 min
En js/main.js:
- Escribe en comentarios cuatro reglas de negocio de tu tema, en castellano.
- Tradúcelas a condicionales.
- Añade el cálculo de un estado con tres posibles valores.
- Escribe una tabla de casos límite y comprueba cada uno.
- Convierte uno de los
ifde dos ramas en un ternario. - Añade una regla que combine dos condiciones con «y», y otra con «o».
Consultar · switch, cuando comparas una cosa contra una lista
switch (categoria) {
case "teclado":
case "raton":
garantia = 24;
break;
case "monitor":
garantia = 36;
break;
default:
garantia = 12;
}
Compara con el triple igual, así que "3" no coincide con 3. Si se omite un break, la ejecución continúa en el caso siguiente: es la fuente de errores clásica de esta estructura.
Antes de continuar: cada una de las cuatro reglas tiene escrito su valor de frontera y el resultado comprobado en ese valor exacto.
Paso 2 · Recorrer el catálogo · 35 min
Con una lista de al menos seis precios de tu tema:
- Calcula el total y la media, tratando el caso de lista vacía.
- Cuenta cuántos elementos superan un umbral.
- Encuentra el más caro sin usar métodos de array todavía.
- Escribe un bucle que se detenga en el primero que cumpla una condición.
- Provoca un bucle infinito a propósito, obsérvalo, y explica qué faltaba.
- Calcula el más caro y el más barato en un solo recorrido.
Consultar · salir antes con break y continue
for (const producto of productos) {
if (producto.stock === 0) continue; // salta este y sigue
if (producto.precio > 500) break; // deja de recorrer
console.log(producto.nombre);
}
Úsalos con moderación: un bucle con cuatro break repartidos es más difícil de seguir que un bucle con una condición bien escrita.
Paso 3 · Un enunciado descompuesto · 15 min
Reproduce este ejemplo y comprueba que entiendes por qué el orden de las reglas cambia el resultado.
Enunciado. Dado un carrito con nombres, precios y unidades, calcula el subtotal, aplica un 10 % de descuento si supera 100 €, suma 4,95 € de envío salvo que el subtotal con descuento llegue a 50 €, y muestra el desglose.
Datos: tres listas paralelas de texto y número. Reglas: tres, y el orden importa —el descuento se aplica antes de decidir el envío—. Salida: cuatro líneas con dos decimales. Casos raros: carrito vacío, unidades cero, precio negativo.
const nombres = ["Teclado", "Ratón", "Alfombrilla"];
const precios = [89.9, 24.5, 12.75];
const unidades = [1, 2, 1];
let subtotal = 0;
for (let i = 0; i < precios.length; i++) {
subtotal += precios[i] * unidades[i];
}
const descuento = subtotal > 100 ? subtotal * 0.1 : 0;
const conDescuento = subtotal - descuento;
const envio = conDescuento >= 50 ? 0 : 4.95;
const total = conDescuento + envio;
console.log(`Subtotal: ${subtotal.toFixed(2)} €`);
console.log(`Descuento: ${descuento.toFixed(2)} €`);
console.log(`Envío: ${envio.toFixed(2)} €`);
console.log(`Total: ${total.toFixed(2)} €`);
El código se lee casi como el enunciado, y eso no es casualidad: es consecuencia de haberlo descompuesto antes.
Ahora invierte el orden de las dos reglas —decide el envío antes de aplicar el descuento— y busca un carrito en el que el total salga distinto. Ese carrito es la demostración de que el orden era parte del enunciado.
Paso 4 · Cuatro problemas · 50 min
Es el trabajo central de la sesión. Para cada uno, escribe primero las cuatro respuestas de la descomposición, y solo después programa.
- Escalonado. Un descuento por unidades: hasta 3, nada; de 4 a 9, un 5 %; de 10 en adelante, un 12 %. Comprueba 3, 4, 9 y 10.
- Validador. Dada una entrada de texto, decide si es un precio válido: número, positivo, con dos decimales como mucho.
- Resumen. Dado un catálogo con precios y stock, calcula el valor total del almacén, cuántos productos están agotados y cuál es el más caro disponible.
- Etiquetado. Genera para cada producto una etiqueta de texto que combine su estado de stock y su franja de precio.
El tercero y el cuarto tienen que funcionar con el catálogo vacío. El segundo reutiliza lo que hiciste en la sesión 1 con las entradas de texto.
Paso 5 · La tabla que casi nadie escribe · 20 min
Vuelve sobre los cuatro problemas y sobre las reglas del paso 1, y construye para cada uno esta tabla:
| Caso | Entrada | Salida esperada | Salida real | ¿Coincide? |
|---|---|---|---|---|
| Normal | ||||
| Frontera exacta | ||||
| Uno menos que la frontera | ||||
| Vacío | ||||
| Cero | ||||
| Negativo | ||||
| Texto donde iba un número |
Rellena la columna «salida esperada» antes de ejecutar. Las filas donde no coincidan son los defectos reales de tu programa: uno que no da error y devuelve un número equivocado es peor que uno que se rompe.
Ampliación si has completado el trabajo
Primero termina y comprueba los cinco pasos. Los dos retos atacan los dos fallos que no se ven: una rama inalcanzable y un enunciado mal leído.
Reto 1 · Las ramas que nunca se alcanzan
Este código funciona, no da ningún error y clasifica mal a la mitad de los clientes.
function categoriaCliente(pedidosAnuales, gastoTotal) {
if (pedidosAnuales > 0) {
return "Cliente activo";
} else if (pedidosAnuales > 10 && gastoTotal > 1000) {
return "Cliente preferente";
} else if (pedidosAnuales > 20) {
return "Cliente VIP";
} else if (pedidosAnuales === 0 && gastoTotal > 0) {
return "Cliente inactivo con historial";
} else if (gastoTotal > 5000) {
return "Gran cuenta";
}
return "Sin categoría";
}
- Identifica todas las ramas que no se pueden alcanzar nunca, y explica para cada una qué rama anterior se las come.
- Reordénalo para que cada categoría sea alcanzable, sin cambiar ninguna condición.
- Una de las categorías sigue sin poder alcanzarse ni siquiera después de reordenar, porque su condición se solapa con otra de forma irreparable. Encuéntrala y propón qué preguntarías al cliente antes de programarla.
- Construye una tabla de seis clientes de prueba que demuestre que tu versión clasifica bien y la original no.
Reto 2 · Escribe tú el enunciado
Escribe un enunciado de programa para un compañero, del estilo de los cuatro del paso 4. Debe cumplir tres condiciones: resolverse con lo visto esta semana, tener al menos dos reglas cuyo orden importe, y tener un caso límite que no sea evidente en la redacción.
Prepara aparte, sin enseñarlo:
- Las cuatro respuestas de la descomposición.
- Tu solución.
- Una tabla de siete casos de prueba, incluidos los raros.
Intercambiad los enunciados y resolvedlos sin preguntar nada. Al comparar:
- ¿La otra persona leyó el mismo orden de reglas que tú tenías en la cabeza? Si no, el enunciado era ambiguo, y eso es un hallazgo sobre tu redacción, no sobre su solución.
- ¿Encontró el caso límite que habías escondido?
- ¿Pasa su solución tu tabla de siete casos?
Un enunciado que dos personas leen distinto es exactamente lo que recibirás de un cliente. Detectarlo antes de programar es la habilidad del reto.
NaN en la lista vacía, y los dos primeros problemas resueltos.Cierre
5 minutos · comprobación y recuerdo
Lista de verificación de la sesión
- Traduces reglas de negocio a condicionales, con sus límites comprobados.
- Ordenas las ramas de lo específico a lo general.
- Recorres colecciones con el bucle adecuado y sabes justificar cuál.
- Tu código no se rompe ni devuelve
NaNcon una lista vacía. - Descompones un enunciado antes de escribir la primera línea.
- Tienes la tabla de casos de prueba rellenada antes de ejecutar.
Antes de cerrar · 3 minutos, sin mirar
- «Envío gratis a partir de 50 €»: ¿qué operador?
- ¿Por qué
10 <= n <= 20no funciona? - ¿Qué ocurre si olvidas un
breaken unswitch? - ¿Cuándo eliges
for...ofy cuándo unforcon índice? - ¿Qué diferencia hay entre
breakycontinue? - ¿Cuánto vale la media de una lista vacía, y qué deberías hacer?
Ver respuestas
1 · Mayor o igual: el 50 exacto entra.
2 · Porque se evalúa por partes: la primera comparación da un booleano, y después se compara ese booleano con 20.
3 · La ejecución continúa en el caso siguiente y se aplican también sus instrucciones.
4 · for...of cuando solo necesitas el valor; el clásico cuando necesitas la posición o un salto distinto de uno.
5 · break abandona el bucle; continue salta a la vuelta siguiente.
6 · NaN, porque divides entre cero. Hay que comprobar la longitud antes y devolver 0 o un aviso.
Microprueba semanal 2 · 5–10 minutos
Individual, sin IA y sin apuntes.
- Traduce a una condición: «el envío es gratis a partir de 50 €». Di qué ocurre con 50 exactos.
- Escribe el bucle que suma una lista de precios, y di qué devuelve con la lista vacía.
- Un
whileno termina nunca: nombra la causa más probable y cómo la comprobarías.