martes, 14 de diciembre de 2010

Primer Coding Dojo en Barcelona

Después del fantástico AOS 2010 celebrado en Barcelona había una idea flotando en el ambiente: hay que montar más cosas!! Así que, ni cortos ni perezosos, el grupo local de Barcelona organizamos nuestro primer Coding Dojo. El evento lo realizamos en las fantásticas oficinas de Runroom con Carlos como anfitrión.

La convocatoria fue un éxito y enseguida se apuntó mucha de gente, aunque el echo diferencial fue la promesa de Gin Tonics subvencionados por Úbeda Gin & Tapas. Todo un detallazo!


La kata que seleccionamos para hacer el Coding Dojo fue la de Cesar juega a la loteria. Es una kata interesante que se puede resolver de varias maneras y que da bastante juego. Entre los 18 participantes se realizó la kata en .Net, en Java y en JavaScript. Eso si, todos con TDD.



No se exactamente por qué, pero me parece que en Barcelona hay más programador en .Net y, en cambio, en otras comunidades hay más programador en Groovy, Rails y compañía. Por lo menos en las comunidades ágiles. Curioso.

Hicimos dos iteraciones de 40 minutos. Después de la primera iteración tocaba cambio de pareja, pero quizá por ser la primera la gente no se animó y todos continuamos con nuestra primera pareja, y con nuestro segundo Gin Tonic, claro :D.



Al final de ambas iteraciones, hicimos un poco de retrospectiva de la kata. Cada uno comentó como se había encontrado haciendo TDD, como había encarado la kata, etc.Surgieron opiniones para todos los gustos: gente que no se acababa de encontrar cómoda con TDD ( para muchos era su primer vez ), gente que se encontraba muy cómoda y la kata le iba saliendo muy bien, gente que estaba refactorizando tranquilamente por el echo de tener tests por debajo, etc.

Y para acabar vimos todos el vídeo del "The downfall of Agile Hitler" para echarnos unas risas antes de continuar con las cervezas ágiles mientras cuatro afortunados nos preparábamos para ir a la mañana siguiente al coderetreat de Zaragoza. Pero eso ya es otro post...

lunes, 1 de noviembre de 2010

VAN sobre integración contínua

Muy buenas a todos,

el pasado viernes tube el placer de participar en la VAN sobre integración contínua que organizó Altnet hispano. La VAN estubo muy interesante, tanto por la explicación general como por las demostraciones de las diferentes herramientas que se hicieron.

Aquí os dejo el video de la VAN.


Unable to display content. Adobe Flash is required.

viernes, 19 de marzo de 2010

Haciendo realidad la agilidad


Ya tenemos a la vuelta de la esquina la primera conferencia sobre métodos ágiles en España. Tendrá lugar el 10 y 11 de Junio en el Campus de la E.U. Informática de la U.P.M en Madrid. Podéis obtener toda la información que necesitéis en la web de la conferencia.


No seáis tímidos y proponed cosas! Podéis proponer sesiones, contribuciones y talleres. Vendrá Henrik Kniberg como orador, así no que no os podéis perder la oportunidad de compartir cartel con el.


Y por supuesto, si queréis patrocinar la conferencia lo podéis hacer.


Nos vemos el 10 de junio en Madrid!

viernes, 26 de febrero de 2010

Integración continua con Hudson

Espero que a estas alturas de la película ya estemos todos convencidos de la necesidad de tener un mecanismo de integración continua en nuestro sistema de desarrollo. Hay un montón de herramientas que nos pueden ayudar como Team Foundation ServerCruise Control o, el que empezaremos a ver hoy, Hudson.

Hoy empezaremos a ver como configurar Hudson para tener una tarea que se descargue un proyecto de Subversion, lo compile y pase los tests. Obviaremos la instalación tanto de Subversion como de Hudson por ser muy sencilla y poderse encontrar en muchos sitios.

Lo primero que tenemos que hacer una vez instalado Hudson tenemos que instalar los plugins que vamos a necesitar. En nuestro caso estos son: Hudson Subversion Plugin, Hudson MSBuild Plugin, Hudson MSTest Plugin y el imprescindible Chuck Norris Plugin :-). Para instalarlos tenemos que ir al menú Gestionar Hudson -> Gestionar Plugins, seleccionarlos de la pestaña Todos los plugins, seleccionar dichos plugins y clicar sobre el botón instalar.


