Blog de Fernando Machado Piriz

Artículos sobre transformación digital, arquitectura empresarial y temas relacionados

Archive for the ‘C# 4.0’ Category

Charlas en Facultad de Ingeniería de la Udelar: .NET Framework & C# 4.0 y Azure

with 2 comments

Hace poco tiempo Pablo García me invitó a dar unas charlas a sus alumnos de Taller de Sistemas de Información (gracias Pablo por la invitación). Una fue sobre .NET Framework y C# 4.0 y la otra sobre Windows Azure. Aquí les dejo las transparencias.

 image image

Written by fmachadopiriz

29/04/2010 at 13:50

Un poster para la pared de su box: keybindings de Visual Studio 2010

with one comment

Una de las cosas que uno encuentra luego de usar Visual Studio por mucho tiempo es que la cantidad de características o comandos es más grande que el menú, es decir, hay algunas prestaciones que no están como comandos del menú.

Déjenme darles un ejemplo. Cuando escribimos un identificador que el compilador no puede resolver, Visual Studio lo subraya con una línea ondulada en rojo:

clip_image002

Cuando movemos el puntero del mouse sobre el identificador subrayado, aparece un pequeño rectángulo azul, y al mover el puntero del mouse sobre este rectángulo, aparece un botón que al hacerle clic, presenta una serie de opciones para ayudar con la resolución del problema:

clip_image004

Esto seguramente ya lo han visto, ¿verdad?

Desafortunadamente esta característica no es accesible desde el menú. Yo no tengo problema en reconocer que a veces la falta de motricidad me impide hacer esto tan rápido como quisiera. Pero, ¿sabían que hay una combinación de teclado para hacer esto mismo sin el mouse? Sólo tienen que oprimir al mismo tiempo Ctrl+Punto.

No sólo resuelve el problema de mi falta de motricidad, sino que también evita que tenga que sacar las manos del teclado. Siempre remarco el aumento de productividad que significa ahorrar un segundo o un clic en cosas que hacemos muchas veces al día, pues al final del día son muchísimos segundos y muchísimos clics, y este es un claro ejemplo de ello.

Visual Studio tiene muchos ejemplos como el anterior, el problema es que como muchas de esas combinaciones de teclado no tienen un correspondiente comando en un menú, jamás las vemos (este problema que hasta tiene un nombre: discoverability). Microsoft ha publicado recientemente un poster donde aparecen listadas todas estas combinaciones de teclado:

clip_image005.

El archivo puede ser descargado de aquí.

En realidad hay más de un poster, uno para cada configuración de teclado asociada a un lenguaje (el lenguaje que elegimos la primera vez que usamos Visual Studio).

Descarguen el archivo, imprímanlo y péguenlo en la pared de su box. Pruébenlo y después me cuentan.

PS:  ¿Ya sabían lo de Ctrl+Punto? Okay, estoy seguro que cuando vean la lista, seguro encuentran alguno que no sabían 🙂

Written by fmachadopiriz

18/04/2010 at 08:55

Visual C# 2010 Express disponible para descarga

with one comment

A partir de hoy está disponible para descarga la versión Express de Visual C# 2010. También están disponibles las versiones Express de Visual Studio 2010, Visual Basic 2010, Visual C++ 2010, Visual Web Developer 2010. También hay una CTP (Community Technology Preview) the Visual Studio 2010 Express para Windows Phone.

Written by fmachadopiriz

16/04/2010 at 17:47

Simple Introducción al Managed Extensibility Framework

with 3 comments

Es muy común que los desarrolladores ocupemos más tiempo modificando aplicaciones existentes que construyendo aplicaciones nuevas desde cero. Nuevos requerimientos de negocio suelen precisar de nuevas funcionalidades en las aplicaciones. La forma como se agregan estas nuevas funcionalidades hoy en día termina cuando generamos, probamos y distribuimos nuevamente la aplicación. Estas actividades generalmente afectan la aplicación completa y no sólo la funcionalidad agregada.

Cuando los requerimientos cambian, los desarrolladores debemos cambiar las funcionalidades de la aplicación. Después de años de evolución, el código que implementa estas funcionalidades suelen tener dependencias indeseables y esas modificaciones pueden tonar la aplicación inestable, o requerir extensas pruebas de regresión que aseguren que no se han introducido errores. También en este caso la historia termina en generar y distribuir de nuevo toda la aplicación.

