0x1017h: Escribí condiciones afirmativas y directas¶
Enunciado normativo¶
Las condiciones de control DEBEN formularse en forma afirmativa y directa. Cuando una condición negativa sea necesaria, DEBE reescribirse el bloque para expresar el caso afirmativo, o aislarse en una variable con nombre positivo.
¿Por qué existe esta regla?¶
El problema¶
Una condición negativa obliga a razonar sobre la ausencia de un estado, que es más difícil que razonar sobre su presencia. Si además la condición mezcla varios términos negados, el lector debe aplicar las leyes de De Morgan mentalmente para saber cuándo se ejecuta el bloque.
Las condiciones afirmativas describen el camino que sí interesa; las
negativas describen todo lo demás y dejan el caso principal para el else.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Bug lógico | Es fácil olvidar una negación al editar la condición. |
| Legibilidad | El lector reconstruye la condición como su complemento. |
| Anidación | El camino principal queda dentro de un else innecesario. |
| Revisión | Comparar dos condiciones negadas es propenso al error. |
Fundamento en la cátedra¶
Complementa 0x1004h: Las condiciones complejas deben simplificarse o comentarse (simplificar condiciones) y 0x1013h: Detector de expresiones booleanas complejas sin paréntesis aclaratorios (paréntesis aclaratorios). La meta es que toda condición se lea como una frase en voz alta.
Alcance y excepciones¶
Aplica a if, while y a las condiciones de guarda. Se admiten negaciones
simples y claras (if (!es_valido)) sobre un nombre ya positivo; lo que se
evita es encadenar negaciones o negar expresiones compuestas.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — De Morgan implícito¶
if (!(hay_datos && es_valido && !esta_vacio)) {
return;
}
procesar();Por qué falla: la condición niega un && de tres términos, uno de ellos ya
negado. Entender cuándo se retorna exige aplicar De Morgan y dos inversiones.
❌ Contraejemplo 2 — Caso principal en el else¶
if (n <= 0 || v == NULL) {
/* error */
} else {
/* el caso normal, indentado un nivel de mas */
double promedio = calcular_promedio(v, n);
/* ... */
}Por qué falla: el camino que interesa queda relegado al else; conviene
guardar el error y seguir con el flujo principal al ras.
✅ Ejemplo conforme 1 — Guardas afirmativas primero¶
if (hay_datos && es_valido && !esta_vacio) {
procesar();
}La condición describe exactamente cuándo se procesa; la negación única
(!esta_vacio) es legible.
✅ Ejemplo conforme 2 — Error temprano y caso principal directo¶
if (n <= 0 || v == NULL) {
reportar_error();
return;
}
double promedio = calcular_promedio(v, n);
mostrar(promedio);El caso de error se atiende y se sale; el camino principal queda al ras, sin indentación extra (0x2001h: Las funciones deben usar cláusulas de guarda y retornos anticipados para reducir la anidación profunda).
⚠️ Casos límite¶
Predicados negativos inevitables:
!feof(f)es idiomático, pero la cátedra prefiere la lectura positiva del retorno de la lectura (0x4006h: Prohibición del antipatrón while (!feof(f)) para control de fin de archivo).Condiciones complementarias: cuando ambos caminos son igual de importantes, un
if/elseafirmativo es aceptable.Variables auxiliares: expresar
bool hay_espacio = !esta_lleno;puede aclarar una condición negativa, pero cuida no introducir negaciones dobles (0x0111h: Nombrá en positivo y evitá las dobles negaciones).
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
| Revisión manual | — | Condiciones con ! sobre expresiones compuestas. |
gaff | gaff check archivo.c | Reglas 0x1004h y 0x1013h. |
Checklist de autocontrol¶
¿La condición se lee como una frase afirmativa?
¿Evité negar una expresión con
&&o||?¿El camino principal está en el primer nivel de indentación?
¿Una variable auxiliar con nombre positivo simplificaría la condición?
Reglas relacionadas¶
0x1004h: Las condiciones complejas deben simplificarse o comentarse — simplificación de condiciones complejas.
0x1013h: Detector de expresiones booleanas complejas sin paréntesis aclaratorios — paréntesis aclaratorios.
0x0111h: Nombrá en positivo y evitá las dobles negaciones — nombrar en positivo.
0x2001h: Las funciones deben usar cláusulas de guarda y retornos anticipados para reducir la anidación profunda — guardas y retornos anticipados.