Ahora vamos a configurar un poco Hudson antes de ponernos con las tareas. Nos vamos al menú de Gestionar Hudson -> Configurar Sistema y cambiamos la ruta del directorio raiz si lo consideramos conveniente.

También le tenemos que configurar la ruta del MSBuild para poder llamarlo en nuestra tarea

Y finalmente le vamos a configurar el servidor de correo a utilizar. Tenemos que configurar la dirección del administrador, la dirección del servidor de Hudson para que funcionen los links que se nos envian, el sufijo por defecto si queremos que se extraigan las direcciones de correo de los usuarios de subversion y la configuración de nuestro servidor de correo saliente, en nuestro caso gmail.

Ahora ya podemos empezar a configurar la tarea. Para ello hacemos click sobre el link Nueva Tarea y nos aparecerá una ventana con varias opciones. En nuestro caso escogemos "Crear un proyecto de estilo libre".
Lo primero es configurar es configurar un par de cosas básicas como la descripción de la tarea y el directorio personalizado del proyecto en caso de no querer el directorio por defecto de Hudson.

A continuación configuraremos el repositorio de subversion al que nos queremos conectar y la periodización de dicha conexión. En este caso nos conectaremos al repositorio para bajarnos el código a los cinco minutos de cada hora.


Ahora vamos a añadir un par de tareas para realizar tareas especificas de .Net. En este caso será realizar una compilación con MSBuild y lanzar los tests con MSTest. Para la tarea de MSBuild añadiremos la tarea llamada "Build a Visual Studio project or solution using MSBuild", escogemos la versión de MSBuild adecuada para nuestro proyecto, la solución a compilar y los parámetros de dicha compilación.

Seguidamente añadiremos un nuevo paso del tipo "ejecutar línea de comandos (shell)" para ejecutar los tests. Tenemos que introducir manualmente el comando para ejecutar MSTest desde línea de comandos generando un archivo .trx con los resultados de los tests para que Hudson los pueda interpretar.

Finalmente sólo nos falta configurar las opciones que nos interesen de las que ofrece Hudson al final de la página de configuración. En nuestro caso será necesario activar la opción "Publish MSTest result report" (especificando el archivo .trx que hemos generado anteriormente), "Notificación por correo" y, claro está, "Activate Chuck Norris" :-). Ahora ya podemos clicar sobre el link "Construir ahora". En caso que algún paso no esté bien configurado o el programa dé algún error, se nos enviará un mail con el error y en la página web de Hudson nos aparecerá la tarea al lado de un circulo rojo indicando que hay algún error. Si todo está bien, el circulo será azul y sólo se nos enviará un mail en caso que anteriormente hubiera habido una ejecución incorrecta, informándonos así que la build vuelve a estar bien.

Espero que con este tutorial podáis empezar a trabajar con Hudson. Es un gran programa con un montón de opciones que iremos comentando a medida que nos parezcan interesantes.

sábado, 30 de enero de 2010

Programación asíncrona

Hoy vamos a hacer un post un poco más técnico, que ya hace tiempo que no hacemos ninguno. Vamos a hablar, en la línea de este otro post, de la programación asíncrona.

Quién no se ha encontrado alguna vez con la necesidad de hacer una tarea que consume mucho tiempo ( acceso a ficheros, cálculos complejos, acceso a la red, etc ) y no quiere que su interfície de usuario se vea afectado por ello? No veo ninguna mano alzada, así que supondremos que es algo recurrente.

Este tipo de programación se ha llevado a cabo históricamente mediante hilos. Aunque .Net ha facilitado mucho la programación con ellos, hacer un uso de los mismos no deja de ser añadir complejidad al programa y es una fuente típica de errores. Es por esto que existen otras alternativas a la programación asíncrona sin tener que utilizar explícitamente hilos. Estas alternativas son las siguientes:
  • Llamadas asíncronas a delegados.
  • Llamadas asíncronas utilizando la interfaz IAsyncResult.
  • El componente BackgroundWorker.
  • Llamadas asíncronas basadas en eventos.
En este artículo nos centraremos en esta última aproximación ya que es la más completa y la más recomendada.

