Regla 0x2008h: Los ejercicios deben ser resueltos mediante funciones
Funciones, contratos y modularizacion (0x20XX)
0x2008h: Los ejercicios deben ser resueltos mediante funciones¶
Enunciado normativo¶
DEBE descomponerse cada ejercicio en funciones con responsabilidad propia, y
mainDEBE limitarse a orquestarlas. La lógica del problema NO DEBE escribirse directamente en el cuerpo demainni en un único bloque monolítico.
¿Por qué existe esta regla?¶
El problema¶
Escribir todo en main mezcla lectura, cálculo, impresión y errores en un
mismo cuerpo: no se puede probar la parte de cálculo, ni reutilizarla, ni leer
por bloques. Dividir permite probar cada pieza con assert (0x8001h: Una aserción por cada función de prueba),
nombra su intención (0x0101h: Los identificadores deben ser descriptivos) y deja main como un índice legible.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Testing | Sin funciones no hay unidad que probar, solo el ejecutable entero. |
| Legibilidad | main deja de ser un resumen y se vuelve el programa entero. |
Fundamento en el estándar y en la cátedra¶
C11 define la función como la unidad de comportamiento (§6.9.1) y permite
auxiliares con enlace interno (static, §6.2.2). La cátedra exige la
modularización porque es la base del bloque: sin funciones propias no aplican
la responsabilidad única (0x2005h: Cada función debe tener una única responsabilidad (Principio de Responsabilidad Única)) ni la separación de E/S
(0x2002h: Las funciones no deben contener printf o scanf, a menos que ese sea su propósito explícito).
Alcance y excepciones¶
Aplica a todo ejercicio entregable, desde una suma hasta un TAD. main es la
excepción estructural: coordina y no se le exige responsabilidad única.
Excepción razonable: un ejercicio de una sola línea no necesita auxiliares;
lo que no se admite es un main de decenas de líneas con toda la lógica.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Toda la lógica en main¶
int main(void)
{
int v[100];
int n = 0;
int x;
while (scanf("%d", &x) == 1) {
v[n] = x;
n++;
}
int suma = 0;
for (int i = 0; i < n; i++) {
suma += v[i];
}
printf("Suma: %d\n", suma);
return 0;
}Lectura, cálculo e impresión conviven en main; no hay forma de probar la suma
sin simular el teclado.
❌ Contraejemplo 2 — Función recursiva sin caso base¶
int factorial(int n)
{
return n * factorial(n - 1);
}Falta la condición de corte: cada llamada apila un marco hasta agotar la pila (0x2017h: Toda funcion recursiva debe tener un caso base explicito). Una función propia debe tener su contrato completo.
✅ Ejemplo conforme 1 — Funciones con propósito y main orquestador¶
static int sumar_arreglo(const int v[], size_t n)
{
int suma = 0;
for (size_t i = 0; i < n; i++) {
suma += v[i];
}
return suma;
}
static size_t leer_arreglo(int v[], size_t cap)
{
size_t n = 0;
int x;
while (n < cap && scanf("%d", &x) == 1) {
v[n] = x;
n++;
}
return n;
}
int main(void)
{
int v[100];
size_t n = leer_arreglo(v, 100);
printf("Suma: %d\n", sumar_arreglo(v, n));
return 0;
}main se lee como un resumen de tres pasos y el cálculo se prueba con assert.
✅ Ejemplo conforme 2 — Función recursiva con caso base¶
int factorial(int n)
{
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}La guarda inicial garantiza la terminación; se prueba para n == 0, 1 y 5.
⚠️ Casos límite¶
mainparametrizado:int main(int argc, char *argv[])sigue siendo el orquestador; el procesamiento va en funciones.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | main que concentra la lógica del ejercicio. |
Checklist de autocontrol¶
¿Separé lectura, cálculo e impresión en funciones distintas?
Reglas relacionadas¶
0x2005h: Cada función debe tener una única responsabilidad (Principio de Responsabilidad Única) — cada función extraída debe tener una sola responsabilidad.
0x2002h: Las funciones no deben contener printf o scanf, a menos que ese sea su propósito explícito — la E/S queda en funciones de interfaz, no en el cálculo.
0x8001h: Una aserción por cada función de prueba — con funciones, cada caso se prueba con un
assert.