I Remote

Otro blog sobre programación en C#, grupos de usuarios .Net y más rollos tecnológicos por el estilo.

jueves 23 de julio de 2009

Wikipedia Explorer ahora sobre Azure


DotNet Solutions ha actualizado su Wikipedia Explorer que ahora utiliza la tecnología de Windows Azure para convertir la base de datos de la Wikipedia a formato XML/XAML y así acelerar la aplicación que antes convertía los datos al vuelo.

Wikipedia Explorer es una aplicación WPF que proporciona una nueva forma de navegar por la wikipedia, visualizando las relaciones entre documentos.
Gracias a la plataforma Windows Azure han podido reducir el tiempo de proceso para la conversión de la base de datos de 6 meses a 5 días.
La aplicación está disponible en modo ClickOnce aquí.

viernes 24 de abril de 2009

Las verdaderas razones detrás de un cambio

Hoy, leyendo una entrada de Jose Fco Bonnin, me han empezado a sonar las alarmas y he sentido la necesidad de investigar un poco.

El motivo de su post es que en el VS2008 se quitaron algunas reglas del FxCop, entre ellas la "CA1818 - Do not concatenate strings inside loops".
Tal como Jose ha comprobado, no ha habido ningún cambio en el framework para que esa regla se pueda quitar y el motivo que alega el equipo de Code Analysis es que la han quitado debido a "high noise or no longer applicable analysis".

Cualquier desarrollador de .Net que se haya preocupado un mínimo por el rendimiento una de las primeras cosas que suele mirar es si la aplicación está generando demasiados strings; así que debe haber alguna otra razón para quitar esa regla del motor.

Tras buscar un poco he encontrado unas entradas que nos dan alguna una pista: tanto en una conversación en el foro de fxcop beta como en una nota de su blog comentan que el "data flow analysis engine", el encargado de comprobar esa regla, ha sido eliminado porque no funcionaba bien, era muy lento y además indeterminista.
Es una opinión/deducción personal, pero creo que nos han contado una verdad a medias y el impacto de haber quitado esa regla puede ser verdaderamente alto en aplicaciones grandes.

Teóricamente Phoenix iba a arreglar el desaguisado pero no parece que tenga continuidad, así que habrá que ver si en vs2010, que vuelve a tener un data flow engine, las reglas se han vuelto a activar. ¿Alguien lo ha probado ya?

lunes 23 de febrero de 2009

Serialización dinámica con el XmlSerializer

Para acabar con esta espontanea serie de posts sobre el XmlSerializer os cuento un par de trucos no demasiado bien documentados para controlar la serialización.

En algunas ocasiones podemos necesitar que una clase hija no persista algunas de las propiedades del base, pero, como ya hemos visto antes, si la propiedad no es virtual se complica un poco el asunto. En estos casos podemos añadir un miembro público a la clase base con el mismo nombre de la propiedad + Specified con el valor a true:

public class C1
{
	public string MyProperty { get; set; }
	[XmlIgnore]
	public bool MyPropertySpecified = true;
}


De esta manera al heredar de la clase podremos especificar su valor a false, lo que hará que no se persista dicha propiedad:



public class C2:C1
{
	public string MyOtherProperty { get; set; }
	public C2()
	{
		MyPropertySpecified = false;
	}
}


En otras ocasiones, lo que querremos es decidir cuando se debe persistir el valor y cuando no. Por ejemplo, si una lista no tiene valores o si un string es null puede que no nos interese que aparezca el valor vacío en el xml. Eso se consigue con un método público llamado ShouldSerialize + el nombre de la propiedad y que devuelva un bool indicando si la propiedad debe persistirse:



public class C3 : C2
{
	public string MyThirdProperty { get; set; }
	public bool ShouldSerializeMyThirdProperty()
	{
		return false;
	}
}


Ahora podéis probar las clases, adivinad qué mostrará cada llamada:



XmlSerializer ser = new XmlSerializer(typeof(C1), 
	new Type[] { typeof(C2), typeof(C3) });
ser.Serialize(Console.Out, new C1() { MyProperty = "test"});
Console.WriteLine();
ser.Serialize(Console.Out, new C2() { MyProperty = "test", 
	MyOtherProperty = "test 2" });
Console.WriteLine();
ser.Serialize(Console.Out, new C3() { MyProperty = "test", 
	MyOtherProperty = "test 2", MyThirdProperty="test 3" });