Este patrón se apoya en la utilización de dos clases de ayuda proporcionadas por .Net: la clase AsyncOperationManager que utilizaremos para crear instancias de la otra clase de ayuda, la AsyncOperation que utilizaremos para efectuar el seguimiento del progreso de la tarea asíncrona e informar del mismo. Una de las ventajas que tiene es que los eventos de progreso y cancelación se hace en el hilo adecuado, con lo que podemos actualizar la interfíce de usuario directamente, sin tener que recurrir a Invoke.

Vamos a ver paso a paso como crear una clase que implemente este patrón y como crear una clase cliente que la instancie y utilice.

Lo primero que tenemos que hacer es, obviamente, crear nuestra clase que queremos que se pueda llamar de manera asíncrona. En nuestro caso creamos una clase llamada LazyClass.

Seguidamente vamos a declarar los delegados y los eventos públicos que necesitamos para informar al cliente del progreso y terminación de la tarea asíncrona.


public delegate void LazyTaskProgressChangedEventHandler(LazyTaskProgressChangedEventArgs pArgs);
public delegate void LazyTaskCompletedEventHandler(object pSender, LazyTaskCompletedEventArgs pArgs);

Esto nos obliga a definir los argumentos LazyTaskCompletedEventArgs y LazyTaskProgressChangedEventArgs.

La clase LazyTaskCompletedEventArgs tendrá la definición de las cosas que queremos que se informen al exterior cuando se haya terminado la tarea asíncrona. Esta clase puede ser tan compleja como queramos, aunque nosotros, por el bien del entendimiento del ejemplo, la hemos reducido lo máximo posible.

public class LazyTaskCompletedEventArgs : AsyncCompletedEventArgs
{
    private int m_iNumIterations = int.MinValue;
    private int m_iTotalTime = int.MinValue;

    ///
    /// Constructor
    ///
    public LazyTaskCompletedEventArgs(int pNumIterations, int pTotalTime, Exception pException, bool pCancelled, object pState) : base (pException, pCancelled, pState )
    {
        m_iNumIterations = pNumIterations;
        m_iTotalTime = pTotalTime;
    }

    ///
    /// Número de iteraciones
    ///
    public int NumIterations
    {
       get
       {
           RaiseExceptionIfNecessary();
           return m_iNumIterations;
       }
    }

    ///
    /// Tiempo transcurrido
    ///
    public int TotalTime
    {
        get
        {
            RaiseExceptionIfNecessary();
            return m_iTotalTime;
         }
    }
}

Como se puede ver, en cada una de las propiedades antes de devolver el valor se llama a una función ( del espacio de nombres System.ComponentModel ) llamada RaiseExceptionIfNecessary. Esta función se utiliza para evitar que alguien acceda a los valores de la clase si se ha producido algún error o se ha cancelado la invocación asíncrona. En tal caso, al acceder a cualquiera de las propiedades de la clase recibiremos una excepción del tipo InvalidOperationException.

La clase LazyTaskProgressChangedEventArgs derivará de la clase ProgressChangedEventArgs del espacio de nombres System.ComponentModel. En nuestro caso no le añadimos nada ( con el porcentaje tenemos suficiente ) pero se le podría añadir todo lo necesario para nuestra tarea en concreto.





///
/// Classe que define los argumentos del progreso de la tarea
///
public class LazyTaskProgressChangedEventArgs : ProgressChangedEventArgs
{
    public LazyTaskProgressChangedEventArgs(int pPercentatge, object pState)
: base(pPercentatge, pState)
    {
    }
}

Lo siguiente es implementar los delegados privados que utilizaremos como puente para informar al cliente del progreso de la tarea. Estos delegados tendrán una firma del tipo SendOrPostCallback, definida también en el espacio de nombres System.ComponentModel.

private SendOrPostCallback onProgressDelegate;
private SendOrPostCallback onCompletedDelegate;

Y los inicializamos en el constructor de la clase:

onProgressDelegate = new SendOrPostCallback(LazyTaskProgress);
onCompletedDelegate = new SendOrPostCallback(LazyTaskCompleted);

A continuación vamos a declarar el delegado encargado de realizar el trabajo que queramos hacer en nuestra clase. Este delegado tendrá que recibir un parámetro del tipo AsyncOperation que se utilizará para hacer el seguimiento del progreso de la tarea asíncrona y un delegado de tipo SendOrPostCallback que se utilizará para notificar del fin de la operación. También puede recibir cualquier otro parámetro que necesitemos para la ejecución de la tarea.

