Regla 0x6001h: Diseñá el algoritmo antes de escribir código en C
Proceso, diseno y construccion sistematica (0x60XX)
0x6001h: Diseñá el algoritmo antes de escribir código en C¶
Enunciado normativo¶
DEBE escribirse el algoritmo en pseudocódigo o en lenguaje natural estructurado antes de traducirlo a C. La traducción a C es el último paso, no el primero.
¿Por qué existe esta regla?¶
El problema¶
El código fuente de C exige, al mismo tiempo, decidir el algoritmo y respetar la sintaxis. Son dos cargas cognitivas distintas que compiten por la misma memoria de trabajo. Cuando un principiante intenta resolver ambas a la vez, su atención se desplaza del problema al compilador: empieza a corregir puntos y comas en vez de razonar sobre el caso borde que olvidó.
Separar los dos momentos baja la carga cognitiva. En pseudocódigo no hay
puntos y comas, ni tipos, ni &, ni *. El estudiante puede concentrarse en
la secuencia lógica, los casos y las condiciones de corte. Una vez
que el algoritmo está escrito y validado “sobre papel”, traducirlo es casi
mecánico.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Bug de lógica | Se descubre tarde que falta un caso (p. ej. lista vacía) y el código ya está enredado. |
| Retrabajo | Se reescribe el cuerpo entero porque la estructura elegida no soporta el caso que apareció a mitad de camino. |
| Ansiedad sintáctica | El estudiante “pelea con el compilador” y pierde de vista la corrección del algoritmo. |
| Mantenibilidad | El código final mezcla intentos sucesivos sin una idea rectora. |
Fundamento pedagógico¶
La programación estructurada de Dijkstra separa el qué (especificación del problema) del cómo (implementación). El pseudocódigo es la especificación operacional intermedia: todavía no es C, pero ya no es una idea vaga. La cátedra lo adopta como paso obligatorio porque el 80 % de los errores lógicos en las entregas se detectan en el pseudocódigo y no en el depurador.
Alcance y excepciones¶
Aplica a todo ejercicio resuelto en el marco de la materia, desde una suma de dos números hasta un TAD con memoria dinámica. No exige un formato rígido: sirve tanto una lista numerada de pasos como un diagrama de flujo. Lo que no se admite es empezar a tipear C sin haber pensado el algoritmo.
Excepción razonable: modificaciones triviales de una línea (cambiar un límite, un mensaje) no requieren rediseño.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Traducir a C sin pensar los casos¶
El enunciado pide “calcular el promedio de un arreglo”. El estudiante escribe directamente:
double promedio(int v[], int n)
{
double suma = 0;
for (int i = 0; i < n; i++) {
suma += v[i];
}
return suma / n;
}Por qué falla: nunca se pensó el caso n == 0. La división 0.0 / 0
produce NaN, no un error, y el bug viaja en silencio hasta la impresión de
resultados. Un pseudocódigo mínimo habría obligado a escribir “si el arreglo
está vacío, devolver un error”.
❌ Contraejemplo 2 — Estructura elegida a ciegas¶
Para “buscar un nombre en una lista”, el estudiante escribe un for anidado
con break y bandera, y recién al final descubre que la lista podía estar
ordenada y bastaba una búsqueda binaria. El pseudocódigo inicial (“recorrer
hasta encontrar o agotar”) habría mostrado el algoritmo lineal desde el
principio y permitido evaluar la alternativa antes de codificar.
✅ Ejemplo conforme 1 — Pseudocódigo primero¶
funcion promedio(valores, cantidad):
si cantidad es 0:
devolver ERROR
suma <- 0
para cada indice desde 0 hasta cantidad - 1:
suma <- suma + valores[indice]
devolver suma / cantidadRecién después se traduce, y el caso vacío queda garantizado desde el diseño:
double promedio(const int valores[], size_t cantidad)
{
if (cantidad == 0) {
return 0.0;
}
double suma = 0.0;
for (size_t i = 0; i < cantidad; i++) {
suma += (double)valores[i];
}
return suma / (double)cantidad;
}✅ Ejemplo conforme 2 — Pseudocódigo para un TAD¶
Antes de escribir una pila dinámica, el estudiante anota:
estado: puntero a arreglo, cantidad, capacidad
apilar(x):
si cantidad == capacidad:
crecer el arreglo (duplicar capacidad)
arreglo[cantidad] <- x
cantidad <- cantidad + 1
desapilar():
si cantidad == 0:
devolver ERROR_PILA_VACIA
cantidad <- cantidad - 1
devolver arreglo[cantidad]El diseño revela tres decisiones (política de crecimiento, byte nulo/centinela inexistente, contrato de error) que en C puro suelen omitirse por accidente.
⚠️ Casos límite¶
Ejercicios simples: el pseudocódigo puede ser tan breve como tres líneas; la obligación es pensar, no escribir mucho.
Refactorizaciones: si se modifica una función existente, alcanza con anotar el nuevo contrato en una o dos líneas.
Integración con testing: el pseudocódigo es la materia prima de los casos de
assertde 0x2016h: Escribí el contrato de la función antes de implementarla.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
| Revisión manual | — | Ausencia de borrador/pseudocódigo en la entrega o el repositorio. |
gaff | — | No automatizable. |
Checklist de autocontrol¶
Antes de abrir el editor, escribí en un papel o comentario el algoritmo.
Enumeré explícitamente los casos borde (vacío, uno, máximo).
Identifiqué las operaciones repetidas para convertirlas en funciones.
Recién después empecé a traducir a C.
Reglas relacionadas¶
0x2014h: Cada función debe caber en una sola idea y en 25 líneas — el pseudocódigo determina cuántas funciones y de qué tipo hacen falta.
0x2016h: Escribí el contrato de la función antes de implementarla — la especificación (contrato) y el pseudocódigo se redactan juntos.
0x0201h: Escribí comentarios que expliquen el ‘porqué’, no el ‘qué’ — los comentarios de intención registran el diseño previo en el código.