Console.ReadLine();

viernes 20 de febrero de 2009

XmlSerializer y ocultación de propiedades

Esta mañana tras responder a un post de Eduard Tomàs i Avellana me ha dado por investigar un poco más sobre el tema...

En su caso el problema tenía solución pues podía modificar ambas clases, pero ¿qué pasaría si estamos heredando de una clase que no podemos modificar? Hay múltiples soluciones, desde el uso de un patrón Adapter hasta la implementación del interface IXmlSerializable, pero todas ellas requieren escribir una cantidad considerable de código.
Pero... en algunos casos nos podría servir una sobrecarga del XmlSerializer que admite como argumento una instancia del XmlAttributeOverrides, que, como su propio nombre indica, nos permite sobrecargar los atributos que usa el XmlSerializer sobre una clase para generar el código de serialización. Aunque tiene sus peligros podremos influir en cómo se serializa la clase base sin tener que modificarla.
Por ejemplo, si tuviéramos la siguiente definición de clases:

public class C1
{
 List<C1> _myList = new List<C1>();
 public List<C1> MyList { get { return _myList; } }
}

public class C2:C1
{
 List<C2> _myList = new List<C2>();
 public new List<C2> MyList { get { return _myList; } }
}

Al crear el XmlSerializer nos daría un error de reflexión como pasaba en el caso de Eduard. Pero podemos obligar al serializador que ignore la propiedad de la clase base mediante el siguiente código:


XmlAttributeOverrides xOver = new XmlAttributeOverrides();
XmlAttributes atts = new XmlAttributes(){ XmlIgnore=true};
xOver.Add(typeof(C1), "MyList", atts);
XmlSerializer ser = new XmlSerializer(typeof(C2),xOver);
ser.Serialize(Console.Out, new C2());

Aunque hay que usarlo con extremo cuidado, pues cualquier otra instancia del tipo C1 o derivados no serializará la propiedad MyList con ese serializador.

¿Alguien más se anima a encontrar otra solución?

viernes 6 de febrero de 2009

Optimización de XmlSerializer

Ayer, haciendo una de revisión en un servicio,  nos dimos cuenta que se hacían continuamente llamadas al csc.exe. Esto provocaba que el servicio fuera muy lento y además consumiera mucha memoria, así que nos pusimos manos a la obra.

Como sabíamos que el servicio hacía un uso intensivo de la serialización Xml con el XmlSerializer no hizo falta hacer debug sino que fuimos a mirar el código que probablemente invocaba al csc.

Paso directamente a describir cómo funciona y el porqué del comportamiento que encontramos.

En .Net serializar una clase sencilla (sin referencias circulares, con al menos el constructor por defecto, etc...) a Xml es bastante directo, sólo necesitas crear un XmlSerializer para la clase en cuestión, por ejemplo, si tenemos un conjunto de clases así:
public class BaseClass
{
 public int BaseProperty { get; set; }
}

public class TestClass
{
 public string MyProperty1 { get; set; }
 public BaseClass MyProperty2{get;set;}
}

Para serializar TestClass podríamos usar el siguiente código:

TestClass xmlSerializableClass =
 new TestClass { MyProperty1 = "test", MyProperty2 = new BaseClass()};
XmlSerializer serializer = new XmlSerializer(typeof(TestClass));
serializer.Serialize(Console.Out, xmlSerializableClass);

Al ejecutarse genera un archivo .cs con el código de serialización de nuestra clase lo compila y lo ejecuta para serializarlo. La siguiente vez la clase XmlSerializer no volverá a compilar pues guarda internamente una lista con (casi) todos los serializadores que va creando.

Si heredamos de BaseClass y queremos que nuestra nueva clase se incluya en el serializador hay que agregar un atributo para que el XmlSerializer la tenga en cuenta automáticamente, en caso contrario nos daría un error en tiempo de ejecución:
public class AnotherClass:BaseClass
{
 public int AnotherProperty { get; set; }
}

[XmlInclude(typeof(AnotherClass))]
public class BaseClass
{
 public int BaseProperty { get; set; }
}


De esta manera el siguiente código seguirá funcionando y utilizando el caché:

TestClass xmlSerializableClass =
  new TestClass { MyProperty1 = "test", MyProperty2 = new AnotherClass()};
XmlSerializer serializer = new XmlSerializer(typeof(TestClass));
serializer.Serialize(Console.Out, xmlSerializableClass);


