CERRADO POR VACACIONES!!!!!

 

El armario se cierra por vacaciones, qué ilusión que me hace poder decir esto. Voy a pasar las siguientes 6 (seis!!!!!!!) semanacas descansando, intentaré aprovechar para leer algo y culturizarme un poco, pero no creo que tenga mucho tiempo para escribir, así que dejaremos la actividad por un tiempo.

 

Un saludo y disfrutad los que podáis.

 

Mario Ropero.

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.

Ejecutar un servicio de Windows en 32-bit en un Windows de 64-bit

Hola a todos, llevo un tiempo apartado de los maravillosos mundos de internés, porque estamos en fase de puesta en producción en mi proyecto actual, y ya sabéis como es eso. Muchos nervios por parte de la jefatura, se ven algún que otro látigo de siete colas, alguna que otra frase graciosa del tipo “¿Dormir? Para que necesitas dormir… a trabajar…” y cosas similares. Bueno, pues unos de los diversos cambios que se hizo fue en la plataforma y pasamos de un bonito Windows Server 2003 32 bit a su esplendido predecesor el Windows 2008 Server 64-bit. Y después de unas pruebas de concepto con la aplicación vimos que todo funcionaba incluso un poco mejor, pero…¿todo?, NO todo no funcionaba a la perfección. Teníamos un pequeño servicio de Windows que se encargaba de ejecutar unos procesillos asíncronamente que decidió dejar de funcionar.

 

La situación fue un poco caótica, un procesillo del que nadie se había acordado, paso a ser la prioridad número uno, vamos que se caía el mundo si eso no funcionaba. Y allí estaba yo, con un montón de jefes revoloteando a mi lado, mirando la pantalla de mi ordenador y sus smartphones viendo que el mundo se caía, y haciendo los típicos comentarios que imagino que todos hemos escuchado alguna vez “¿Ya está?”, “¿Seguro que eso es por (poned aquí cualquier cosa que paso el día anterior que no tenga nada que ver con esto)?”, “Esto tiene que estar ya”. Y yo ahí aguantando el chaparrón y el servicio sólo me decía “No encuentro la xxx.dll”, y yo… “Joé, que la dll está aquí, ¿dónde quieres que te la deje corazón?”.

 

Lo único que había cambiado era la plataforma, así que me dije, voy a ejecutarlo en 32-bit y a probar, y… más problemillas no tenía acceso al código para compilarlo para la plataforma x86, que sería la solución ideal, y busqué por internet y encontré una pequeña maravilla que se esconde en el Windows 2008 SDK (esta herramienta es más antigua, pero para el 2008 se encuentra ahí), la herramienta ‘CorFlags.exe’.

 

Esta herramienta se encuentra en “C:Program FilesMicrosoft SDKsWindowsv6.0Binx64CorFlags.exe “, y sirve para activar el modo 32BIT a un ejecutable, en mí caso el servicio.

Para ejecutarla, es muy sencillo, si queremos poner el modo 32BIT:

CoreFlags.exe Ejecutable.exe /32BIT+

Si queremos quitar el modo 32BIT:

CoreFlags.exe Ejecutable.exe /32BIT-

Y con eso todo empezó a funcionar. Y el pequeño proceso dejó de ser la prioridad uno, y todo el mundo respiró más tranquilo. Luego estuve investigando un poco más, y el problema no era el proceso en sí que puede ejecutarse en 32 o 64, era la dll que referenciaba (un proveedor de base de datos) que no estaba instalado en modo 64bit porque no existía.

 

Hasta la próxima.

Una de TransactionScope por favor!!!!

Buenos días a todos, no tenía pensado en escribir nada de este maravilloso elemento, pero estamos haciendo una pequeña refactorización de código porque algún DBA nos dijo que en nuestra aplicación teníamos un poco de contención con las transacciones y yo pensé “Transacciones?? Si prácticamente no las usamos”, infeliz de mí, luego hice una búsqueda sencilla por el código y aquí estoy quitando código y escribiendo sobre esto.

 

Lo que me he encontrado hasta la saciedad es esto

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
//Acción sobre base de datos
DoSomething.....
scope.Complete();
}

Dónde el DoSomething es un Insert, un Update, un Delete o un Select (sí, sí… se ven cosas que dan mucho miedito), a ver…

¿PARA QUÉ NECESITAS UNA TRANSACCIÓN?, es que parece que si un insert está dentro de una transacción mola más o debe ser algo parecido, pero lo único que hace es NADA, o dar un poco por saco en todo caso.

 

Otro caso gracioso es poner una transacción para una sentencia de selección, joe… esa es buenísima y la he visto demasiadas veces por desgracia, ahora imaginaos una select entre varias tablas de vuestra base de datos que sea pesada y que tenga un transactionscope con IsolationLevel a Serializable (uuuuuuuuuuuuhhh escalofríos me entran sólo de pensarlo).

 

Otro tema son los transactionscopes encadenados, para hacer justamente eso, una acción, esto encima tiene delito porque pones a trabajar al DTC en una transacción distribuida, os pongo un ejemplito de código que me he encotrado, para que veáis:

private void Metodo1()
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{ //Acción sobre base de datos
Metodo2();
scope.Complete()
}
}

private void Metodo2()
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{ //Acción sobre base de datos
DoSomething...
scope.Complete()
}
}

 

Conclusión

Los TransactionScope están para lo que están, no para abusar de ellos porque nos pueden poner en situación bastante perjudiciales para el rendimiento de nuestra máquina, y nos pueden a llevar a bloqueos en base de datos sin quererlo. Así que se tienen que usar con cabeza y vuelvo a repetir, UNA ÚNICA OPERACIÓN EN BASE DE DATOS NO NECESITA UN TRANSACTIONSCOPE.

 

Perdonad por el tono del post, es que estoy muy cabreado con esto, que estoy aquí pico y pala quitando transactionscopes que me salen por las orejillas, intentaré escribir algún post con algún ejemplo más tangible.

 

Saludicos.

[WCF] Pasar información entre las distintas “capas” del servidor

Hola a todos, siguiendo con los artículitos de WCF, os vengo a hablar de una solución que implementamos en un cliente para pasar información a través de su parte servidora sin tener que tocar la firma de los métodos, porque había unos cuantos. Esto se implementó a través del OperationContext que nos ofrece la activación del servicio WCF y la verdad es que funciona de vicio. Pero cómo me dijo un gran crack sobre esto, hay que tener cuidado con el OperationContext porque no deja de ser una sesión de servidor, pero es finita y se sabe en qué momento se invalida y se crea. Os paso a contar el problema que teníamos…

 

El problema

Bueno, el problema era más o menos sencillo, en la solución implementada existían entidades de datos muy, muy, muy pesadas y obtenerlas consumía mucho tiempo de base de datos e impactaba muchísimo en el rendimiento de la aplicación. Cómo la solución tenía una sesión de servidor ya implementada (cosa que ya quitamos), pues se metió una especie de cache que se creaba cuando se iniciaba la llamada al servicio y se destruía cuando se terminaba la ejecución del servicio. Pero estaba construida de aquella manera y cuando se sometió a pruebas de concurrencia… en fin, podría haber salido mejor.

 

¿Qué necesitabamos?

La necesidad era poder pasar las entidades que ya se habían obtenido de un método a otro, o de una capa a otra del servidor, para no tener que volver a obtenerlas una y otra vez. La respuesta clara y más sencilla… pasemos esa información en la llamada a los métodos. Después vimos que había que tocar muchos, muchos, muchos métodos y se descartó por tiempo y esfuerzo 🙁

 

La solución que implementamos

Un compañero muy listo que tengo me dijo “oye, mira a ver si en el contexto de operación puedes pasar información personalizada”, así que me puse manos a la obra y encontré que se puede, vaya si se puede, a través de la interfaz IExtension. La verdad es que se pasa una hashtable (nos encantan las hashtables, tenemos kilo y medio de ellas) con la información que queremos, no es muy bonito, de hecho es feote, pero funciona (esta frase es uno de los peores males en esto de la programación…).

Para hacer esto, creamos una clase que implemente la interfaz IExtension<IContextChannel>, porque queremos almacenar la información en el canal, y tenemos que implementar los métodos “Attach” y “Detach”.

Algo parecido a esto

using System.Collections;
using System.ServiceModel;

namespace TestIExtension
{
public class ExtensionTest : IExtension<IContextChannel>
{
Hashtable mHash = null;

public Hashtable Hash
{
get { return mHash; }
set { mHash = value; }
}

#region IExtension<IContextChannel> Members

public void Attach(IContextChannel owner)
{
if (mHash == null)
{
mHash = new Hashtable();
}
}

public void Detach(IContextChannel owner)
{

}

#endregion
}
}

Pensad que en vez de una hashtable en modo cajón desastre, se puede poner cualquier tipo de información.

Para utilizar esta extensión en vuestro código, para recoger la información o para insertarla tendremos que utilizar el siguiento código:

if (OperationContext.Current != null &&
OperationContext.Current.Channel != null &&
OperationContext.Current.Channel.Extensions != null)
{
TestIExtension testExtension = OperationContext.Current.Channel.Extensions.Find<TestIExtension>();
if (testExtension != null)
{
return cacheExtension.Hash;
}
}

 

Como esta información está “viva” durante toda la activación del servicio, da exactamente igual desde que “capa” llamemos a este código porque siempre estará disponible.

Otra cosa que encontramos que estaba bastante bien, es que aunque los servicios estén en modo Single, esta información se genera en cada llamada al servicio. Cosa totalmente lógica y normal, pero bueno en esto nunca se sabe :).

 

Conclusiones

WCF mola!!!! y el contexto de operación está genial y se le pueden hacer mil y una perrería, pero si me queda una cosa clara es que, la información que necesite un método se le debería pasar siempre por parámetros, vamos que un método debería disponer de toda la información que necesita de forma explícita y así no llevar a ninguna confusión, esto puede no ser cierto en todos los casos, pero en la medida de lo posible la simplicidad ayuda mucho (Keep it simple!!!!).

 

Saludicos.