Skip to content
IRC-CodingIRC-Coding
Exception HandlingReturn CodeExit Codetry catchBashPythonLenguaje de programación

Exception Handling vs Return Codes vs Exit Codes

Manejo de errores: Exception Handling, Return Codes y Exit Codes. Ejemplos, ventajas, desventajas y preguntas de examen.

S

schutzgeist

14 min read
Exception Handling vs Return Codes vs Exit Codes

Manejo de Excepciones, Códigos de Retorno y Códigos de Salida

Este artículo es una explicación de conceptos sobre manejo de excepciones, códigos de retorno y códigos de salida, incluyendo preguntas de examen, componentes clave y etiquetas de referencia.

De un Vistazo

El manejo de excepciones, los códigos de retorno y los códigos de salida son tres estrategias para comunicar errores, cada una adaptada al lenguaje de programación, tipo de sistema y complejidad del problema.

Descripción Técnica Compacta

  • Manejo de excepciones: Los errores en tiempo de ejecución se tratan como objetos de excepción (por ejemplo, try/catch). Común en Java, C#, Python.
  • Códigos de retorno: Las funciones devuelven valores que señalan éxito o fallo (frecuente en C). Típicamente: 0 = OK, != 0 = Error.
  • Códigos de salida: El programa completo devuelve un código al sistema operativo al terminar. 0 significa éxito, cualquier otro valor indica error.

Los tres métodos sirven para procesar errores de forma estructurada, pero difieren en el nivel (función versus programa), cantidad de información y robustez.

Puntos Clave para el Examen

  • El manejo de excepciones es orientado a objetos y claramente estructurado. Separa el código normal del programa de la lógica de manejo de errores. Con try, catch y finally puedes reaccionar específicamente ante determinados errores y liberar recursos de forma segura.
  • Los códigos de retorno son valores devueltos por funciones, por ejemplo 0 = OK, 1 = Error. Son números simples que una función devuelve para indicar éxito o fallo. Típicos en C, Batch y sistemas más antiguos.
  • Los códigos de salida son valores de retorno a nivel de programa para shells y scripts. Se envían al sistema operativo cuando el programa termina. El valor 0 señala éxito, otros valores representan distintos tipos de error.
  • Los códigos de retorno y salida son frecuentes en shell, C, Batch (relevante para IHK). En el examen IHK debes saber en qué lenguajes y entornos se utilizan códigos de retorno y salida, y cómo interpretarlos.
  • Las excepciones proporcionan más contexto (tipo de error, stack trace) (aplicación práctica). Las excepciones contienen frecuentemente el tipo de error, un mensaje y un stack trace. Esto facilita mucho el análisis de errores comparado con códigos numéricos.
  • El manejo de errores no debe filtrar información sensible (aspecto de seguridad). Las excepciones y stack traces deben guardarse internamente en logs, pero solo mostrar mensajes generales al usuario. De lo contrario, revelan detalles de la arquitectura a posibles atacantes.
  • Los códigos de salida permiten automatización y control (eficiencia). Los scripts de shell, tuberías CI/CD y herramientas de automatización evalúan códigos de salida para controlar el siguiente paso. Son simples y legibles por máquinas.
  • Los mecanismos deben estar documentados y ser rastreables (obligación de documentación). El significado de códigos de retorno, tipos de excepciones y códigos de salida debe estar establecido en la documentación para que otros desarrolladores usen el código correctamente.