Cada vez más los negocios cambian más y más rápido, para sobrevivir en un mundo global y competitivo. Y el software que hace que esos negocios funcionen, también tiene que poder cambiar y tiene que poder cambiar rápido.

Supongamos por un instante que cada funcionalidad de la aplicación puede ser descompuesta en una “parte”. Lo que necesitamos es la capacidad de desarrollar partes débilmente acopladas, independientes no sólo en su estructura sino también en su prueba y en su distribución; y que esas partes pueden ser fácilmente compuestas en una aplicación.

Los principios de Ingeniería de software para resolver esta situación se conocen desde hace tiempo y muchas organizaciones los aplican con éxito. Pero las soluciones suelen ser caso a caso y no están disponibles al público en general como nosotros.

Recientemente han aparecido frameworks para desarrollo de aplicaciones en partes. MEF es uno de ellos.

En MEF existen los siguientes roles:

  • Partes exportadas. Declaran que pueden ser usadas para componer una aplicación y el contrato que implementan. Son unidades independientes de desarrollo, compilación y distribución. Estar débilmente acopladas, tanto como las demás partes como la aplicación que compondrán, es decir, una parte no necesariamente conoce a las demás, ni sabe necesariamente en qué aplicación será usada.
  • Puntos de importación. Variables que contienen partes o colecciones de partes importadas que deben implementar cierto contrato. Las partes son creadas automáticamente a partir de la información contenido en catálogos de partes.
  • Catálogos de partes. Contienen definiciones de partes: dónde están y qué contrato implementan.
  • Contenedores de partes. Contienen partes instanciadas y realizan la composición de las partes.

A continuación voy a mostrarles cómo desarrollar una aplicación con MEF paso a paso. Para entender MEF la aplicación debe ser simple, pero debe ofrecer varias funcionalidades que se puedan descomponer en partes.

La aplicación en este caso me permite escribir texto y luego puedo transformarlo aplicando diferentes algoritmos. Cada algoritmo ofrece una funcionalidad diferente y eso es lo que voy a transformar en partes. La aplicación luce así:

image

La lista desplegable muestra las transformaciones que puedo aplicar:

image

El objetivo es desarrollar la interfaz de usuario y cada transformación de forma independiente. Ahí vamos.

El contrato que deben implementar las partes lo declaro con una interfaz IFilter:

public interface IFilter
{
    string Filter(string input);
}

Luego creo una parte (la transformación ToUnicodeFilter) implementando esa interfaz IFilter y declarándola como exportable en MEF con el atributo Export:

[Export(typeof(IFilter))]
public class ToUnicodeFilter : IFilter
{
    public string Filter(string input)
    {
        StringBuilder output = new StringBuilder();
        foreach (char item in input)
        {
            output.AppendFormat(" U+{0:x4}", (int)item);
        }
        return output.ToString();
    }
}

La transformación en este caso es convertir cada letra del texto recibido en su correspondiente representación Unicode.

Puedo tener tantas partes como quiera, mientras también implementen la interfaz IFilter y estén decoradas con el atributo Export.

Ahora vamos a la aplicación a programar la composición de las partes en la aplicación. Necesito un catálogo que describa las partes. En este ejemplo voy a tener todos los ensamblados con las partes en una carpeta llamada Extensions, así que uso un catálogo DirectoryCatalog.

DirectoryCatalog catalog = new DirectoryCatalog("Extensions");

También necesito un contenedor para las instancias de las partes y para armar la composición. Al contenedor le paso el catálogo para que tenga la información de dónde encontrar las partes:

CompositionContainer container = new CompositionContainer(catalog);

Ya casi estamos. Lo que necesito ahora es un punto donde importar las partes. En este caso puede haber varias transformaciones, así que declaro una IList<IFilter> que decoro con el atributo Import:

[ImportMany(typeof(IFilter))]
private IList<IFilter> filters = new List<IFilter>();

Lo último que hago es componer las partes, indicándole al contenedor dónde están los puntos de importación:

container.ComposeParts(this);

Luego puedo recorrer la lista para poblar los filtros en la lista desplegable:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    foreach (IFilter filter in filters)
    {
        comboBoxFilters.Items.Add(filter.GetType());
    }
}