private delegate void WorkerEventHandler ( AsyncOperation pOperation, SendOrPostCallback pCompletionMethod );

Después declararemos una colección para administrar las diferentes operaciones asíncronas que se produzcan en nuestra clase. Podemos utilizar un Dictionary, un HibrydDictionary o lo que más nos convenga.

ListDictionary m_ldTasks = new ListDictionary();

A continuación pasamos a implementar los eventos públicos que utilizaremos para informar al cliente del progreso y terminación de la tarea asíncrona.

///
/// Implementación del delegado del progreso
///
private void LazyTaskProgress(object pSate)
{
    ProgressChangedEventArgs e = pSate as LazyTaskProgressChangedEventArgs;
    FireOnLazyTaskProgressChanged(e);
}

///
/// Implementación del delegado de tarea completada
///
private void LazyTaskCompleted(object pSate)
{
    LazyTaskCompletedEventArgs args = pSate as LazyTaskCompletedEventArgs;
    FireOnLazyTaskCompleted(args);
}

///
/// Lanza el evento de tarea completada
///
private void FireOnLazyTaskCompleted(LazyTaskCompletedEventArgs pArgs)
{
    if (OnLazyTaskCompleted != null)
    {
        OnLazyTaskCompleted(this, pArgs);
    }
}

///
/// Lanza el evento de progreso en la tarea
///
private void FireOnLazyTaskProgressChanged(LazyTaskProgressChangedEventArgs e)
{
    if (OnLazyTaskProgressChanged != null)
    {
        OnLazyTaskProgressChanged(e);
    }
}

Y para acabar con la implementación de delegados tan sólo nos falta implementar el delegado de finalización de la tarea. Este delegado se llamará  cuando se haya terminado la ejecución de nuestra tarea. En este método es donde se elimina el identificador de la tarea de la colección y donde se da por terminada la tarea asíncrona llamando al método PostOperationCompleted. Una vez llamado este método, cualquier intento de utilización de la AsyncOperation a la que se refiere nos dará una excepción.


/// Método que se llamará cuando la ejecución de la tarea de forma asíncrona haya acabado
///
private void LazyTaskCompletionMethod(object pLazyTaskState)
{
    LazyTaskState taskState = pLazyTaskState as LazyTaskState;

    AsyncOperation operation = taskState.Operation;
    int iNumIterations = taskState.NumIterations;
    int iTotalTime = taskState.TotalTime;
    bool bCancelled = false;
    Exception eException = taskState.TaskException;

    LazyTaskCompletedEventArgs args = new LazyTaskCompletedEventArgs(iNumIterations, iTotalTime, eException, bCancelled, operation.UserSuppliedState);

    lock (m_ldTasks.SyncRoot)
    {
        if (m_ldTasks.Contains(operation.UserSuppliedState))
        {
            m_ldTasks.Remove(operation.UserSuppliedState);
        }
    }
    operation.PostOperationCompleted(onCompletedDelegate, args);
}


Ahora ya podemos pasar a implementar la función que hará el trabajo real de nuestra clase. En nuestro caso será algo tan trivial como un for con un sleep dentro para simular una tarea pesada.

///
/// Realiza la operación que queremos
///
private void DoTask(AsyncOperation pOperation, SendOrPostCallback pCompletionMethod)
{
    Exception ex = null;

    try
    {
        for (int i = 0; i < 100; i++)
        {
            if (!TaskCanceled(pOperation.UserSuppliedState))
            {
                System.Threading.Thread.Sleep(100);
                LazyTaskProgressChangedEventArgs pChangedEventArgs = new LazyTaskProgressChangedEventArgs(i + 1, pOperation.UserSuppliedState);
                pOperation.Post(this.onProgressDelegate, pChangedEventArgs);
            }
        }
    }
    catch ( Exception e )
    {
        ex = e;
    }

    if (!TaskCanceled(pOperation.UserSuppliedState))
    {
        LazyTaskState state = new LazyTaskState(100, 10000, pOperation, ex);
pCompletionMethod(state);
    }
}

En este código podemos ver tres cosas. La primera es que nos apoyamos en una función llamada TaskCancelled. Esta función, que la debemos implementar nosotros, simplemente mira en la colección si está el identificador de tarea que le pasamos como parámetro. Por otra parte podemos ver que cada vez que queremos informar de un cambio en el progreso de la tarea llamamos a la función Post de la AsyncOperation que recibimos como parámetro. Y finalmente vemos que cuando acabamos la realización de la tarea llamamos al delegado del completionMethod.

