Cláusula de guardia — Transforma los if "sucios" en algo elegante
Al finalizar este tema
Aprenderás a organizar las sentencias if anidadas mediante cláusulas de guardia y comprenderás por qué es importante la legibilidad del código.
Escribí el código de validación para el registro
Supongamos que debemos validar el nombre de usuario, la contraseña y el correo electrónico en un formulario de registro. Al principio, lo escribiríamos así:
function register(id, pw, email) {
if (id.length > 0) {
if (pw.length >= 8) {
if (email.includes('@')) {
if (!existingUsers.includes(id)) {
createAccount(id, pw, email);
return 'Registro completado';
} else {
return 'El identificador ya existe';
}
} else {
return 'Formato de correo electrónico no válido';
}
} else {
return 'La contraseña debe tener al menos 8 caracteres';
}
} else {
return 'Introduce un identificador';
}
}El código funciona. Pero léanlo: un if dentro de otro if dentro de otro if dentro de otro if... se desplazan constantemente hacia la derecha. Si añadimos solo dos condiciones más, está a punto de salirse por el borde derecho de la pantalla.
Dentro de seis meses, al volver a abrir este código, nos encontraremos preguntándonos "¿a qué if pertenece este else?", moviéndonos arriba y abajo entre líneas.
Cambiando a cláusulas de guardia
Podemos escribir la misma lógica de la siguiente manera:
function register(id, pw, email) {
if (id.length === 0) return 'Introduce un identificador';
if (pw.length < 8) return 'La contraseña debe tener al menos 8 caracteres';
if (!email.includes('@')) return 'Formato de correo electrónico no válido';
if (existingUsers.includes(id)) return 'El identificador ya existe';
createAccount(id, pw, email);
return 'Registro completado';
}Es la misma acción. Pero la sensación al leerla es completamente distinta.
Lo que ha cambiado son dos cosas:
- Invertimos la condición: en lugar de "si hay ID, continuar", ahora es "si no hay ID, terminar aquí".
- Retornamos inmediatamente: si hay un problema, salimos del código justo en ese punto.
Esto se conoce como Guard Clause (cláusula de guardia). Se establece una condición que no debe cumplirse al principio de la función; si alguna de estas condiciones falla, se retorna de inmediato. Es como un guardia de seguridad que realiza controles en la entrada.
¿Por qué es mejor?
La clave está en el orden de lectura.
Las instrucciones if anidadas mezclan el "camino normal" con las rutas de error. Solo al leer todo el código se puede ver claramente cuál es el flujo normal.
La cláusula de guardia maneja primero los errores y deja solo el camino normal al final. Al leer de arriba hacia abajo, el flujo se vuelve naturalmente: "esto no vale, aquello tampoco, si todo pasa la prueba, entonces ejecutar".
Flujo de lectura después de aplicar cláusulas de guarda:
✗ Sin identificador → fin
✗ Contraseña demasiado corta → fin
✗ Correo electrónico incorrecto → fin
✗ Identificador duplicado → fin
✓ Si se llega hasta aquí → ¡registro!Puntos a tener en cuenta
Las cláusulas de guardia no son una solución universal. No es posible usar return fuera de funciones, por lo que dentro de los bucles se debe utilizar continue en su lugar. Además, cuando las condiciones están complejamente entrelazadas (por ejemplo, A y no B y C), puede ser más adecuado combinar las condiciones mediante operadores lógicos en lugar de usar cláusulas de guardia.
El refactorización se aplica naturalmente cuando el código se vuelve complejo. Intentar escribir código optimizado desde el principio suele ser una pérdida de tiempo. Primero haz que funcione y, cuando resulte difícil de leer, entonces organízalo.
Lo mismo en otros lenguajes
Las cláusulas de guardia no son un patrón exclusivo de JavaScript. Funcionan en cualquier lenguaje que tenga return:
# Pythondef register(id, pw, email): if not id: raise ValueError("Introduce un identificador") if len(pw) < 8: raise ValueError("La contraseña debe tener al menos 8 caracteres") if "@" not in email: raise ValueError("Formato de correo electrónico no válido")
create_account(id, pw, email)// Go
func Register(id, pw, email string) error {
if id == "" {
return errors.New("id required")
}
if len(pw) < 8 {
return errors.New("password too short")
}
createAccount(id, pw, email)
return nil
}En Go, dado que la convención del lenguaje es retornar errores, la Cláusula de Guarda (Guard Clause) se convierte naturalmente en un patrón estándar. Independientemente del lenguaje que se utilice, el principio de "filtrar primero lo anormal y dejar solo el flujo normal" es el mismo.
Clave
Una Cláusula de Guarda es un patrón que consiste en "filtrar primero las condiciones que no se cumplen y retornar inmediatamente". Elimina el infierno de sangría de las sentencias if anidadas y separa el manejo de errores del flujo normal. Invertir la condición (
if normal→if anormal) y salir inmediatamente: esto es todo.