Cuando el usuario hace clic en el botón Apply, se busca el filtro a ejecutar en la lista de filtros a partir del elemento seleccionado en la lista desplegable:

private void buttonApply_Click(object sender, RoutedEventArgs e)
{
    if (comboBoxFilters.SelectedIndex != -1)
    {
        int index = comboBoxFilters.SelectedIndex;
        IFilter filter = filters.ElementAt(index);
        textBoxOutput.Text = filter.Filter(textBoxInput.Text);
    }
}

Tres ensamblados intervienen aquí. El primero es donde está declarado IFilter. El segundo es donde está implementada la clase ToUnicodeFilter. El tercero es el de la propia aplicación. Lo interesante aquí es que para agregar una nueva transformación o para modificar una existente, lo único que tengo que hacer es distribuir el ensamblado que la contiene en la carpeta Extensions. El resto de los ensamblados no se ven afectados, ni siquiera el de la aplicación.

¿Cómo se logra que esto funcione casi de forma máquina? Cuando invoco el método ComposeParts del contenedor pasando como parámetro la propia aplicación, el contenedor busca todas las variables decoradas con ImportMany (o con Import) en la aplicación. En cada caso aparece también la interfaz requerida por cada punto de importación.

El contenedor también conoce el catálogo, pues lo paso como parámetro en el constructor. Como el catálogo tiene la información de todas partes, incluyendo qué partes implementan qué interfaz, puede encontrar que parte o partes implementan la interfaz de cada punto de importación. Como el catálogo también conoce en qué ensamblados están las partes, puede crear instancias de las partes apropiadas y asignarlas a las variables correspondientes a los puntos de importación.

Al final, la composición “se arma sola”, el trabajo lo hace MEF y no el programador. El programador solo “decora” los tipos con Export, las variables con Import, crea uno o más catálogos y el contenedor, y finalmente compone las partes. Simple, ¿no?

Recuerden que el desafío era desarrollar partes débilmente acopladas, independientes no sólo en su estructura sino también en su distribución; y que esas partes pudieran ser fácilmente compuestas en una aplicación. ¿Objetivo cumplido? Yo creo que sí.

Pueden descargar el código de esta aplicación de aquí. El ejemplo contiene más partes todavía de las que estoy mostrando aquí.

Vean también MEF Home y MEF Overview (en inglés).

En un próximo post voy a hablar de cómo asociar metadata a las partes, por ejemplo, para que en lugar de poner el nombre del tipo en la lista desplegable, aparezca un nombre más adecuado. Nos vemos.

Written by fmachadopiriz

15/04/2010 at 10:46

La explicación fácil para entender covarianza y contravarianza

with 15 comments

Una de las novedades más importantes de C#4.0 y .NET Framework 4.0 es la introducción de covarianza y contravarianza. Varias veces he presentado covarianza y contravarianza en las charlas de novedades de C# y .NET Framework 4.0, y también en el blog, pero no siento que toda la audiencia termine entendiendo fácilmente estos conceptos. Hasta ahora he partido de las definiciones formales de covarianza y varianza, para luego mostrar cómo se implementan en C#. Probablemente no sea el mejor enfoque, así que ahora voy a intentar explicar estos conceptos de otra manera. Aquí vamos.

Vean las siguientes clases Animal y Cat que desciende de Animal:

class Animal { }
class Cat : Animal { }

Las siguientes declaraciones son correctas en cualquier versión de C#:

Cat kitty = new Cat();
Animal animal = kitty;

Todo Cat es un Animal (eso es lo que significa que Cat hereda de Animal), por lo tanto puedo asignar la variable kitty a la variable animal. Hasta ahora no hay nada nuevo.

Vean ahora lo que sucede cuando intento hacer algo análogo con enumerables de Animal y Cat:

IEnumerable<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;

Todo Cat es un Animal, por lo que intuitivamente todo enumerable de Cat es un enumerable de Animal, ¿cierto? No, falso, al menos para los compiladores anteriores a C# 4.0, que dicen que no pueden convertir IEnumerable<Cat> en IEnumerable<Animal> y me preguntan si me estará faltando un cast.

clip_image001

Puedo agregar el cast, pero es un cast inseguro. Es decir, el programa compila, pero en tiempo de ejecución veo una excepción InvalidCastException en el momento de la asignación.