Componentes Clave

  1. try/catch/finally - try envuelve código que puede generar un error. catch captura la excepción y la maneja. finally contiene código que siempre se ejecuta, por ejemplo para cerrar archivos o conexiones.
  2. Clases de excepción personalizadas - Las clases de excepción personalizadas permiten modelar errores específicos del dominio de forma limpia. Hacen el código más legible y facilitan capturar tipos de error específicos.
  3. Códigos de error como constantes - Constantes como EXIT_SUCCESS o ERROR_FILE_NOT_FOUND hacen que los códigos de retorno y salida sean comprensibles. Evitan que aparezcan números mágicos en el código cuyo significado es difícil de entender.
  4. Interpretar valores de retorno - Cada llamada a una función con código de retorno debe verificar el resultado. Si olvidas evaluar el código, el programa puede continuar con datos erróneos.
  5. Terminación mediante exit() - Con exit() un programa termina la ejecución y envía un código de salida al sistema operativo. Es importante para que scripts o tuberías que llaman al programa puedan detectar el estado.
  6. Propagación de señales a procesos llamadores - El código de salida de un programa lo recibe el proceso que lo llamó o la shell. Los scripts lo utilizan para decidir si abortar o tomar un camino alternativo.
  7. Logging de excepciones y códigos - Las excepciones, códigos de retorno y códigos de salida deben registrarse en logs para que administradores y desarrolladores puedan rastrear errores. Los logs son especialmente importantes en producción.
  8. Pruebas unitarias para escenarios de error - Las pruebas unitarias verifican cómo se comporta el código ante errores. Esto incluye pruebas para excepciones, manejo de códigos de retorno inválidos y establecimiento correcto de códigos de salida.
  9. Analizar cascadas de errores - Una cascada de errores ocurre cuando un error provoca errores adicionales. Debes entender cómo se propagan los errores en un sistema para planear protecciones adecuadas.
  10. Convenciones de códigos de salida (por ejemplo Unix) - Los sistemas Unix siguen convenciones específicas para códigos de salida: 0 para éxito, 1 para errores generales y 2 para uso incorrecto de comandos. Respetarlas facilita la automatización.

Ejemplo Práctico Simple

Python: Manejo de Excepciones + Código de Salida

try:
  result = 10 / x
except ZeroDivisionError:
  print("Division durch Null!")
  raise SystemExit(1)

Bash: Evaluar Código de Salida

#!/bin/bash
cp datei.txt /zielpfad/
if [ $? -ne 0 ]; then
  echo "Fehler beim Kopieren!"
  exit 2
fi

Explicación: Python captura una excepción y termina con código de salida 1. Bash utiliza $? para obtener el código de retorno del último comando.

Java: Manejo de Excepciones con try/catch

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println(result);
        } catch (ArithmeticException e) {
            System.out.println("Fehler: " + e.getMessage());
        } finally {
            System.out.println("Aufraeumen");
        }
    }
}

C: Código de Retorno y Código de Salida

#include <stdio.h>
#include <stdlib.h>

int readFile() {
    FILE *file = fopen("datei.txt", "r");
    if (file == NULL) {
        return 1;
    }
    fclose(file);
    return 0;
}

int main() {
    int status = readFile();
    if (status != 0) {
        printf("Fehler beim Lesen\n");
        exit(1);
    }
    return 0;
}

Explicación: Java utiliza try/catch/finally para un manejo de errores estructurado. C utiliza códigos de retorno de funciones y establece un código de salida con exit() para el sistema operativo.

Ventajas y Desventajas

Manejo de Excepciones

  • Ventajas: estructurado, muchos detalles
  • Desventajas: más esfuerzo, no disponible en todas partes

Códigos de Retorno

  • Ventajas: simple, rápido, poco overhead
  • Desventajas: poco contexto, fácil de pasar por alto

Códigos de Salida

  • Ventajas: conforme al sistema operativo, ideal para automatización
  • Desventajas: sin detalles, solo numérico

Preguntas Típicas de Examen (con Respuesta Breve)

  1. ¿Diferencia entre manejo de excepciones y códigos de retorno? Las excepciones son objetos de error; los códigos de retorno son simples valores devueltos.
  2. ¿Cuándo se utilizan códigos de salida? Al terminar el programa, por ejemplo en scripts o CI/CD.
  3. ¿Qué significa código de salida 0? Éxito.
  4. ¿Por qué las excepciones suelen ser más robustas? Tratamiento explícito más contexto.
  5. ¿Cómo se evalúan códigos de retorno? Mediante comparaciones con if o $? en Bash.

Respuesta libre