Hasta aquí bien, pero ¿qué pasa si en tiempo de compilación aún no sabemos exactamente cuantas clases heredarán de BaseClass? Podría ocurrir que tuvieramos una aplicación con plugins y que pudieran añadir más clases ahí. Para eso el XmlSerializer tiene otro constructor donde le podemos pasar una lista de tipos a añadir al serializador aparte de los que haya indicados en el atributo:

XmlSerializer serializer = new XmlSerializer(typeof(TestClass),
  new Type[]{typeof(NotIncludedClass)});


El único problema de este constructor es que no guarda la clase autogenerada en el caché. Por lo tanto, cada vez que se ejecute el código se ejecutará un csc.exe y se cargará un nuevo assembly dentro de nuestra aplicación. Eso nos produce dos efectos:

  1. Nuestra aplicación se ralentiza
  2. Como los assemblies no se descargan nunca, la memoria no se libera
En estos casos nos conviene guardar una referencia al serializador. Espero haber ayudado a alguien. Podéis descargar el código de ejemplo aquí.

Para saber más, hace ya unos cuantos años escribí un pequeño  de introducción al XmlSerializer que podéis encontrar aquí.

miércoles 3 de diciembre de 2008

The network is the...

Computer Great Deal!
Mientras los unos hablan del Cloud como la evolución natural e ineludible y los otros nos advierten de sus peligros, los más avispados se están dando cuenta de que volvemos a los inicios de la computación, cuando alquilaban los “superordenadores” por horas. El Cloud Computing no va de ubicuidad, ni va de la red, ni va de encontrar la pregunta a la respuesta 42, sino de cambiar la manera en que las grandes compañías hacen el negocio.
Igual que la moda tiene ciclos (y no sólo la de mujer... aunque lo diga Stallman) y cada 50 años vuelven los pantalones de campana, parece ser que en tecnología ocurre lo mismo (y ahí si que le doy la razón).

EC2, GoogleApi, Azure, Project Caroline, Blue Cloud, vCloud son todo tecnologías propietarias, pero yo me pregunto si habrá alguien desarrollando un Free Cloud OS por ahí, algo revolucionario de verdad.

lunes 1 de diciembre de 2008

Nota mental: desactivar el informe de problemas y soluciones

Hace unos días la herramienta de "Informes de errores y soluciones" me dió un buen susto. Mientras ejecutaba unos tests unitarios en Visual Studio el VSTestHost.exe encontró un problema y se cerró... tras el primer susto inicial (que luego os cuento) resultó que una de las clases que estaba testeando daba una StackOverflowException.

Como algunos sabréis las StackOverflowException no son capturables desde la versión 2.0 del framework. Además, para los que no lo hayáis probado sabed que ni siquiera se capturan con RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup, así que el framework de unit testing tampoco las captura, se cierra y punto.
Lo gracioso de todo esto es cómo el Windows Vista ha manejado el error del unit testing. La dichosa herramienta de solución de errores me ha dado la siguiente solución:


Informes de errores y soluciones
Este problema se debe a Visual Studio Team Edition for Software Testers. Visual Studio Team Edition for Software Testers fue creado por Visual Studio Team Edition for Software Testers.
El período de prueba para ejecutar versiones beta o preliminares de Visual Studio Team Edition for Software Testers se ha agotado, y Visual Studio Team Edition for Software Testers ya no ofrece soporte para versiones beta. Deberá realizar la actualización a la versión comercial de Visual Studio Team Edition for Software Testers.

Solución
Para obtener más información acerca de cómo realizar la actualización a la versión comercial de Visual Studio Team Edition for Software Testers, vaya al sitio web que se indica a continuación.



¿Cómo?¿Que tengo que comprar otro VS.Net para ejecutar las pruebas que venía ejecutando hasta ahora? ¿Tan malo soy programando?

Moraleja: en las máquinas de desarrollo con Vista mejor desactivar el informe... os evitaréis problemas innecesarios.

miércoles 19 de noviembre de 2008

Guía sobre Oslo, Azure & Dublin

Vía Miguel Llopis he encontrado una guía de los blogs del equipo de Connected Systems en Microsoft donde encontraréis todo lo que se ha hablado sobre estos temas. Podéis encontrar esta guía aquí.

Recordad desbloquear el CHM en las propiedades del fichero para poder verlo.