Ahora bien, coincidamos que a pesar que el compilador de C# no acepte que una todo enumerable de Cat es un enumerable de Animal, intuitivamente aceptamos la afirmación, en forma análoga a la afirmación todo Cat es un Animal.

C# 4.0 resuelve el conflicto. El fragmento de código anterior compila y no genera ninguna excepción en tiempo de ejecución, tal como nuestra intuición nos indica.

¿Por qué el mismo código que compila en C# 4.0 no compila en los anteriores?

Antes de C# 4.0 la interfaz IEnumerable estaba declarada como:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Mientras que en C# 4.0 está declarada como:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Noten la palabra clave out junto al tipo parámetro T: sirve para indicar que la interfaz IEnumerable es covariante con respecto de T. En general, dado S<T>, la covarianza de S respecto de T implica que si la asignación de Y ← X es válida cuando X hereda de Y, entonces la asignación S<Y> ← S<X> también es válida.

Veamos ahora otro fragmento de código que involucra acciones (las acciones son delegados a funciones de la forma void Action<T>(T)) sobre Animal y Cat:

Action<Animal> doToAnimal =
    target => { Console.WriteLine(target.GetType()); };
Action<Cat> doToCat = doToAnimal;
doToCat(new Cat());

De nuevo, como todo Cat es un Animal, una Action<Animal> que puedo hacer con un Animal debería ser también una Action<Cat> que pueda hacer con un Cat. Vean que aunque la afirmación resulta razonable al decirla, los tipos parámetro están al revés que en el caso anterior: allá estaba asignando un enumerable definido en función de un Cat a un enumerable definido en función de un Animal, mientras que aquí estoy asignando una acción definida en función de Animal a una acción definida en función de Cat.

A pesar que la afirmación es razonable, a los compiladores anteriores a C# 4.0 no les gusta la asignación y arrojan al compilar un mensaje similar al del caso anterior: no se puede convertir una Action<Animal> en una Action<Cat>; en esta oportunidad no me pregunta si me está faltando un cast.

clip_image002

Nuevamente C# 4.0 resuelve el problema, y el código anterior sí compila. Veamos cómo están declaradas las acciones.

Antes de C# 4.0 el delegado Action estaba declarado como

public delegate void Action<T>(T obj)

Mientras que ahora en C# 4.0 está declarado así:

public delegate void Action<in T>(T obj)

Noten ahora la palabra clave in junto al tipo parámetro T: sirve para indicar que el delegado Action es contravariante con respecto de T. En general, dados S<T>, la contravarianza implica que si la asignación de Y ← X es válida cuando X hereda de Y, entonces la asignación S<X> ← S<Y> también es correcta.

En resumen, la covarianza en C# 4.0 permite que un método tenga un resultado de un tipo derivado del tipo definido como parámetro de un tipo genérico. De esta forma, permite asignaciones de tipos genéricos que siendo intuitivas, no eran posibles antes, tales como IEnumerable<Animal> IEnumerable<Cat>, cuando Cat hereda de Animal. Noten que IEnumerable sólo puede retornar instancias de T como resultado, no recibe instancias de T como parámetro. Por ello la palabra clave para declarar que IEnumerable es covariante respecto de T es out.

En forma análoga, la contravarianza permite que un método tenga argumentos de un tipo ancestro del tipo especificado como parámetro del tipo genérico. Así, permite también asignaciones que siendo razonables, no eran posibles, como por ejemplo Action<Cat>Action<Animal>. Vean que en este caso Action sólo puede recibir instancias, no las retorna. Por eso la palabra clave para declarar Action contravariante respecto de T es in.

En este artículo estoy mostrando un ejemplo de covarianza con una interfaz genérica y de contravarianza con un delegado genérico (con tipos parámetro); en un próximo artículo les mostraré otros ejemplos diferentes y les contaré que interfaces y delegados del .NET Framwork 4.0 son covariantes o contravariantes.

De aquí pueden descargar el código de ejemplo.

Para probarlo en compiladores anteriores a C# 4.0 y ver la diferencia, cambien el framework para el cual generan en las propiedades del proyecto:

clip_image003

Nos vemos en la próxima.

Written by fmachadopiriz

13/04/2010 at 08:42