Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x2001h: Las funciones deben usar cláusulas de guarda y retornos anticipados para reducir la anidación profunda

Funciones, contratos y modularizacion (0x20XX)

Universidad Nacional de Río Negro

0x2001h: Las funciones deben usar cláusulas de guarda y retornos anticipados para reducir la anidación profunda

Enunciado normativo

DEBE validarse al inicio toda precondición o condición de error y abandonarse la función con un retorno anticipado. El camino feliz queda al primer nivel. Si se adquieren recursos, la liberación se centraliza al final.

¿Por qué existe esta regla?

El problema

Validar dentro de cada rama sepulta el cuerpo útil bajo casos excepcionales. La guarda invierte el orden: descarta primero lo inválido y deja el camino normal al ras. Cada guarda es una afirmación local verificable (“si es NULL, no sigo”).

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug silenciosoUn caso borde mal ubicado deja el else correspondiente desanidado.
MantenibilidadAgregar una validación obliga a reindentar medio cuerpo.
TestingEl camino de error es difícil de alcanzar sin simular toda la cadena.

Fundamento en el estándar y en la cátedra

En C11 cada return es un salto válido en cualquier punto (§6.8.4 y §6.8.6.4); no hay exigencia de punto único de salida. La cátedra adopta las guardas para bajar la carga cognitiva y hacer explícitos los contratos de 0x2003h: Todas las funciones deben incluir documentación completa y estructurada.

Alcance y excepciones

Cubre la validación de parámetros (NULL, rangos, arreglos vacíos) y errores inmediatos (fallo de fopen o malloc). No obliga a eliminar los if anidados cuando la lógica realmente combina condiciones.

Excepción explícita: si la función reserva memoria o abre archivos, se prefiere un único bloque de limpieza al final, en tensión con 0x200Ch: Cada función debe tener a lo sumo un return.

Ejemplos exhaustivos

❌ Contraejemplo 1 — La pirámide de condiciones

int procesar(struct dato_t *d)
{
    if (d != NULL) {
        if (d->activo == true) {
            if (d->valor > 0) {
                return calcular(d);
            }
        }
    }
    return -1;
}

La línea que importa está en el cuarto nivel y no se distingue la causa del error.

❌ Contraejemplo 2 — Guarda que fuga el recurso

FILE *abrir(const char *ruta)
{
    if (ruta == NULL) {
        return NULL;
    }
    FILE *f = fopen(ruta, "r");
    if (f == NULL) {
        return NULL;
    }
    if (fseek(f, 0, SEEK_END) != 0) {
        return NULL;
    }
    return f;
}

El retorno del fseek deja el archivo abierto: la guarda olvida la limpieza.

✅ Ejemplo conforme 1 — Guardas para el camino feliz

int procesar(const struct dato_t *d)
{
    if (d == NULL) {
        return ERROR_PUNTERO_NULO;
    }
    if (d->activo == false) {
        return ERROR_DATO_INACTIVO;
    }
    if (d->valor <= 0) {
        return ERROR_DATO_INVALIDO;
    }
    return calcular(d);
}

Cada precondición se verifica de a una y el cuerpo útil queda al primer nivel.

✅ Ejemplo conforme 2 — Guardas y limpieza centralizada

int cargar(const char *ruta, struct tabla_t *t)
{
    int resultado = ERROR_GENERICO;
    if (ruta == NULL || t == NULL) {
        return ERROR_PUNTERO_NULO;
    }
    FILE *f = fopen(ruta, "r");
    if (f == NULL) {
        return ERROR_APERTURA;
    }
    if (leer_tabla(f, t) == 0) {
        resultado = OK;
    }
    if (fclose(f) != 0) {
        resultado = ERROR_CIERRE;
    }
    return resultado;
}

Las guardas previas a la apertura son seguras y el fclose se concentra en un punto.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cAnidación superior a tres niveles.
gcc / clanggcc -Wall -Wextra -Wmisleading-indentation ...else que parece pertenecer a otro if.

Checklist de autocontrol

Reglas relacionadas