AYUDA : Validaciones vs Excepciones

Hola a todos, estamos en pleno periodo vacacional para algunos, otros no (nos queda poco, poco) y me ha surgido un problema, que espero que podáis ayudarme a resolver. Se refiere al tema de trabajar con validaciones o trabajar con excepciones y su rendimiento.

 

A la hora de desarrollar un método cuando este recibe parámetros lo “ideal” es comprobar que los parámetros que nos llegan son válidos para utilizarlos en nuestra lógica posterior, así que según dicho esto lo que yo creo como ideal, es que la primera parte de un método sería validar la entrada de los parámetros y si está todo ok, seguir adelante.

 

Bueno, en mi caso, la realidad es bastante diferente, en mi caso particular y “chapucero” (estoy intentando cambiar…), yo soy más de los de “try…catch” y listo y sí, debo admitir que algún catch vacío existe por mi código, aunque cada vez que lo veo digo “aghhhhhhh, mis ojos, mis ojos….”

 

Esto es MALO, porque cuando te llegan varios parámetros o parámetros complejos y te da un error en el catch, no tienes la certeza de saber en qué punto te ha dado, lo normal es el típico error de “Object reference not set…” y listo, ahora tienes que averiguar en qué punto se te ha ido la pinza…

 

En este caso está claro que lo mejor es validar la entrada y después hacer lo que tengas que hacer, pero mi problema está en el rendimiento, y pensaba que era mucho más eficiente validar que trabajar con la excepción, que costaría mucho más trabajar con una excepción que con validaciones, así que me generé un código sencillo para poder verlo.

static void Main(string[] args)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int aux = 0; aux < 10; aux++)
{
DoSomething(null);
}
Console.WriteLine("Tiempo total Exception " + sw.Elapsed.TotalSeconds.ToString());
sw.Stop();
sw.Start();
for (int aux = 0; aux < 10; aux++)
{
DoSomethingHasValue(null);
}
Console.WriteLine("Tiempo total HasValue " + sw.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}

private static void DoSomething(int? i)
{
try
{
int local = i.Value;
}
catch (Exception)
{
Console.WriteLine("Valor de i nulo");
}
}

private static void DoSomethingHasValue(int? i)
{
if (i.HasValue)
{
int local = i.Value;
}
}

 

Pues la salida de ese ejemplo es que las excepciones son un poco más rápidas que el “HasValue”, da igual que ponga 10, 100, 1000 o 10000, que compile en Debug o en Release, que ejecute dentro del Visual Studio o fuera.

 

Lo único que vi, es que con las excepciones en el windbg (herramienta molona) genera un montón de ruido, por otra parte normal.

 

Tengo varias cosas bastante claras, una es que se mucho mejor validar la entrada antes que dejar el control en un try…catch global, aunque no se por rendimiento, el mantenimiento posterior será mucho más sencillo. Otra cosa es que seguro que el código que he puesto está mal pero no consigo encontrar dónde y la verdad, me sorprendió mucho que sea más rápido capturar una excepción que hacer una validación.

 

Espero que podáis dedicar un tiempo y echarme una mano.

 

Muchas gracias a todos.

Mario Ropero.

 

EDITO: Gracias a un compi que ha visto el error del código que he puesto, he llegado a dos conclusiones, una soy un rato inútil por no haberlo visto antes y dos, realmente es mucho más eficiente validar antes que lanzar excepciones. Os dejo el código arreglado que lo comprueba:

static void Main(string[] args)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int aux = 0; aux < 10; aux++)
{
DoSomething(null);
}
Console.WriteLine("Tiempo total Exception " + sw.Elapsed.TotalSeconds.ToString());
sw.Stop();
sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int aux = 0; aux < 10; aux++)
{
DoSomethingHasValue(null);
}
Console.WriteLine("Tiempo total HasValue " + sw.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}

private static void DoSomething(int? i)
{
try
{
int local = i.Value;
}
catch (Exception)
{
Console.WriteLine("Valor de i nulo");
}
}

private static void DoSomethingHasValue(int? i)
{
if (i.HasValue)
{
int local = i.Value;
}
}

Gracias por vuestro tiempo.

Un saludico.

Mario.