Los mecanismos cubren diferentes niveles: Exceptions (nivel de método), códigos de retorno (contrato de función), códigos de salida (nivel de programa). En aplicaciones modernas predominan las Exceptions, pero en scripts, C/C++ y automatización los códigos de retorno y de salida siguen siendo centrales.

Notas adicionales

En los exámenes, asegúrate de distinguir entre el nivel de función, programa y sistema. En la práctica, las convenciones, el logging y la documentación son decisivos. En aplicaciones críticas de seguridad, las Exceptions no deben escapar sin filtrar al exterior.

Estrategia de aprendizaje

  1. Introducción conceptual: Compara el manejo de errores en C frente a Java frente a Bash.
  2. Profundización: Escribe un mini-programa que use Exception, código de retorno y código de salida.
  3. Enfoque en exámenes: Clasifica el manejo de errores en escenarios del IHK.
  4. Evitar errores: Usa convenciones (0=OK), evalúa códigos de retorno, registra Exceptions en logs.

Ejemplo de ejercicio 1: Capturar Exception en Python

def teilen(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return None
    finally:
        print("Berechnung beendet")

print(teilen(10, 2))
print(teilen(10, 0))

Explicación: Cuando se divide entre cero, se lanza una ZeroDivisionError. El bloque except la captura y devuelve None. El bloque finally se ejecuta en cualquier caso.

Ejemplo de ejercicio 2: Evaluar código de retorno en C

#include <stdio.h>

int pruefeZahl(int zahl) {
    if (zahl < 0) {
        return 1;
    }
    return 0;
}

int main() {
    int status = pruefeZahl(-5);
    if (status == 0) {
        printf("Zahl ist gueltig\n");
    } else {
        printf("Zahl ist ungueltig\n");
    }
    return status;
}

Explicación: La función pruefeZahl devuelve 0 si el número es válido, y 1 si es negativo. El llamador verifica el código de retorno y lo establece como código de salida.

Ejemplo de ejercicio 3: Evaluar código de salida en Bash

#!/bin/bash
mkdir /tmp/testordner
if [ $? -ne 0 ]; then
    echo "Verzeichnis konnte nicht erstellt werden"
    exit 1
fi
exit 0

Explicación: $? contiene el código de salida del último comando. Si mkdir falla, el script termina con código de salida 1. Si tiene éxito, termina con 0.

Tarea de ejercicio 1: Identificar manejo de errores

def leseDatei(pfad):
    try:
        with open(pfad, 'r') as datei:
            return datei.read()
    except FileNotFoundError:
        print("Datei nicht gefunden")
        return ""

Solución: Este código usa Exception Handling. FileNotFoundError se captura y se emite un mensaje. No hay código de retorno ni código de salida.

Tarea de ejercicio 2: Determinar código de salida

#include <stdlib.h>
int main() {
    exit(0);
}

Solución: El programa termina con código de salida 0, es decir, éxito. Un script que lo invoque lo interpretaría como exitoso.

Tarea de ejercicio 3: Código de retorno pasado por alto

int berechne(int a, int b) {
    if (b == 0) {
        return -1;
    }
    return a / b;
}

int main() {
    int ergebnis = berechne(10, 0);
    printf("Ergebnis: %d", ergebnis);
    return 0;
}

Solución: El código de retorno -1 se imprime como resultado normal porque el llamador no verifica si ha ocurrido un error. Este es un problema típico de los códigos de retorno.

Análisis de temas

  • Núcleo técnico: Comunicación de errores por niveles. Exception Handling, códigos de retorno y códigos de salida comunican errores en diferentes niveles: métodos, funciones y programas. Un ejemplo es un método Java que lanza una Exception, mientras que el script de shell llamador verifica el código de salida del programa completo.
  • Implementación: Método apropiado por sistema/lenguaje. La elección del manejo de errores depende del lenguaje de programación. Java y Python usan Exceptions, C usa códigos de retorno y los scripts de shell trabajan con códigos de salida. En sistemas híbridos, los mecanismos se combinan.
  • Seguridad: Evitar filtración de Stacktrace. Las Exceptions pueden revelar detalles internos como rutas de archivos o versiones de framework. En aplicaciones sensibles a la seguridad, solo deben mostrarse mensajes de error generales, mientras el Stacktrace se registra internamente.
  • Documentación: Describir valores de retorno y contratos de error. Cada módulo o programa debe documentar qué Exceptions lanza, qué códigos de retorno devuelve y qué códigos de salida establece. Un ejemplo es un documento API que enumera todos los códigos de error posibles.
  • Eficiencia: Automatización más robusta, menos interrupciones. Con un manejo claro de errores, estos se detectan y reparan temprano. En pipelines CI/CD, un código de salida diferente de 0 causa que un build se interrumpa antes de que ocurra un despliegue erróneo.

Información adicional

  1. https://docs.python.org/3/tutorial/errors.html
  2. https://tldp.org/LDP/abs/html/exitcodes.html
  3. https://www.geeksforgeeks.org/returning-values-from-c-functions/
  4. https://www.baeldung.com/java-exceptions
  5. https://linuxize.com/post/bash-exit/

Preguntas frecuentes: Exception Handling, códigos de retorno y códigos de salida

1. ¿Qué es Exception Handling?

Exception Handling es un procedimiento en el que los errores en tiempo de ejecución se tratan como objetos. Con try, catch y finally puedes capturar errores de forma específica y reaccionar ante ellos sin que el programa se bloquee inmediatamente.

2. ¿Qué es un código de retorno?

Un código de retorno es un valor que devuelve una función para indicar éxito o error. Por convención, 0 significa éxito y cualquier otro valor indica error.

3. ¿Qué es un código de salida?

Un código de salida es un valor que devuelve un programa al sistema operativo cuando termina. El valor 0 indica éxito, mientras que otros valores señalan errores.

4. ¿Cuál es la diferencia entre Exception Handling y código de retorno?

Exception Handling utiliza objetos de error con contexto como tipo de error y Stacktrace. Los códigos de retorno son números simples que proporcionan menos información, pero son rápidos y fáciles de manejar.

5. ¿Cuál es la diferencia entre código de retorno y código de salida?

Un código de retorno lo devuelve una función al llamador. Un código de salida lo devuelve un programa completo al sistema operativo cuando termina.

6. ¿Qué significa código de salida 0?

Un código de salida 0 indica éxito en la mayoría de los casos. El programa terminó sin errores. Otros valores señalan diferentes tipos de errores.

7. ¿Qué significa código de salida 1?

Un código de salida 1 suele indicar un error general. Muchos programas y scripts usan 1 cuando ocurre un problema inesperado.

8. ¿Qué es try/catch?

try/catch es una estructura para manejar errores. El código dentro de try se ejecuta. Si ocurre un error, el programa salta al bloque catch para tratar la Exception.

9. ¿Qué es finally?

finally es un bloque opcional que siempre se ejecuta, sin importar si ocurre una Exception o no. Es especialmente útil para liberar recursos.

10. ¿Qué es un Stacktrace?

Un Stacktrace muestra la cadena de llamadas de un programa en el momento en que ocurre una Exception. Ayuda a localizar el lugar en el código donde ocurrió el error.

11. ¿Qué lenguajes usan Exception Handling?

Exception Handling se usa en muchos lenguajes modernos, como Java, C#, Python, JavaScript y PHP. Los lenguajes funcionales suelen utilizar conceptos diferentes como Option o Result.

12. ¿Qué lenguajes usan códigos de retorno?

Los códigos de retorno son típicos de C, Batch y sistemas antiguos. En Go también se tratan los errores frecuentemente como valores de retorno, aunque devuelve un valor de error adicional.

13. ¿Qué lenguajes usan códigos de salida?

Casi todos los lenguajes de programación y scripts que se ejecutan a nivel del sistema operativo soportan códigos de salida. Son especialmente importantes en Bash, C, C++ y Python.

14. ¿Qué es $? en Bash?

$? es una variable especial en Bash que contiene el código de salida del último comando ejecutado. Con ella puedes verificar si un comando tuvo éxito.

15. ¿Cuándo debo usar Exception Handling?

Exception Handling es apropiado para aplicaciones complejas donde los errores deben tratarse detalladamente. Es especialmente útil cuando diferentes tipos de errores requieren tratamientos distintos.

16. ¿Cuándo debo usar códigos de retorno?

Los códigos de retorno son útiles cuando información de error simple es suficiente y deseas evitar overhead. Son típicos de programación de sistemas, scripts y interfaces antiguas.

17. ¿Cuándo debo usar códigos de salida?

Los códigos de salida deben usarse cuando un programa será evaluado por otros programas, scripts o pipelines CI/CD. Permiten un control simple de flujos de trabajo.

18. ¿Qué es una cascada de errores?

Una cascada de errores ocurre cuando un error genera otros errores. Sin manejo de errores apropiado, un problema único puede desestabilizar todo el sistema.

19. ¿Por qué las Exceptions no deben escapar sin filtrar?

Las Exceptions pueden contener información interna como rutas de archivos, versiones de framework o estructuras de base de datos. Si se muestran sin filtrar, los atacantes pueden usar esta información.

20. ¿Qué es logging en relación al manejo de errores?

Logging es el registro de eventos y errores. Las Exceptions, códigos de retorno y códigos de salida deben registrarse para que desarrolladores y administradores puedan rastrear problemas.

21. ¿Qué es una prueba unitaria para escenarios de error?

Una prueba unitaria para escenarios de error verifica cómo se comporta una función con entradas inválidas o condiciones críticas. Garantiza que las Exceptions se lancen, los códigos de retorno se establezcan y los códigos de salida se transmitan correctamente.

22. ¿Qué es un contrato de error?

Un contrato de error describe qué errores puede devolver una función o programa y cómo interpretarlos. Debe documentarse claramente.

23. ¿Qué es una Exception personalizada?

Una Exception personalizada es una clase de error definida por el usuario que representa un tipo de error específico. Hace el código más legible y permite capturar errores concretos.

24. ¿Qué es SystemExit en Python?

SystemExit es una Exception en Python que termina el programa y devuelve un código de salida al sistema operativo. Se lanza frecuentemente con raise SystemExit(1).

25. ¿Cuál es la ventaja de los códigos de salida en CI/CD?

Los códigos de salida son especialmente valiosos en CI/CD porque los pipelines pueden evaluarlos automáticamente. Un código de salida distinto de 0 interrumpe el build o deployment inmediatamente.

26. ¿Cuál es la desventaja de los códigos de retorno?

Los códigos de retorno ofrecen poco contexto. Un número simple no explica por qué ocurrió el error. Además, pueden pasarse por alto fácilmente si el llamador no los verifica.

27. ¿Cuál es la desventaja de las Exceptions?

Las Exceptions requieren más recursos y pueden hacer el flujo del programa más difícil de seguir. En algunos lenguajes o sistemas embebidos no están disponibles.

28. ¿Cuál es la diferencia entre nivel de método, programa y sistema en manejo de errores?

A nivel de método, los errores se tratan frecuentemente con Exceptions. A nivel de programa se usan códigos de salida. A nivel de sistema, el sistema operativo o la shell que llamó evalúa estos códigos y controla operaciones posteriores.

29. ¿Cómo se documenta el manejo de errores?

Se documenta el manejo de errores describiendo el significado de códigos de retorno, tipos de Exception y códigos de salida. También deben incluirse ejemplos y escenarios de error esperados.

30. ¿Cómo se elige el manejo de errores correcto?

La elección depende del nivel y el lenguaje. A nivel de método, las Exceptions suelen ser apropiadas; a nivel de función, códigos de retorno; a nivel de programa, códigos de salida. En la práctica, los mecanismos se combinan frecuentemente.
Volver al blog
Share:

Nächster Artikel in Desarrollo de Software

Weiterlesen
Fundamentos legales: Derechos de marca y copyright

Entradas relacionadas