Y ya nos vamos acercando al final. Ahora tan sólo nos queda implementar los métodos para iniciar y cancelar el trabajo. En el método para iniciar la tarea nos tendremos que asegurar que el identificador de tarea que nos pasan cómo parámetro es único mirando si está en la colección. En el método para cancelar, tan sólo tendremos que quitar la tarea de la colección. El framework hará el resto.

///
/// Realiza la tarea asíncronamente
///
public virtual void DoLazyTaskAsync(object pTaskID)
{
    AsyncOperation operation = AsyncOperationManager.CreateOperation(pTaskID);

    lock (m_ldTasks.SyncRoot)
    {
        if (m_ldTasks.Contains(pTaskID))
        {
            throw new ArgumentException("Ya existe una tarea con este identificador", "taskID");
        }
        m_ldTasks[pTaskID] = operation;
    }

    doTaskDelegate = new WorkerEventHandler(DoTask);
    doTaskDelegate.BeginInvoke(operation, completionMethodDelgate, null, null);
}

///
/// Cancela la ejecución de una tarea asíncrona
///
public void CancelLazyTaskAsync(object pTaskId)
{
    lock (m_ldTasks.SyncRoot)
    {
        if ( m_ldTasks.Contains(pTaskId ) )
        {
            AsyncOperation operation = (AsyncOperation)m_ldTasks[pTaskId];
            if (operation != null)
            {
                 m_ldTasks.Remove(pTaskId);
            } 
        }
    }
}

Ya tenemos nuestra clase con una llamada a un método asíncrono preparada para ser utilizada por un cliente. Para completar su funcionalidad deberíamos tener también un método para que podamos llamarla de forma síncrona por si nos interesa.

La implementación del cliente es muy sencilla. Simplemente nos tenemos que subscribir a los eventos de progreso y finalización y llamar a los métodos de inicio y cancelación cuando nos interese. Podéis ver el código completo en el adjunto.

Espero que este pequeño ejemplo os haya servido de ayuda. Podéis descargaros el ejemplo de aquí.

domingo, 17 de enero de 2010

Programación en pareja

Esta es más o menos la cara que se le queda a un gestor de proyectos tradicional cuando le comentas que quieres implantar que el equipo trabaje en parejas. Sin embargo es una de las mejores decisiones que hemos tomado para mejorar la calidad de nuestro código. Que ventajas le vemos? Pues las siguientes serian las principales:
  • Calidad del análisis previo: no sólo programamos en pareja, sino que también hacemos el análisis técnico de la solución en pareja. Esto hace que el diseño sea mucho mejor ya que el error que uno sólo no detectaría, con la ayuda del otro si que lo hace.
  • Calidad del código: el código que sale de la programación en parejas es de mucha más calidad que el hecho por uno sólo. La idea que no tiene uno, la tiene el otro. El comentario que a uno le da pereza añadir, el otro se lo recuerda. El test que uno no cree necesario hacer, el otro le obliga a hacerlo. Y así una larga lista.
  • Concentración: si uno trabaja sólo y tiene ciertos problemas de concentración es posible que no dedique todo el tiempo que seria deseable a programar. Messenger, mail, charlas con el compañero son pequeñas cosas que, si no se gestionan correctamente, pueden hacer perder mucho tiempo a un programador. Trabajando en pareja esto se minimiza muchísimo. Nadie se atreve a charlar por el messenger si está con el compañero trabajando. El focus se aumenta muchísimo.
  • Aprendizaje: siempre se aprenden cosas de los compañeros, a no ser que haya demasiada diferencia entre las capacidades de ambos, con lo cual sólo aprendería uno. Pero si la pareja está bien montada ambos aprenden el uno del otro.
  • Propiedad colectiva del código: al ir cambiando de pareja y de tarea el conocimiento de las características del código va fluyendo entre los integrantes del equipo, haciendo mucho más fácil que alguien se incorpore al equipo.
  • Ánimo del equipo: en general a la gente le gusta más trabajar en equipo que no sólo y el hacerlo le anima a seguir trabajando y cohesiona al grupo.
Así que espero que a partir de ahora os animéis a probar la programación en pareja!