14 comentarios en “AYUDA : Validaciones vs Excepciones”

  1. Yo llevo tiempo dandole vueltas a como implementar una capa de validaciones para usar desde la capa de negocio, algo parecido a un framework para reutilizar desde la capa de negocio y poner las validaciones en clases, luego incorporar estas a la interface que puede ser web o escritorio o servicio web o similar ¿se te ocurre alguna buena practica para desarrollarlo o tienes algun link a documentacion de microsoft?

    Gracias

  2. Hola,

    Yo lo que hago es validar la entidad en la capa de negocio, y si existen errores lanzar una excepción “customizada” (por ejemplo ValidationException). Entonces desde la presentación siempre hago un catch de ese tipo de excepción y hago que la aplicación responda en consecuencia.

    Saludos

  3. Pues a mi no me parece correcto gestionar las validaciones con Excepciones, por un lado son un artefacto bastante pesado dentro del Fwk, y por otro lado como su nombre lo indica, las excepciones son para tratar situaciones no contempladas dentro del código.

    Pero bueno es una opinion 😀

  4. Revisando tú código rapidamente, creo que el problema puede estar entre el stop y el start, que lo que estas haciendo es pararlo y volverlo a arrancar, pero el tiempo que muestras es entre que paras y se ejecuta el HasValue. Con el siguiente cambio se nota el rendimiento:

    sw.Stop();

    sw = new System.Diagnostics.Stopwatch();

    sw.Start();

    Tiempo total Exception 0,0572096
    Tiempo total HasValue 0,000355

    Salu2

  5. Estoy con Luis la diferencia de tiempo es causada por la falta de un sw.Reset(); antes del segundo sw.Start() .. me suena el olvido, a mi me pasa también!

    De todas formas estoy con Bruno y creo que no debería ser el objetivo de las excepciones validarnos los input de un método.

  6. Para Luis: Gracias… joe que zanguango soy :). Ya decía yo que no podía ser más eficiente una cosa que la otra… no no no.

    Por cierto estoy totalmente de acuerdo con Bruno, las excepciones no son para validar, ni para mandar mensajitos al cliente.

    Además como ya ha comprobado nuestro amigo Luis, es mucho más eficiente comprobar que lanzar una excepción.

  7. Los que comentáis que no validáis con excepciones… comentar que bueno, antes lo hacía sin excepciones, pero creo que al final era más propenso a errores. Una excepción mal gestionada no se quedará ahí, como un cacth sin código, te petará en la cara 😛

    Por otro lado, qué alternativas habría? Tengo curiosidad por el tema.

    Saludos

  8. @Jesús: A ver, lo que yo no veo es que tú canal de información a las distintas capas de aplicación para una validación de negocio sea a través de una excepción. Por poner un ejemplo, si un campo de una entidad digamos Cliente viene a null y tú lo necesitas, el hacer un throw de una exception para informar que el cliente está a null… pues no lo veo.
    Parafraseando a un crack de por aquí (Luis Guerrero), las excepciones son algo excepcional y no por validaciones de código si no por algo que tú no puedes controlar.
    Alternativas, por desgracia estoy buscando alguna que me convenza, como ya he dicho en el post yo soy/era el típico bruto de try…catch y ale… ya se verá. Estoy buscando algo… si consigo dar con ello intentaré haceroslo llegar…
    Pero para ponerte un caso, en mi cliente actual, se lanza excepciones para informar sobre validaciones, típico “No se encuentra ese cliente” y cosas similares, y a la hora de utilizar windbg es horrible el ruido que meten esas validaciones…

    Pufffffff rollazo que he soltado…

  9. @Luis: Mirando CodeContracts he visto que aunque da una herramientas muy potentes para la validación de datos el sistema que utiliza para la comunicación de los incumplimientos en el lanzamiento de un ContractExecption. ¿Sabes si tiene algún otro método de comunicación que no sea lanzando excepciones?

  10. Yo estoy de acuerdo, creo que que antes de gestionar una excepción hay que gestionar un proceso de validación.

    Pero entiendo que cuando te encuentras en el mantenimiento de un sistema con try catch {} vacios se te ponen los pelos de punta…

    Os cuento la solución por la que optamos:

    En CIC disponíamos de un sistema de logueo de Excepciones basado en la Enterprise Library y el logging applicaction block, pero se decidió implementar uno propio que integrase mas funcionalidad y no dependiese de las dlls de la EL.

    Se diseñó uno con una serie de caracteríticas:
    – Mas información de detalle: stack trace, procesos activos, prioridad, memoria ocupada, equipo, usuario,… incluso bajo petición un memory dump.
    – Captura de pantalla del momento previo.
    – Notificaciones via mail, evento log de windows, ficheros de texto… incluso auto inserción en nuestro bug tracker.
    – Un interfaz chula que informe del error transmitiendo calma y serenidad al usuario.

    El caso es que una vez que preparamos esa DLL se vio que la potencia era muy grande y se podía utilizar en otros desarrollos…

    Y vino uno con un montón de Catch {}, no penseis que era uno de un supermercado, era un módulo de gestión de un reactor nuclear! (no es broma)

    El caso es que con un simple find and replace se cambiaron los catch vacios por una correcta gestión de la excepción. (tiempo dedicado 6 minutos)

    Obviamente después hemos tenido que revisar cada uno con detenimiento, pero la información que nos ha devuelto el sistema ha sido crucial para dar con los errores vacios.

    Si alguien quiere esa DLL de gestión de excepciones que me la pida.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *