Skip to main content

Inicia sesión en CleanKata

Sigue tu progreso, gana XP y desbloquea todas las lecciones.

Al iniciar sesión aceptas nuestros Términos de uso y Política de privacidad.

Código Limpio60 XP6 min

Manejo Limpio de Errores

El manejo de errores es una preocupación separada — mantenla aislada para que tu algoritmo principal sea legible.

Excepciones vs. Códigos de Retorno

Los códigos de retorno obligan al invocador a verificar cada resultado inmediatamente, contaminando el punto de llamada con condicionales. La lógica de manejo de errores se entrelaza con la lógica de negocio. Las excepciones separan el camino feliz de los casos de error, permitiendo escribir el algoritmo una vez, con claridad, y manejar los fallos en un lugar enfocado.

Códigos de retorno — el manejo de errores domina

result = db.connect()
if result == ERROR_NO_CONNECTION:
    log("connection failed")
    return ERROR_NO_CONNECTION

result = db.query(userId)
if result == ERROR_NOT_FOUND:
    log("user not found")
    return ERROR_NOT_FOUND

result = db.save(result)
if result == ERROR_SAVE_FAILED:
    log("save failed")
    return ERROR_SAVE_FAILED

Excepciones — el camino feliz es legible

try:
    connection = db.connect()
    user       = db.query(userId)
    db.save(user)
catch NoConnectionError:
    log("connection failed")
catch UserNotFoundError:
    log("user not found")
catch SaveFailedError:
    log("save failed")

El Bloque Try-Catch-Finally

Piensa en try-catch-finally como una transacción de base de datos: define un ámbito. El bloque try es el cuerpo de la transacción. El catch maneja el rollback. finally siempre se ejecuta (limpieza de conexión, handles de archivos). Extrae el cuerpo de los bloques catch en funciones con nombre: un bloque catch de más de 2 líneas es una función esperando nacer.

Lógica enterrada dentro del catch

try:
    processPayment(order)
catch PaymentError as e:
    log("Payment failed: " + e.code)
    notifyFinanceTeam(order, e)
    order.status = "failed"
    db.update(order)
    sendFailureEmail(order.user, e.message)
    metrics.increment("payment.failures")

Extrae el cuerpo del catch a una función

try:
    processPayment(order)
catch PaymentError as e:
    handlePaymentFailure(order, e)

function handlePaymentFailure(order, error):
    log("Payment failed: " + error.code)
    order.status = "failed"
    db.update(order)
    notifyFinanceTeam(order, error)
    sendFailureEmail(order.user, error.message)
    metrics.increment("payment.failures")

El Peligro del Null

Devolver null obliga a cada invocador a comprobarlo. Un null check olvidado = crash en runtime. Pasar null como argumento es igual de peligroso: la función receptora debe protegerse contra él. En su lugar: lanza una excepción, devuelve una colección vacía o usa el patrón de Caso Especial (Null Object).

// ✗ Returns null — caller must remember to check
function findUser(userId):
    row = db.query(userId)
    if not row:
        return null   // ← every caller must null-check

user = findUser("123")
if user:             // easy to forget
    process(user)

// ✓ Option 1: raise an exception
function findUser(userId):
    row = db.query(userId)
    if not row:
        raise UserNotFoundError(userId)
    return User.fromRow(row)

// ✓ Option 2: Special Case / Null Object
class GuestUser:
    name = "Guest"
    function canCheckout(): return false

function findUser(userId):
    row = db.query(userId)
    if row:
        return User.fromRow(row)
    return new GuestUser()

// ✓ Option 3: empty collection (for list results)
function findOrders(userId):
    return db.queryOrders(userId) or []

Desafío de Código

Reemplaza Códigos de Retorno con Excepciones — reescribe para separar el camino feliz del manejo de errores.

💡Conclusión clave

El manejo de errores es una preocupación separada. Escribe primero el camino feliz, luego trata los fallos en un lugar enfocado.

🔧 Algunos ejercicios pueden tener errores. Si algo parece incorrecto, usa el botón Feedback (abajo a la derecha) para reportarlo — nos ayuda a corregirlo rápido.

Pista: Escribe primero el camino feliz como si nada pudiera salir mal. Luego pregunta en cada paso: ¿qué podría fallar aquí? Cada fallo se convierte en una excepción lanzada. El llamador decide cómo manejarlo, no el llamado.

✗ Tu versión