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.