Cacheitis: Lo mínimo que todo desarrollador debe saber sobre las cachés

Creo que, después de tanto artículo sobre Scrum, los lectores de mi blog agradecerán una entrada que no tenga nada que ver con las metodologías ágiles. Sí, sí, yo también estoy un poco saturado del tema, pero de todos modos, no dudéis que vamos a seguir hablando de ello en este blog. Pero antes de meterme en harina, permitidme que os presente www.scrumweek.com, una semana enterita de formación sobre metodologías ágiles.

Pero como decía hoy no vamos a hablar de metodologías, sino de arquitectura y diseño de software. De hecho vamos a hablar de uno de los elementos claves de toda arquitectura: la caché.

Seguro que ninguno de los lectores ignora los beneficios que una caché bien diseñada proporciona a casi cualquier aplicación. Se puede asegurar que sea cual sea el dominio de nuestra aplicación el rendimiento de la misma se verá beneficiado por el principio general de almacenar datos en lugares donde su acceso sea más rápido (memoria frente a disco, memoria frente a base de datos, capas más cercanas de la aplicación frente a capas más lejanas…).

Este principio general se cumple casi siempre, pero no es el motivo de este post hablar de los ya conocidos efectos beneficiosos del cacheo, sino de los usos aberrantes que a menudo he visto de la cache. Y es que, si bien una cache bien utilizada es un catalizar claro del buen rendimiento, una mal uso de la cache es más a menudo de lo que muchos desarrolladores sospechan fuente de serios problemas de rendimiento. Es la tan temida cacheitis. La cacheitis es una enfermedad que sufren muchísimas aplicaciones, consiste en hacer una mal uso de la cache que provoca una dolorosa inflamación de la misma que la hace totalmente inservible. La cacheitis se manifiestas con muchos síntomas diferentes siendo los más significativos un altísimo consumo de memoria y un mal rendimiento de la aplicación.

La cacheitis tiene sus orígenes en diversos malos usos de la caché casi siempre relacionados con olvidar alguna de las siguiente buenas prácticas:

Asume que no puedes cachearlo todo: Como arquitecto, cuando te enfrentas a la difícil decisión de diseñar tu modelo de caché debes tener en cuenta que no puedes cachear todo. La cache por definición es finita. Si puedes contar con una caché infinita, simplemente no necesitas una caché. El lugar en el que suelen acabar todo los datos es la memoria, si todos los datos que va a manejar tu aplicación caben en memoria por definición y tienes la seguridad de que esto siempre va a ser así, simplemente almacénalos directamente en memoria (ignoro aquí la necesidad de persistencia). Por ejemplo supongamos una aplicación que utiliza una tablas de cálculo, cargar directamente esas tablas en memoria puede ser una opción interesante. De todos modos, hemos de reconocer, que a menudo las aplicaciones no puede asumir está premisa. En ese caso es una labor sumamente difícil decidir cual es el balance justo entre consumo de memoria y uso de recursos más lentos como acceso a disco y petición de datos por la red, pero ese no es le punto ahora. El punto ahora es que la memoria es finita y además un recurso compartido y por tanto tu cache tiene que estar explícitamente limitada. Diseñar si tener en cuenta que la cache es finita y cachearlo todo es un error de base, una cache que cachea todo nunca va a ser efectiva. Una frase que en el Debugging and Optmization Team de Plain Concepts hemos oído a menudo es: ‘Cómo puede ser lenta la aplicación si lo cacheamos todo’… cachear todo es dañino por que la cache es finita. Si en una cache finita, cacheas todo el resultado será que algo tendrá que salir de la caché para que entre lo último que has cacheado y que tu cache por lo tanto siempre contendrá lo último cacheado, pero no lo que más importante sea cachear. La cache debe almacenar lo recursos costosos que se acceden con más frecuencia, no los últimos accedidos.

El cacheo temprano es el origen de todos los males: Parafraseando la mítica frase de Donald Knuth , ‘la optimización temprana es el origen de todos los males’, tomar decisiones de cacheo demasiado temprano es dañino en la mayoría de las ocasiones. A menudo cuando diseñamos una arquitectura establecemos mecanismos de cacheo que luego son utilizados hasta el abuso. El peligro subyacente al cacheo temprano es que comencemos a cachear sistemáticamente elementos que nos parecen costosos sin tener evidencia de que realmente son los mejores candidatos para su cacheo. Por ejemplo, llegamos a una historia de usuario que requiere cargar datos de provincias y como suponemos que van a cambiar poco decidimos cachearlos ignorando que el factor más importante a la hora de cachear es el coste de obtener la información multiplicado por el número de accesos que esa información va a ser accedida. Cachear toda la información que cambia poco simplemente por que es fácil de cachear es un error habitual. Además los patrones de acceso a la información en aplicaciones complejas son difícilmente predecibles, es muy difícil sin analizar el rendimiento de tu aplicación mediante unas adecuadas pruebas de carga que modelen el uso que va a tener, tomar las decisiones correctas sobre que cachear. Diseña para hacer el cacheo posible, pero no decidas que cachear hasta que no te quede más remedio.

No solo existe una caché: Otro error habitual es olvidar que no solo existe una cache en el sistema. El gestor de bases de datos que utilizamos implementa mecanismos de cache, el servidor web que utilizamos implementa mecanismos de cache, nuestra aplicación implementa mecanismos de caché… ¡y todos usan la memoria!. Hace un tiempo nos llamaron para ver que estaba ocurriendo en una aplicación que hacia un buen uso de la caché, de hecho el comportamiento de la aplicación era adecuado la gran mayoría de las ocasiones… excepto cuando el ‘servidor’ tenía menos de dos bigas de memoria situación en la que todo se volvía escandalosamente lento. Lo más sorprendente es que en la última versión de la aplicación habían añadido una caché que mejoraba mucho el rendimiento en la mayoría de los casos. Sin embargo la versión anterior sin caché se comportaba aceptablemente en servidores con poca memoria. Tras estudiar el comportamiento de la aplicación, sorprendentemente, en situaciones con poca memoria, elementos costosos que habitualmente debían estar en la caché sistemáticamente tenían que ser recuperados desde la base de datos. Y lo que es peor, cuando observábamos el comportamiento de la base de datos ¡también veíamos tiempos de respuesta muy elevados!. Tras tirar del hilo nos dimos cuenta de lo que estaba ocurriendo: SQL Server y ASP.Net/IIS se estaban pegando por la memoria para colocar sus respectivas cachés. Vaya, nos habíamos olvidado de que ¡la memoria es finita!. La solución, sencilla, limitar la memoria máxima a utilizar por parte de SQL Server y de ASP.Net y listo… problema solucionado.

Una colección estática o global no es una caché: Aunque parezca sorprendente, no es extraño encontrar desarrolladores que implementa su propio sistema de caché. Esto siempre es una aberración. Hoy por hoy todas las tecnologías que podemos usar en una arquitectura .Net en las que el cacheo puede jugar un papel tiene un mecanismo de caché. ¡He visto cachés implementadas como colecciones estáticas! Una mecanismo de caché que no cuenta con un mecanismo de invalidación no es un mecanismo de caché. Tan importante es mantener en caché los elementos que se acceden con más frecuencia como liberar la memoria utilizada por aquellos elementos en cache que no son accedidos. Igualmente es importante, siempre que se decide cachear un elemento establecer la política de invalidación de dicho elemento.

La cacheítis, como cualquier enfermedad tiene síntomas que nos pueden poner sobre su pista. Casi todos estos síntomas se manifiestan con contadores de rendimiento fuera de control. El el Performance Monitor (Perfmon.exe) el termómetro que nos indicará que podemos estar sufriendo de cacheitis. Hay un parámetro que todo mecanismo de caché suele publicar en sus contadores rendimiento y que es fundamental a la hora de diagnosticar una cacheítis:

Cache Hit Ratio:

Cuando el cliente de un sistema de caché pide el acceso a un dato que es susceptible de encontrarse en la caché y lo encuentra se produce un ‘hit’ de la cache. La relación entre las veces que se hacen peticiones a la cache y las veces que el dato buscado en la caché se encuentra en esta es el Cache Hit Ratio. Un porcentaje bajo en este indicador es un síntoma claro de un mal uso de la caché. Se suele considerar un valor adecuado un ratio de alrededor del 90%.

En la siguiente imagen se pueden ver diferentes contadores de rendimiento de componentes típicos de una aplicación .net:

image

¡Ojo con la cacheitis!

¡ScrumWeek y el primer curso de certificación Professional Scrum Developer en España!

Scrumweek2011_r2_c1

En el marco de la primera edición de la ScrumWeek organizada por Plain Concepts y Proyectalis, desde Plain Concepts hemos preparado el primer curso de certificación Professiona Scrum Developer en España. Pero no solo podrás aprender y certificarte sobre Scrum y TFS a fondo, además hay formación sobre: Pruebas unitarias, Arquitectura ágil, Coaching de equipos ágiles, Scrum (de manera agnóstica a la tecnología) y sesiones gratuitas.

Regístrate ahora con un descuento del 50% sobre el valor del curso.

El programa Professional Scrum Developer .NET (PSD.NET) capacita, evalúa y certifica a los desarrolladores de Scrum que trabajan en tecnologías .NET. Durante Scrumweek se llevará a cabo un curso PSD.NET durante el cual se mostrará cómo utilizar prácticas de ingeniería de software modernas para desarrollar un incremento de funcionalidad potencialmente entregable, en el marco de Scrum, Visual Studio y Team Foundation Server 2010, y trabajando como parte de un equipo autoorganizado y multifuncional que practica un desarrollo iterativo e incremental. Las clases son guiadas por ejercicios prácticos, en los que los estudiantes trabajan en equipo para desarrollar incrementos completados de elementos del Backlog de producto.

Lugar y fecha

La ScrumWeek Madrid 2011 tendrá lugar del 4 al 8 de Abril (lugar pendiente de determinar).

PROGRAMA

El programa de esta semana Ágil incluye:

Cursos

  • Curso de Scrum (iniciación a intermedio), por Rodrigo Corral y José Luis Soria (lunes-martes, 9 a 18)
  • Coaching de equipos Ágiles, por Ángel Medinilla (lunes-miércoles, 9 a 15)
  • Arquitectura Ágil, por Unai Zorrilla (miércoles-jueves, 9 a 15)

Seminarios y talleres en profundidad

  • Gerencia Ágil, por Ángel Medinilla (jueves, 9 a 18)
  • Taller de pruebas unitarias, por Ibón Landa (viernes, 9 a 15)

Sesiones divulgativas gratuitas

  • Visual Studio Ágil, por Ibón Landa (jueves-viernes, 16 a 18)
  • Cultura Corporativa Ágil (lunes-martes, de 16 a 18)

Scrum Clinic

Por Ángel Medinilla y Rodrigo Corral (viernes, 9 a 15)

Curso oficial Professional Scrum Developer .NET

Por Rodrigo Corral y José Luis Soria (lunes-viernes, día completo)

Adicionalmente, el programa incluirá la celebración de una serie de sesiones divulgativas, talleres, coloquios, reuniones de grupos locales y networking, además de un Coding Dojo, las tardes de lunes a miércoles, así como un barcamp-cena el jueves. Permaneced atentos a esta página y a nuestras noticias para más información.

Scrumweek2011_r6_c2

Gestión de proyectos guiada por la intuición, o por qué gestionar proyectos es tan difícil

Tras unos cuantos años participando en la gestión de proyectos de desarrollo de software y ayudando a diversas organizaciones a mejorar como gestionan sus proyectos, he llegado a una conclusión muy curiosa: gestionar proyectos de software es una actividad extremadamente difícil. Continuamente veo aberraciones, errores abismales, errores que llevan descritos décadas en los libros sobre gestión de proyectos, errores que todos los que participamos en la gestión de proyectos cometemos muy a menudo. Observando estos errores, buscando su causa última, lo que nos lleva caer una y otra vez en el mismo error he llegado a una conclusión: la intuición no sirve para gestionar proyectos. La intuición de proyectos esta llena de ideas contra intuitivas, de anti patrones, de soluciones que parecen atractivas y simples y que no funcionan. Un buen gestor de proyectos tiene que luchar continuamente contra su intuición. Solo los conocimientos, las convicciones firmes en principios y fundamentos universales de la gestión de proyectos nos sirve. Y evidentemente la voluntad de defender esos principios, muchos de ellos, insisto, contra intuitivos contra la gente que trata de meter su nariz en la gestión de nuestros proyectos basándose en su intuición, en el siempre se ha hecho así, o en el aquí mando yo…

La lista de trampas que nos encontramos en la gestión de proyectos es inmensa, no me ha costado más de quince minutos pensar en una serie de ejemplos. Esta lista de cosas que parecen funcionar y no lo hacen no pretende ser completa o exhaustiva, simplemente pretende soportar mi tesis de que la gestión de proyectos está llena de trampas, que disfrazadas como soluciones interesantes o verdades absolutas, a menudo se rebelan como errores. Errores que se repiten con demasiada frecuencia. Esta es la gran dificultad de la gestión de proyectos: tener los conocimientos suficientes, el arsenal de respuestas preparado para que cuando algún gestor de proyectos de postal, uno de los miembros de nuestro equipo, un consultor externo u otro que viene con una genial idea, plantea de nuevo una de estas soluciones que llevan una trampa dentro, podamos contrarrestarla con contundencia, con datos y demostraciones que dejen claro que lo que es intuitivo no siempre funciona en lo que se refiere a la gestión de proyectos.

El modelo en cascada. No hay nada más intuitivo que el modelo en cascada, es fácil de explicar, fácil de entender, fácil de implementar, describe perfectamente las actividades claves del desarrollo de software… solo tiene un problema, no funciona.  Aun así es una trampa golosa en la que miles de proyectos mueren atrapados cual moscas ignorantes del peligro. Nunca falta quien defiende este modelo, y es normal, la intuición no dice que si dedicamos suficiente esfuerzo al principio del proyecto para eliminar la incertidumbre todo fluirá después por nuestra cascada de manera limpia y ordenada. Con suficiente planificación y diseño todo fluirá. Pero hay un motivo por el que este modelo nunca a funcionado y nunca va a funcionar: Siempre hay incertidumbre, nunca vas a se capaz de eliminarla toda y en el momento en que esa incertidumbre aparezca por pequeña que sea, el modelo en cascada mostrará sus flaquezas de manera irreversible: la retroalimentación es casi imposible. ¿Que pasa si en tu fase de test descubres que tu arquitectura no da el rendimiento adecuado?. Pues te pasará lo que ha un salmón que remonta una cascada: morirás exhausto sin remedio. Steve McConnell tiene una ilustración en su libro Rapid Application Development que yo procuro traer a mi cabeza cada vez que la tentación de acercarme a un modelo en cascada me ronda la cabeza:

image

Las estimaciones son certezas. Convertir las estimaciones en compromisos o certezas es otra de esas trampas que nos hacemos a nosotros mismos cada poco. Bien cuando damos estimaciones, bien cuando las recibimos. Pensar que somos capaces de estimar con el grado de certeza suficiente, olvidar el cono de incertidumbre es otra de esas trampas habituales. Es imposible acertar sistemáticamente en tus estimaciones, no por que yo lo diga, sino por que así lo demuestra el cono de incertidumbre.

El cono de incertidumbre nos dice, que en el momento en que habitualmente estimamos un proyecto o una tarea, al principio del mismo, es altísimamente probable que nos desviemos. Boehm intuyo esta realidad en 1981 y formuló el cono de incertidumbre que luego fue validado por el Laboratorio de Ingeniería del Software de la NASA. La próxima vez que alguien quiera ignorar el difícil problema de la estimación y convertir tus estimaciones en adivinaciones, dale con el cono en los morros… y dale fuerte.

Estimar con búferes. Como todos nos hemos visto atrapados por las dificultades de la estimación en un momento u otro y todos hemos sido flagelados por no cumplir nuestras estimaciones en alguna ocasión (pese a que el cono de incertidumbre demuestra que lo normal es no acertar), todos hemos sido victimas alguna vez de otra de esas ideas, que si bien la intuición nos dice que son correctas, la realidad y la ciencia han demostrado como erróneas: estimar con búferes. La intuición nos dice que si añadimos búferes a nuestras estimaciones, nuestro grado de cumplimiento de las mismas mejorará. La tozuda realidad, que a menudo es más compleja de lo que nuestra intuición asume demuestra que esto no es así. Y lo demuestra en forma de ley, la Ley de Parkinson: el trabajo se expande para consumir el tiempo disponible para realizar una tarea. Da igual el búfer que añadas, las tareas laterales, las tareas de investigación, las tareas divertidas, el ruido, todo esto conspirará en tu contra para que consumas el búfer. Además la naturaleza humana nos hará ‘posponer el inicio de la tarea hasta que no quede más remedio que iniciarla’ o lo que es lo mismo ¡primero consumiremos el búfer!. ¿Recordáis vuestros días de estudiantes? Sabías la fechas de los exámenes con meses de antelación… y si la noche anterior estabais estudiando.

Podemos sacrificar calidad para ahorrar coste o recortar plazos. Esta es otra de esas trampas mentales que nos hacemos a menudo. Nos decimos: rebajemos la calidad del software que hacemos, así cumpliremos plazos o reduciremos costes. Parece intuitivo ¿no? Al fin y al cabo todos tenemos en nuestro barrio una tienda de Chinos que demuestra esto, podemos hacer productos de menos calidad más baratos y venderlos como churros. Olvidamos con facilidad o incluso muchos desconocen que en el software también existen costes asociados a la ‘no calidad’ y que son nuestros clientes no nosotros quienes finalmente marcan el nivel de calidad exigido. ¿Habéis intentando mantener o extender software de baja calidad?  ¿Habéis conseguido que un cliente acepte un software que no cumple sus expectativas de calidad? Y es que en el software la calidad no es opcional. Fijaros en el siguiente gráfico que podéis encontrar en la página 69 del ya mencionado Rapid Application Development:

image

En 1991 varios estudios desvelaron que los proyectos que tienen una tasa de defectos más baja son los que logran unos plazos de entrega más cortos. Aun así la mayoría de organizaciones ignoran esta máxima. Increíble ¿no?, una vez más nos estamos dejando engañar por nuestra intuición sacrificando calidad para intentar lograr terminar antes. Dejar la calidad para el final nunca ha sido una buena idea.

Hay muchas otras trampas que la intuición nos pone y de las que ya he hablado en este blog:

No es raro que caigamos en el error de olvidar que no podemos vencer la tiranía del triángulo de gestión de proyectos, o que olvidemos la ley de Brooks y olvidemos que añadir recursos no es una solución que pueda funcionar, o incluso que nos creamos que existen balas de plata, herramientas o técnicas maravillosas que van a hacer que ganemos velocidad de desarrollo.

Lo  peor de todo es que el factor que más influye en el desempeño de un equipo de desarrollo no lo puedes gestionar fácilmente:  la motivación. Es más, la ciencia de la motivación, lo que llevamos décadas pensando que motiva a los desarrolladores se a demostrado, que contrariamente a lo que nos dice nuestra intuición desmotiva y es un elemento tóxico. Te sugiero que visites : Leer antes de motivar… o lo que debe saber todo jefe de proyecto.

Corolario: No eres el más listo. Lo que no ha funcionado a muchos otros no te va a funcionar a ti. La gestión de proyectos es una ciencia llena de trampas, soluciones atractivas que no funcionan, saber detectarlas y luchar contra ellas es el principal trabajo de quien gestiona proyectos.

En el próximo post hablaré de como Scrum evita estas trampas de la intuición estableciendo un conjunto claro de reglas. Saltarse esas reglas es una trampa en la que muchos caen sin darse cuenta de que están ahí para protegerte de ti mismo, de tu intuición errónea, de caer una vez más en ciertos antipatrones.

¡Un saludo!

Evento: Metodologías ágiles con Visual Studio 2010 en la oficinas de Microsoft en Madrid

imageEl próximo jueves, 16 de Diciembre tendré el placer de participar en un evento sobre los temas que más me apasionan, gestión de proyectos, y Team System en las oficinas de Microsoft en Madrid.

Sesión: Metodologías ágiles con Visual Studio 2010 (pinchad en el link para inscribiros)

Cada vez más empresas necesitan encontrar el equilibrio entre control de los proyectos y productividad de sus equipos de desarrollo, las metodologías ágiles proponen un marco de trabajo que nos permite gestionar los proyectos y mejorar la productividad de nuestros equipos de desarrollo sin caer en la temida burocracia. Team System es un marco de trabajo ideal que proporciona de manera integrada todas las herramientas que un equipo ágil puede necesitar. En este evento veremos cómo un equipo de desarrollo puede usar metodologías ágiles junto a Team System para dar un salto importante en su productividad.

Agenda:

Registro y bienvenida
Metodologías ágiles ¿qué son? ¿cómo nos ayudan?
Introducción a MSF Agile 
Introducción a Scrum
Scrum y Team System en el mundo real
Team System: la herramienta perfecta para el desarrollo ágil

Prometo un interesante paseo por las metodologías ágiles y Visual Studio.

La cobertura de código no significa nada

No deja de sorprenderme cuanta gente le da una importancia excesiva al valor de la cobertura. Entiéndaseme bien, al valor absoluto de la cobertura. A la cifra en si.

¿Qué significa tener una cobertura del 75%? ¿Nos dice algo este 75%? Pues la verdad es que algo dice, pero muy poco. El motivo es sencillo, una simple cifra nos da muy poca información sobre nuestro testeo unitario. Esa cifra no nos dice cómo están distribuidos nuestros test unitarios, tampoco nos dice mucho sobre la calidad de los mismos, ni sobre su mantenibilidad, ni menos aun sobre el tiempo que tardan en pasar…

¿Qué situación os parece mejor? Una batería de test unitarios con una cobertura del 75% en todos los componentes o una batería de test con una cobertura del 95% en aquellos componentes de la arquitectura que más cambian y una cobertura media del 60% en el resto. Si yo pudiese elegir en que aplicación trabajar, elegiría esta segunda. Seguro que los test unitarios me van a resultar más útiles.

Miremos ahora otro aspecto importante del los test unitarios. Supongamos una aplicación con una cobertura del 90% por cierto, pero que a cambio de obtener esta cobertura hemos tenido que sacrificar la velocidad de ejecución de los test. ¿Es esta una buena situación? ¿Es conveniente sacrificar otros aspectos como velocidad, mantenibilidad, tiempo consumido en su escritura excesivo, etc… para conseguir mayor cobertura? ¿Es aumentar la cobertura a cualquier precio una buena decisión?. Evidentemente no. No debemos nunca olvidar que la cobertura no sirve si olvidamos qué hace a un test unitario un buen test.

La cobertura es importante, sumamente importante,  pero solo puesta en contexto. Siempre que miramos a las métricas debemos hacerlo desde un enfoque multidimensional. Mi cobertura es el X% es una afirmación que no nos dice nada, pero que oímos habitualmente. Cuando miramos al porcentaje de cobertura de nuestro código debemos hacerlo desde un enfoque crítico siempre acompañado de una mirada a otros aspectos de nuestro testeo unitario, entre otros:

  • Son los test mantenibles: Aspecto fundamental, si tu test no son fáciles de mantener, da igual lo que hagas, su cobertura se irá reduciendo con el tiempo.
  • Tienen más test la partes más importantes: Es una simple cuestión de economía, si tus recursos son limitados, y siempre lo son, debemos enfocar nuestros esfuerzos en aquellas partes en las que el testeo nos va a dar mejores resultados. Prestar más atenciones a aquellas partes de nuestra aplicación más propensas a cambios, luego aquellas de las que dependen otras, luego aquellos que son compartidos por varios proyectos, etc…
  • Cuál es la relación coste beneficio de nuestro testeo unitario: debemos valorar situaciones como ¿realmente interesa complicar el proyecto con una librería de mockeado solo para ganar cobertura marginalmente?, ¿añadir un poco más de cobertura será a costa de enlentecer significativamente nuestros test?, ¿por un puntito más de cobertura vamos a añadir nuevas dependencias a nuestros test?, etc..

Cuando la cobertura muestra toda su potencia, como en general cualquier métrica, es cuando se estudia cómo está evolucionando. La evolución de la cobertura es lo realmente importante. Ese es el aspecto clave. El problema es que casi cualquier framework de testeo unitario, por si mismo o combinado con alguna herramienta especifica, es capaz de darte informarte de cual es tu cobertura en un momento determinado, pero recoger la evolución de la cobertura es algo mucho más complejo. Para empezar necesitas como mínimo un proceso de construcción automatizado, un repositorio donde recoger la evolución de la cobertura, y un mecanismo para representarla.

Los afortunados que usamos Visual Studio y Team Foundation Server contamos con todo lo necesario para tirar del hilo y mirar nuestro testeo unitario de manera poliédrica.

Podemos ver la cobertura por modulo, namespace o clase de nuestra aplicación:

Podemos ver cómo evoluciona la cobertura en relación a los cambios en el código y el número de bugs:

Example Build Quality Indicators report

Ver si nuestras builds tienen cobertura suficiente y sobre todo si están pasando de situaciones de cobertura suficiente a menos cobertura:

Healthy and Unhealthy version of Build Success

Example Build Summary report

En conclusión ojo con pensar que un porcentaje de cobertura determinado es indicador suficiente.

Un saludo.

Haz que tu código fluya

Sin duda la expresividad, la facilidad para leerlo y tener clara su intención y efectos sobre el sistema, es una de las características más importantes del código. Si por algo son interesantes las interfaces fluentes son por que aumentan extraordinariamente.

Los primeros en describir formalmente esta técnica fueron Eric Evans y Martin Fowler, aunque el origen de la misma esta en el idiom, descrito para C++, method chaining. Quizás la primera librería que presenta un uso acusado de este idioma es la Iibrería iostream de C++ que permite construcciones de estilo de out << “hola” << “ “<< “mundo” << endl, aplicando method chaining al operador <<. Además en C++ se hace a menudo uso del named parameter idiom, que también está en la base de las fluent interfaces.

¿Cómo implementamos fluent interfaces?

La técnica es sumamente sencilla en cualquier lenguaje orientado a objetos. Se trata básicamente en crear métodos que además de realizar una labor, que generalmente es cambiar el estado del objeto sobre el que se invoca el método devolver como resultado de la función el propio objeto (this, en los lenguajes de la familia C) de manera que podamos encadenar la siguiente llamada.

Miremos el siguiente ejemplo:

File f = OpenFile("foo.txt")

        .ReadOnly()

        .CreateIfNotExist()

        .AppendWhenWriting()

        .BlockSize(1024)

        .Unbuffered()

        .ExclusiveAccess();

Si el método ReadOnly de la clase está implementado de esta manera:

OpenFile ReadOnly()

{

    _ReadOnly = true;

    return this;

}

…podemos encadenar la llamada a CreateIfNotExists sin problemas, dotando a nuestro código de una expresividad mayor que si simplemente hubiésemos hecho:

File f = OpenFile("foo.txt")

     f.ReadOnly = true;

     f.CreateIfNotExist = true;

     f.AppendWhenWriting = true;

     f.BlockSize = 1024;

     f.BufferMode = BufferMode.Unbuffered;

     f.AccessMode = AccessMode.ExclusiveAccess;

Vemos que implementar fluent interfaces es trivial en casi cualquier lenguaje orientado a objetos. Pero que sea fácil no quiere decir que sea adecuado siempre ¡ojo!. Ahora bien, cuando es adecuado, la potencia de esta técnica es clara y notoria. Esta técnica esta especialmente indicada cuando tenemos una serie de métodos y/o propiedades que tiene en la mayoría de las ocasiones tienen sentido invocar uno tras otro sobre el mismo objeto. Por ejemplo, una variación de esta técnica se usa para implementar las continuaciones en la Taks Parallel Library de .Net, permitiendo que podamos expresar de manera muy simple el encadenamiento de una serie de tareas:

new Task().ContinueWith(…)

          .ContinueWith(…)

          .ContinueWith(…)

          .ContinueWith(…)

          …

¿Cómo nos ayudan las fluen interfaces?

Hay dos librerías que son un claro ejemplo de la potencia de esta técnica y que son sumamente útiles.

La primera es una librería Fluent Validation que permite expresar validaciones de manera sumamente elegante:

using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Company).NotNull();
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

La otra, Fluent Assertions, es una librería que permite expresar aserciones en nuestras pruebas unitarias utilizando una fluent interface:

// Example

string actual = "ABCDEFGHI";

actual.Should().StartWith("AB").And.EndWith("HI").And.Contain("EF").And.HaveLength(9);

 

// Example

IEnumerable collection = new[] { 1, 2, 3 };

collection.Should().HaveCount(4, "because we thought we put three items in the collection"))

 

// Example

var recipe = new RecipeBuilder()

   .With(new IngredientBuilder().For("Milk").WithQuantity(200, Unit.Milliliters))

   .Build();

 

// Act

Action action = () => recipe.AddIngredient("Milk", 100, Unit.Spoon);

 

// Assert

action

   .ShouldThrow<RuleViolationException>()

   .WithMessage("Cannot change the unit of an existing ingredient")

   .And.Violations.Should().Contain(BusinessRule.CannotChangeIngredientQuanity);

Ambas librerías están disponibles a través de NuPack, así que no tienes disculpa para no probarlas.

¡Un saludo!

Leer antes de motivar… o lo que debe saber todo jefe de proyecto sobre la motivación

Lo más bonito de mi trabajo es que los clientes no dejan de sorprenderte nunca. Hace unos días llegue a un cliente, en el que recientemente hemos arrancado un piloto de un equipo. De las primeras cosas que llamaron mi atención fue ver tres líneas diferentes en su burndown chart. Tras preguntar, el jefe de desarrollo y el Scrum Master del equipo, me contaron, no sin cierto pudor, que las líneas representaban diferentes grados de cumplimiento de los objetivos del sprint, ¡cómo si fuese posible cumplir en diferentes medidas el trabajo comprometido para un sprint!.

Me reacción fue de clara contrariedad. Ellos sabían que la cosa no me iba a hacer gracia, pero se veían en la necesidad clara de ¡motivar al equipo!. Yo sabía que no era buena idea intentar ‘motivar’ al equipo prometiéndoles recompensas económicas por cumplir ‘más’ el sprint. Lo sabía porque ya había sufrido estos intentos de ‘motivarme’ durante mi carrera profesional y siempre habían tenido resultados dañinos. Lo sabía empíricamente, pero claro, cuanto te pagan por tu conocimiento, generalmente, no vale solo con decir, ‘tu idea no vale porque yo ya la he visto fallar’. Se espera una respuesta más analítica. Les apunté un artículo de Joel Spolky sobre el tema, titulado, Los pagos de incentivos considerados dañinos, pero me quede con la sensación de no haber respondido a su necesidad. La gente cuanto te paga por responder preguntas y ayudarles no quieren solo saber que puede pasar y como debe actuar sino los porqués…

La siguiente cuestión que se puso sobre la mesa fue: ¿tú qué haces para motivar a tu equipo? Mi respuesta es clara: tratar de no desmotivar. Hace tiempo leí o alguien me conto, que una buena forma de actuar es tratar de no hacer lo que a ti te han hecho y te ha desmotivado. Y a eso me suelo ceñir en lo que ha motivación se refiere.

Automáticamente me di cuenta de una realidad: ¡No sabía gran sobre la motivación! Y la motivación es el factor que más influye en el rendimiento de un equipo de desarrollo, eso sí que lo tengo muy claro, gracias al trabajo de Boehm que Steve McConnell refleja en sus libros que yo he leído con deleite. Si queremos equipos motivados no es para ser nominados a gestores del año, no, es simple egoísmo (léase sin connotaciones negativas) económico. Los desarrolladores motivados producen más.

En esta tesitura, tras dejar al cliente y llegar al aeropuerto, en una de esas casualidades que tiene la vida, mirando libros en el aeropuerto, tras el enésimo retraso del Vueling, encontré ‘La sorprendente verdad sobre qué nos motiva’ de Daniel H. Pink. Y ahora, unos días después de devorar el libro, puedo escribir este post.

¿Por qué mi intuición de que ofrecer dinero a un equipo de desarrollo por completar más historias que las comprometidas para un sprint no funciona es cierta?

Lo que debemos saber es que hay dos tipos de labores que los empleados pueden realizar. Hay tareas que son algorítmicas, que consisten en repetir una determinada receta para lograr un determinado objetivo productivo sin cabida para la creatividad o tareas heurísticas en las que el componente creativo es un factor relevante. ¿Alguien duda de que el desarrollo de software es una tarea de creación? Desarrollar software exige tomar continuamente decisiones de diseño. Cada línea es una decisión de diseño o varias. No es para nada una tarea repetitiva. Un desarrollador está continuamente solucionando problemas.

Hay un experimento esclarecedor descrito en el libro de Pink que demuestra científicamente que para tareas que requieren de creatividad y de dotes de resolución de problemas los incentivos económicos son dañinos. El experimento consistió en proponer a dos grupos de personas la resolución de un problema, el problema de la vela, cuyo planteamiento y solución podéis ver en la siguiente imagen, que exige cierta componente de pensamiento creativo. Se trata de sujetar la vela a la pared sin derramar una sola gota de cera. La solución una vez la conoces parece obvia, pero exige cierto pensamiento lateral para ver que es necesario sacar los clavos de la caja y que no es necesario usar las cerrillas.

Experimiento de la vela

A un grupo se le dijo que se le pagaría una cantidad si lograba resolver el problema, y a otro no. Sorprendentemente, el grupo remunerado obtuvo peores resultados a la hora de resolver el problema. El experimento demuestra que el hecho de establecer una recompensa económica automáticamente desvía nuestra atención de resolver el problema a obtener la recompensa.

El libro de Pink describe un motón de experimentos similares que llegan a una conclusión que es contraintutiva: tratar de motivar el trabajo mediante incentivos económicos solo funciona para tareas muy simples. Y desarrollar software no es una tarea simple. Además y de manera sorprendente, los incentivos económicos no solo no mejoran el rendimiento de los equipos de desarrollo, sino que además, a menudo ¡lo empeoran!. Es curioso ver en libro ejemplos de investigaciones que demuestran resultados muy ‘extraños’: incentivar económicamente la donación de sangre se traduce en una menor tasa de donaciones, los artistas realizan obras de peor calidad cuando están trabajando por encargo, los escolares que reciben un diploma por pintar pierden el interés por esta actividad… ¡cuando menos sorprendente!. Esto resultados ponen en evidencia la creencia general en gestión de que las personas respondemos al palo y la zanahoria, a un esquema de incentivos y castigos.

Para conocer el porqué hay que tener en cuenta que existen dos tipos fundamentales de motivación: la motivación extrínseca, es aquella que aparece cuando lo que atrae no es la acción que se realiza en sí, sino lo que se recibe a cambio de la actividad realizada (por ejemplo, dinero, comida o cualquier otra forma de recompensa) y la motivación extrínseca, que aparece cuando el individuo realiza una actividad por el simple placer de realizarla, sin que nadie de manera obvia le de algún incentivo externo. Cuando hablamos de trabajos en los que la creatividad juega un papel, la motivación intrínseca es sumamente importante, muchísimo más que la motivación extrínseca. Y lo que es más relevante, la motivación extrínseca forzada daña el rendimiento en este tipo de actividades.

No hay mejor manera de convertir un trabajo interesante y motivador en una pesada carga que tratar de incentivarlo. Si a un desarrollador le ofreces incentivos por realizar su trabajo, automáticamente le estas lanzando el mensaje de que el trabajo que realiza no debe despertar en él el interés suficiente por si mismo. Todos los desarrolladores odiamos los trabajos que no son interesantes, que no plantean un reto o una oportunidad de aprendizaje. Evidentemente en el desarrollo de software hay muchos trabajos que son repetitivos, pero por suerte, esto son susceptibles de ser automatizados, pedir a un desarrollador que automatice un trabajo repetitivo es mucho más productivo que remunerarle por realizar un trabajo que considera desagradable.

La psicología ha dado la explicación a algo que se sabía hace mucho tiempo. Fijaros en los factores que motivan a los desarrolladores, descubiertos por Barry Bohem hace décadas, tal y como aparecen en recomendable artículo Best Practices to Increase Productivity and Decrease Turnover de Janet Amirault:

image

El salario, en el caso de los desarrolladores de proyectos y los gestores aparece en el noveno lugar, tres más abajo que para la gente en general. Vamos que intentar motivar a desarrolladores con dinero, no da buenos resultado, hay factores mucho más influyentes y adecuados.

El corolario, expresado por Pink en su libro es que debemos recordar siempre que los incentivos basados en ‘si haces esto obtendrás aquello’ pueden eliminar la poderosa motivación intrínseca, reducir el rendimiento, dañar la creatividad, apartarnos de una conducta adecuada para lograr los objetivos volverse adictivos (necesitándose mayores y mayores incentivos cada vez) y potenciar el pensamiento cortoplacista.

Veamos qué escenario nos encontraríamos si cogemos un equipo y le ofrecemos dinero por terminar más historias de las comprometidas para un sprint. Para empezar, algo que es una meta loable, conseguir los objetivos marcados, algo a lo que nuestro ‘buenismo’ natural nos empuja, se convertiría en algo por lo que debemos ser sobre compensados. Implícitamente es admitir que el trabajo no es interesante, o no es motivador por si mismo o que los objetivos solo son factibles con una sobre motivación. Además la gente, como demuestra el experimento de la vela la gente se concentraría en fin, y olvidaría los medios. El fin de obtener el objetivo haría que fuésemos menos eficientes en el proceso de obtenerlo. Además seguro que algunos desarrolladores, sino todos, tomarían atajos de calidad, o no escribirían test unitarios o actualizarían la documentación solo para cerrar un historia más y obtener la recompensa, sutilmente estaríamos recompensando comportamientos anómalos. En el hipotético caso de que los incentivos funcionasen a corto, nunca funcionarían a largo plazo, pues cada vez serían necesarias mayores dosis para lograr los mismos resultados, algo insostenible económicamente.

Lo que si funciona, siempre administrándolo con juicio, son las recompensas no esperadas. Y sobre todo, aunque parezca mentira, lo que más funciona, es el reconocimiento al trabajo bien hecho. Un simple reconocimiento explícito es lo que mejor resultado da según muestran los estudios que Pink muestra en su libro.

Creo que después de todo, mi táctica de simplemente tratar de no desmotivar, es más que acertada. Y creo que la táctica de las metodologías ágiles de establecer metas claras, dar voz a los desarrolladores y permitir la excelencia son poderosos catalizadores de la motivación intrínseca.

Por si este post no ha despertado suficiente interés en vosotros sobre este tema, os dejo un video (en inglés) resumen brutal del libro de Pink, espero que lo disfrutéis:

¿A vosotros que os motiva?.

P.D.: Los videos con subtítulos en español (La soprendente verdad sobre los que nos motiva 1/2 y La sorprendente verdad sobre lo que nos motiva 2/2).

Experiencias en la implantación de metodologías ágiles con Visual Studio Team System

Cuando Microsoft lanzo Visual Studio Team System hace unos cuatro años, muchos desarrolladores vimos como se cumplían nuestras expectativas de lograr que Visual Studio se convirtiese en una herramienta al servicio de los equipos de trabajo y no solo al servicio de los desarrolladores. Además personalmente vi colmada otra expectativa, contar con una herramienta en entornos Microsoft que acercase las metodologías a los equipos de desarrollo, con independencia de la metodología elegida y del tamaño del equipo de desarrollo. En estos cuatro años he participado en multitud de proyectos de implantación de Team System, y Team System y las metodologías ágiles forman parte de mí día a día como desarrollador. En este artículo pretendo compartir lo aprendido sobre la implantación de metodologías ágiles con Team System, las dificultades encontradas, como las hemos abordado y que resultados hemos obtenido.

¿Por qué metodologías ágiles?

En Team System cuando creamos un nuevo proyecto en nuestro Team Foundation Server, la primera elección que debemos hacer y sin duda una de las más importante para el futuro de nuestros proyectos será la metodología que queremos usar. Las opciones son variadas y cada vez lo serán más, pues cada poco tiempo aparecen nuevas plantillas metodologías que podemos instalar en nuestro Team Foundation Server. No me voy a extender mucho en este punto, más siendo que en este mismo número podéis encontrar información sobre este tema. Simplemente me gustaría recalcar la importancia de que esta elección sea fundamentada y basada en el conocimiento de varias metodologías.

Dicho esto, ¿por qué elijo metodologías ágiles en la mayoría de las ocasiones? El motivo es uno solo: economía de recursos. En la mayoría de las ocasiones, lo equipos que implantan Team System tiene un conocimiento más o menos profundo de la herramienta y una fuerte predisposición para usarla, pero es raro que la motivación principal sea implantar una metodología. En esta situación es evidente que un enfoque de menos a más es el adecuado. Yo siempre digo que las metodologías se ganan como las contrarreloj en ciclismo: yendo de menos a más. Es muy difícil saber qué ‘cantidad de metodología’ necesita un proyecto, un equipo y una empresa. Poder ir de menos a más, añadir paulatinamente elementos hasta lograr el equilibrio justo entre tener un ciclo de vida gestionado y coste de mantenimiento del proceso y evitar que un exceso de burocracia asesine la adopción de la metodología es el vital. Las metodologías ágiles permite esto precisamente. Otras metodologías imponen ya de entrada unos costes de implantación y de mantenimiento que no todos los proyectos, equipos o empresas necesitan o pueden asumir. Mantenerse ágil es utilizar el mínimo de elementos metodológicos que eligiendo aquellos que más valor aportan al equipo de desarrollo.

Otro aspecto que me preocupa particularmente a la hora de elegir una metodología es que el desarrollador la perciba como algo familiar, que le puede ayudar en su trabajo diario. Los desarrolladores tienden a pensar en las metodologías ágiles de manera más amistosa mientras que ven otro tipo de metodologías como una imposición de más burocracia. No digo que esta percepción sea siempre correcta, pero sí que es cierto que contar con el apoyo y la comprensión de los desarrolladores es vital a la hora lograr implantar con éxito una metodología. El motivo es simple: ¡los desarrolladores son los más numerosos de todo los roles implicados en un proyecto!

Más adelante hablaré de las buenas prácticas, aspecto clave para tener un ciclo de vida sano. La metodología es el pegamento que une esas buenas prácticas y que permite gestionar el proceso de desarrollo de principio a fin, iteración tras iteración. Señalar que Scrum y MSF Agile son las opciones más frecuentemente elegidas en las implantaciones de Team System utilizando metodologías ágiles.

Las buenas prácticas: claves para el éxito

Durante el tiempo que llevo trabajando con Team System he visto equipos brillar con diferentes metodologías, ágiles y no. Pensando en esto he llegado a una conclusión clara. Todos esos equipos tenían algo en común: habían elegido una serie de buenas prácticas, no siempre las mismas, y las habían incorporado al día a día de su ciclo de vida en el marco de una metodología. Además, todos esos equipos habían utilizado inteligentemente las posibilidades que Team System nos brinda a la hora de adoptarlas. Si importante es adoptar buenas prácticas, igualmente importante es apoyar esta adopción en una herramienta que facilite la vida la vida del desarrollador. Toda práctica que queramos introducir en nuestro ciclo de vida va a encontrar una resistencia inicial por parte del equipo, utilizar una herramienta natural para el programador es vital. Team System permite a los desarrolladores realizar todas las actividades relacionadas con el seguimiento del proyecto y la puesta en marcha de buenas prácticas desde el entorno que más natural les resulta, su herramienta de desarrollo, Visual Studio.

Además de usar una herramienta que facilite la adopción de buenas prácticas, seleccionar qué buenas prácticas queremos incorporar a nuestro proceso de desarrollo es una cuestión que exige atención.

El difícil problema de la gestión de proyectos

Gestionar proyectos de software es una tarea difícil. Son muchos los aspectos relevantes y muchas las personas implicadas. Entre los aspectos relevantes podríamos citar una infinidad de ellos: las herramientas, los procesos, la gestión del riesgo, la involucración del cliente, la gestión de la configuración, la calidad, el retorno de la inversión, así, una larguísima relación de cuestiones relevantes. La dificultad está en elegir en cuales de estos aspectos vamos a centrar nuestros esfuerzos en primera instancia. Además, para más inri, ni siquiera serán los mismos de proyecto a proyecto. Evidentemente todos estos aspectos de la gestión de proyectos presentan dificultades, sobre las que podemos actuar para obtener ciertos resultados. Tras años de participar en la implantación de proyectos he llegado a valorar algunas de estos aspectos por encima de otros en base a su rango de aplicación en el espectro posible de tipos de proyectos, sus posibilidades de éxito y los resultados obtenidos una vez puestos en funcionamiento. Comentar las dificultades, las acciones realizadas en pos de su puesta en marcha y los resultados obtenidos es lo que viene a continuación.

El equipo multidisciplinar, auto-organizado y auto-gestionado

Las metodologías ágiles abogan por formar un equipo multidisciplinar, auto-organizado y auto-gestionado. Entender y formar este tipo de equipos es difícil, pero si logramos establecer un proceso de trabajo que promociones las relaciones entre iguales y el trabajo en pos de una meta compartida y con una visión común, las ventajas son muchas. Es evidente que cuando logramos trabajar en equipo la productividad se ve impulsada de manera importante. Un equipo de cuatro es mucho más productivo que la simple suma de cuatro individuos. Desde mi punto de vista hay varios puntos clave a la hora de lograr funcionar en equipo: establecer una visión común de proyecto, fomentar la participación de todos los miembros y la participación de compartida en los resultados y sobre todo permitir que sea el equipo quien en base a estimaciones establezca sus compromisos. Un equipo que establece compromisos claros, basados en un proceso formal de estimación, de manera consensuada y solidaria y los asume como suyos se deja la piel para cumplirlos. No aparece ningún dilema moral sin embargo cuando un equipo no logra cumplir compromisos que han sido establecidos por terceros en su nombre.

La estimación explicita como base de compromisos realistas

Evidentemente para poder establecer compromisos realistas es necesario realizar un proceso formal de estimación. Estimar la magnitud del proyecto y la magnitud de las porciones de proyecto que vamos a abordar en cada iteración es vital, puesto que solo así podremos establecer compromisos realistas, alineados con la capacidad del equipo. Un equipo de desarrollo solo va a tratar de cumplir aquellos objetivos que percibe que son realistas. Es necesario aprender a estimar y estimar en cada iteración. Un primer paso es comprender que las estimaciones solo son estimaciones. Esto que, a priori, es una perogrullada, se tiende a obviar. Los involucrados en los proyectos, especialmente los roles involucrados en la gestión del proyecto y la relación del cliente, tienden a olvidar esto. Tenemos que entender que cuando un desarrollador da una estimación no conoce muchos de los aspectos que con más fuerza influirán en la duración de la tarea, como, por ejemplo, la dificultad técnica. Además estos aspectos son mucho más difíciles de ver cuanto más lejano está el punto de inicio de la tarea. Las estimaciones con estimaciones, no contratos. Cuando alguien ajeno al equipo convierte las estimaciones en contratos está realizando un acto de adivinación no de ingeniería del software. Si una estimación no nos gusta o no casa con las necesidades del proyecto solo podemos añadir recursos o recortar características para que se ajuste a nuestras necesidades. Estimar y re-estimar con frecuencia, al inicio de cada iteración y tratar las estimaciones con responsabilidad y con respeto es el camino que nos lleva a poder gestionar nuestros proyectos en base a datos objetivos. ¿Pero qué técnicas podemos usar para estimar con frecuencia y con la participación de todo el equipo de manera ágil? Las técnicas que estimación que más adopción y mejores resultados presentan, usadas en combinación, en proyectos ágiles son Wideband Delphi y Planning Poker. No entro en detalles, pero si invito al lector a visitar la sección sobre estimación de mi blog donde encontrará información suficiente sobre estas técnicas.

Asumir el cambio como una oportunidad

Otro aspecto complicado en la adopción de metodologías ágiles es que estas asumen el cambio como algo positivo, inherente a todo proyecto de desarrollo de software. El cambio se debe percibir como una oportunidad más que como un problema. Mi experiencia es que este planteamiento choca de manera frontal con el estilo de gestión clásico al que muchos hemos estado acostumbrados. Cambiar esta mentalidad es un reto claro en toda implantación de metodologías ágiles. Es necesario comprender y explicar que si bien los cambios son bienvenidos para que estos nos asesinen el proceso de desarrollo es necesario arbitrar cuando se pueden producir. Que el cambio sea una realidad en todo proyecto, que lo gestionemos como una oportunidad y que bien gestionado el cambio nos ayude a cubrir las necesidades del cliente no quiere decir que el cambio constante sea bueno. Solo durante la planificación de una iteración es posible asumir cambios y estos deben estar fundamentados en necesidades reales surgidas de nuevas oportunidades o de cambios en el entorno. La manera en la que lidiamos con los cambios es simple: Iterar, iterar, iterar y volver a iterar… en iteraciones cortas durante las cuales los cambios están congelados y planificar, planificar, planificar y volver a planificar en base a estimaciones al comienzo de cada iteración. Evidentemente contar con una herramienta que nos permita gestionar de manera ágil y cómoda la información surgida del proceso es vital. Es aquí donde Team Foundation Server nos ayuda de manera clara.

Pruebas unitarias

En todo proyecto hay una frase que se oye a menudo: ‘si funciona, no lo toques’. Esta máxima es un exponente claro de la dificultad que los desarrolladores hemos padecido a la hora de mejorar, mantener y extender nuestro código. Todos sabemos que una función con mil líneas es una mala solución, pero solo si contamos con un mecanismo que nos permita saber que si mejorarnos esa situación no romperemos nada. Este mecanismo es son las pruebas unitarias. Si bien esta capacidad para integrar cambios con facilidad es a mi modo ver la principal ventaja de las pruebas unitarias no es la única:

  • El conjunto de test unitarios proporciona constante retroalimentación de que cada uno de los componentes sigue funcionando.
  • Los test unitarios actúan como documentación que no se queda obsoleta, al contrario que otros tipos de documentación.
  • Cuando el test pasa y el código de producción es refactorizado para eliminar duplicidades, es claro que el código está terminado, y el desarrollador se puede mover a la siguiente tarea.
  • El testeo unitario fuerza un análisis y diseño explicito porque el desarrollador no puede crear código de producción sin entender realmente cuales deberían ser los resultado deseados y como probarlos.
  • El software tiende a estar mejor diseñado, esto es, menos acoplado y más fácilmente mantenible, porque el desarrollador es libre de hacer decisiones de diseño y refactorizar en cualquier momento con la confianza de que el software todavía funciona.
  • El conjunto de pruebas actúa como una red de seguridad contra regresiones en los bugs: Si se encuentra un bug, el desarrollador debe crear un test que ponga de manifiesto el bug y después modificar el código de producción para eliminar el bug. En sucesivas ejecuciones de los test, todas las correcciones de bugs son verificadas.
  • El tiempo de depuración se reduce.

La principal dificultad a la hora de adoptar las pruebas de desarrollo en nuestro ciclo de vida es asumir que se trata de una inversión no de un coste. Es evidente que implementar las pruebas unitarias tiene un coste, y que este coste solo se rentabiliza cuando hay una base de código amplia. Es necesario hacer por tanto un acto de fe y creer que las pruebas unitarias nos ayudaran de manera cada vez más importante según la base de código vaya creciendo y el software se vaya complicando. Este acto de fe, muy sencillo para los equipos que han usado pruebas unitarias con anterioridad, es más difícil si ninguno de los miembros ha usado esta técnica antes. En estas situaciones, desde la dirección del proyecto se debe lanzar un mensaje claro: las pruebas unitarias no son opcionales.

El testeo unitario se debe implementar desde la primera línea de código del proyecto para que sea totalmente exitoso. Si lo hacemos, sin un gran, esfuerzo conseguiremos reunir un conjunto de pruebas que actuarán como una red de seguridad en nuestro proyecto. Otro aspecto importante en relación a las pruebas unitarias es contar con una herramienta de desarrollo que facilite al desarrollador la escritura y la ejecución de las pruebas. Visual Studio Team System cuenta con un poderosísimo framework de pruebas unitarias y con un motón de facilidades a la hora de ejecutarlas desde dentro del propio entorno. Personalmente, si tuviese que elegir la técnica que más ha impactado en como desarrollo software en los últimos años, sin dudarlo ni un segundo, diría que es el testeo unitario y su integración en el entorno de desarrollo.

1. Testeo unitario

Testeo unitario: Visual Studio Team System permite integrar con facilidad el testeo unitario en nuestra metodología de desarrollo.

Integración frecuente y construcciones automatizadas

Una de las grandes novedades de Visual Studio Team System y Team Foundation Server es la posibilidad de crear construcciones automatizadas. Pero el simple hecho de contar con una herramienta que nos ayude en la tarea no significa que vayamos a adoptar una buena práctica. De hecho antes de Team System ya existía NAnt como herramienta de automatización de la construcción, y se trata de una gran herramienta, pero aun así pocos son los equipos de desarrollo que cuentan con la posibilidad de construir todo su proyecto con la simple ejecución de un comando, son pocos los que usan construcciones automatizadas. Conocer las ventajas que aporta las construcciones automatizadas es el único camino para que estas se popularicen y más y más equipos de desarrollo disfruten de sus bondades.

El proceso de construir el software desde las fuentes es complejo. De hecho es cada vez más complejo: elegir la fuentes adecuadas, compilarlas con las versiones adecuadas de los componentes, asegurarnos que hemos compilado la configuración adecuada (debug o release), seleccionar de la salida del proceso de compilación aquellos archivos que debemos distribuir, no olvidar incluir aquellas librerías o componentes de los que depende nuestro software y asegurarnos de que su versión es la correcta, generar los archivos de ayuda, crear la estructura de directorios que espera como entrada nuestra herramienta de generación de instaladores, ejecutar el proceso de generación del instalador… y todo esto involucrando a un buen número de personas diferentes ¿de verdad alguien cree que es posible realizar este proceso manualmente sin cometer varios errores durante el mismo?. La cruda realidad es que no es posible. Y lo que es peor, a menudo los errores cometidos en alguno de los múltiples pasos que hay que dar se detectan solo al final del proceso. El resultado: ¡una enorme pérdida de tiempo!. Y lo peor del caso es que este es un proceso que se repite muchas veces a lo largo de la vida de un proyecto. Además, para agravar aún más la situación este problema ocurre cuando menos tiempo tenemos, ¡justo cuando alguien está esperando que le entreguemos el software!.

En todo proyecto de software existe un ciclo que ser repite infinitas veces: escribir código, compilarlo, integrarlo y realizar pruebas. Contar con un proceso de construcción del software automatizado hace que este ciclo se acelere enormemente.

El principal problema que plantean las construcciones automatizadas es que exigen una inversión de tiempo para ponerlas en marcha. Configurar un proceso de construcción completo que sea capaz de desde el código fuente de nuestro software construir el software completamente hasta el instalador y además desplegarlo en un sistema de prueba es complejo. De hecho es algo que solo es abordable y rentable si se realiza de forma incremental, haciendo que el proceso de construcción crezca de manera paralela a nuestro software. En cualquier caso, a menudo, en proyectos con problemas de integración, merece la pena invertir el tiempo necesario para configurar un proceso de construcción a posteriori. El esfuerzo es grande pero a menudo no hay otro camino para zanjar de raíz los problemas de integración en los proyectos de software. Resumiendo, más vale configurar pronto el proceso automatizado de construcción que hacerlo a posteriori cuando hay problemas.

Si bien el simple hecho de poder construir nuestro software de manera automática nos proporciona claras ventajas, yendo un paso más allá y construyendo nuestro software diariamente (gracias a nuestro proceso automatizado de construcción esto es algo posible) podemos obtener ventajas añadidas. Si diariamente construimos nuestro software detectáramos rápidamente problemas de integración y corregirlos cuando los cambios que pueden ser la causa aun están frescos en nuestra memoria y por tanto nos es más fácil corregirlos. Además como parte del proceso de construcción podemos ejecutar nuestros test unitarios lo que nos proporcionará la posibilidad de detectar errores no solo relacionados con la integración. Adicionalmente, como colofón a nuestro proceso de construcción y aprovechando que nuestro proceso de construcción despliega el software construido a un entrono de pruebas podemos realizar un test de humo que asegure que el software construido tiene la calidad suficiente como para ser probado en profundidad. Este paso asegura que cualquier error relativo a la configuración del software desplegado se detecta pronto.

A menudo se pone como escusa para no realizar construcciones diarias la magnitud del proyecto: ¿Cómo vamos a construir y desplegar un software tan complejo todos los días? Precisamente cuanto mayor es el proyecto mayores son las posibilidades de sufrir problemas de integración y de calidad pues más es el código que cada día se añade. Además el hecho de que grandes proyectos como por ejemplo Firefox lo haga, demuestra que es viable y rentable. Podéis ver el estado de las construcciones diarias de Firefox (http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox).

Métricas

Las métricas son el camino hacia una gestión explicita de proyectos, basada en datos, no en intuiciones. La gran mayoría de los gestores de proyectos creen que las métricas son un instrumento poderoso, pero la gran mayoría de los proyectos no usan métricas. Este hueco se produce por la dificultad para recolectar los datos que fundamentan estas métricas. He visto implantaciones de metodologías fallar estrepitosamente por el hecho de que los desarrolladores tenían que pelear para abrir la hoja Excel en la que se realizaba el seguimiento del proyecto para alimentar los datos, con el resultado de que ese seguimiento se abandonaba.

Si en algo ha cambiado Team System la gestión de proyectos es en la facilidad que tenemos para recolectar métricas de lo más variado sin interferir en el día a día del desarrollador, sin imponerle burocracia adicional. El desarrollador trabaja desde el entorno de desarrolla, realizando sus actividades habituales y de forma casi transparente alimenta un completísimo datawarehouse que permite que todo el equipo y los gestores del proyecto accedan a las métricas más relevantes relacionadas con la metodologías elegida.

En las metodologías ágiles, la velocidad de desarrollo entendida como el trabajo realizado frente al trabajo que hemos estimado que nos queda por hacer es la principal métrica. Utilizar la velocidad como principal métrica está fundamentada en que incrementos en este aspecto del desarrollo son síntoma claro de mejora del proceso de desarrollo. Si desarrollamos más rápido, es que desarrollamos mejor. Además es una métrica difícilmente sesgable, si para mejorar la velocidad de desarrollo sacrificamos por ejemplo la calidad, olvidándola, o el equipo, forzándole por encima de su capacidad o cualquier otro aspecto, tarde o temprano esto se verá reflejado en la velocidad. Además la velocidad es una métrica que nos permite estimar con facilidad cuando el proyecto estará concluido o que magnitud de funcionalidad se debe quedar fuera para cumplir una fecha concreta.

Implantar métricas de progreso clara, nos permite informar a partes ajenas al desarrollo de cuál es el comportamiento del proyecto de manera analítica, explícita y difícilmente rebatible. Esto hace que el resto de los afectados por un proyecto puedan actuar en fase a datos. Los comerciales no comprometen fechas imposibles, los redactores técnicos pueden planificar cuando podrán comenzar a capturar pantallazos de la documentación, el departamento de calidad final sabrá cuando debe esperar carga de trabajo relacionada con nuestro proyecto, etc…

2. Metricas

Métricas: La velocidad es la métrica clave en las metodologías ágiles, Visual Studio Team System nos permite obtenerla sin imponer burocracia al desarrollador.

Facilitar la comunicación

La comunicación dentro de los proyectos y hacia afuera de los proyectos es un problema claro que todas las metodologías tratan de atajar. Algunas como RUP o CMMI ponen el peso en la documentación y en generara artefactos que actúen como repositorios de información que se mueven de un lado para otro. Otras como Scrum o XP y en general las metodologías ágiles asumen que las personas son el principal repositorio de conocimiento y tratan de habilitar mecanismos (como una serie de reuniones con propósito claro, asistentes determinados, duración preestablecida y entregables predefinidos) para promocionar que las personas compartan información. Sin duda en todo proceso de desarrollo ágil o no tendremos que mantener una magnitud mayor o menor de documentación.

Es vital lograr que todo el equipo esté informado. Es aquí donde una herramienta de gestión de proyectos juega un papel vital. Contar con un lugar único donde el desarrollador pueda consulta sus tareas, sus bugs o donde el gestor del proyecto pueda consultar si un requisito esta implementado o probado o no facilita de manera radical el acceso a la documentación. Pero no solo eso, exprimir al máximo las capacidades de notificaciones que Team Foundation Server pone a nuestro servicio nos va a permitir lograr un enfoque ‘push’ en nuestra gestión de proyectos. Ya no es necesario recordar mirar nuestras métricas, podemos recibirlas en nuestro correo cada día. Unamos esto a la capacidad que tiene el portal del proyecto de Team System para radiar información hacia el exterior del proyecto, para actuar como repositorio de la información y sobre todo, para informarnos de cuando hay cambios en documentos de nuestro interés y veremos que la labor de gestión de proyectos será mucho más efectiva, gracias a la utilización de herramientas como gestores documentales, wikis y listas de discusión.

3. Alertas

Alertas: La capacidad de subscribirnos a información relevante facilita enormemente la gestión del proyecto.

Calidad, calidad y… calidad

Unos de los principios de MSF dice que ‘La calidad es el negocio de todos todos los días’. No dejar la calidad para el final es vital. Si algo he aprendido implantando metodologías es que es imposible pensar en tener un proceso de desarrollo sano y sostenible sin incorporar testers a los proyectos. Podéis ahondar en las justificaciones leyendo un artículo publicado en mi blog, titulado ‘Pon un tester en tus proyectos’ (http://geeks.ms/blogs/rcorral/archive/2006/10/21/Pon-un-tester-en-tus-proyectos.aspx)

Es difícil asumir que añadir calidad a nuestro software, hasta cierto punto, al contrario de lo que puede parecer a primera vista, reduce los costes de desarrollo y acorta los plazos. La reducción de costes se produce porque con un adecuado proceso de desarrollo, que tenga la calidad del software como un factor central, se descubre antes los errores. Y los errores, de cualquier índole, son más costosos cuanto más tarde se descubren, además estos coste se incrementan siguiendo un función exponencial. Descubrir que nuestra arquitectura no es capaz de gestionar el número requerido de transacciones por segundo, es infinitamente más costoso de corregir si se descubre durante las pruebas de aceptación que durante la revisión de la arquitectura. La reducción del tiempo de desarrollo se produce porque es mucho más fácil construir software sobre software estable que sobre software que no es estable. Hoy en día todos los procesos de desarrollo de software son en mayor o menor medida iterativos e incrementales. Es imposible construir un incremento de funcionalidad si la base de ese incremento no es estable.

Debemos tener en cuenta que el nivel de calidad lo decide el cliente no nosotros. Ningún cliente aceptará de buen grado un software que no cumple sus estándares de calidad. Poner el esfuerzo en averiguar cuál es el nivel de calidad que nuestros clientes requieren y asegurar que durante todo el proceso de desarrollo estamos muy próximos a ese nivel. Pasarse es desperdiciar fuerzas y quedarse corto significa que en algún momento tendremos que hacer un esfuerzo añadido para alcanzar las expectivas de calidad de nuestro cliente. Si queremos poder actuar con agilidad, incorporar cambios de manera sencilla, y construir el software de manera iterativa e incremental es imprescindible lograr mantener el nivel de calidad a lo largo de todo el proceso.

Cuando apareció Visual Studio Team System, Microsoft puso a nuestra disposición una herramienta de pruebas completamente integrada en el ciclo de desarrollo de la aplicación. Los testers son uno más del equipo de desarrollo, utilizan las mismas herramientas que los desarrolladores y consolidan la información sobre los resultados de las pruebas en el mismo servidor de gestión de proyectos. Esto hace que el proceso de compartir la información entre desarrolladores y testers sea mucho más eficiente.

4. Calidad

Calidad: Visual Studio Team System proporciona las herramientas necesarias para hacer de la calidad un punto central de nuestro proceso de desarrollo.

Conclusiones

Visual Studio Team System y las metodologías ágiles son una excelente pareja que me ha permitido ayudar a numerosísimos equipos a mejorar su manera de desarrollar software. Usar metodologías ágiles me ha permitido optimizar la relación entre el esfuerzo de implantación y los resultados obtenidos. Utilizar Visual Studio Team System ha sido vital a la hora de impulsar y facilitar la adopción de buenas prácticas de gestión de proyectos e ingeniería del software.

Articulo publicado con anterioridad en DotNetMania.

Oferta de empleo: Desarrollador de software para Plain Concepts en Bilbao

PlainConceptsBlackLogoEn Plain Concepts estamos buscando para nuestra oficina de Bilbao, un desarrollador de software apasionado por .Net, con experiencia, pero sobre todo con capacidad y aptitud.

¿Qué harías en Plain Concepts?

Integrarte en un equipo de desarrollo que utiliza metodologías ágiles, que desarrolla diferentes tipos de proyectos utilizando metodologías ágiles siempre usando las últimas tecnologías. Además tendrás que impartir formación o ayudar a nuestros clientes presencialmente ocasionalmente. En Plain Concepts somos todo terreno, tenemos un equipo altamente multidisciplinar. No somos una ‘cárnica’, lo único que te garantizo es no vas a estar abandonado en un cliente sin saber quienes son tus compañeros. El resto depende de tus gustos y aptitudes.

¿Qué conocimientos valoramos especialmente?

Cualquier desarrollador de Plain Concepts es capaz de trabajar con soltura con las principales tecnologías del framework de .Net: ASP.Net, MVC, EF, WF, WCF, Silverlight, WPF, TFS, Azure, Blend… Esperamos además que tengas un nivel muy por encima de la media en alguna de estas tecnologías. Además deberías ser capaz de formar a otros y de transmitir los conocimientos que tienes. No esperamos que simplemente escribas código sino que tu código sea excelente, que participes en las decisiones de diseño, y que sepas plantear una arquitectura coherente. También deberías tener la capacidad de resolver problemas a nuestros clientes, no será en principio tu labor principal, pero si que esperamos que si es necesario puedas ayudar en labores de consultoría en aquellas tecnologías que domines.

Las certificaciones de Microsoft son bienvenidas, pero no imprescindibles.
En esta ocasión en concreto valoraremos especialmente que te manejes con mucha soltura con Silverlight y que manejes Blend.

¡Qué hablas inglés perfectamente! perfecto… así podrás colaborar con nuestra oficina de USA. Que no… mientras hables C# a nivel nativo y entiendas perfectamente documentación técnica… no pasa nada.

¿Qué aptitudes valoramos más?

Debes ser un jugador de equipo. Ser capaz de criticar constructivamente el trabajo de tus compañeros y estar abierto a recibir críticas sobre tu trabajo.
Tienes que tener interés constante por aprender y la capacidad de aprender rápidamente.
Tienen que apasionarte todas las actividad relacionadas con el desarrollo de software.
Tienes que tener capacidad de comunicación. Escribir un blog es un plus.
Si te gusta colaborar con la comunidad .Net mejor que mejor: eres habitual de un club de usuarios, has dado alguna charlita en la Universidad sobre .Net, eres un habitual de los foros de MSDN y ayudas a otra gente, etc…
Además puestos a elegir preferirías leer Silverligth in depth que Los pilares de la tierra.

¿Cómo será el proceso de selección?

Duro. Te va a entrevistar todo el equipo con el que vas a trabajar. Todos ellos con derecho a veto.
Es posible que queramos ver el código que escribes y algunas pruebas unitarias del mismo.
También sería un plus que nos sorprendieses con alguna aplicación de esas que todos hemos hecho alguna vez en nuestro tiempo libre por puro placer geek (una aplicación para gestionar la agenda de tu Nokia hecha en Mono, la web de la floristería de tu hermana, el backlog de la preparación de tu boda, el informe para TFS que dice quien es el que más días llega tarde al Daily de tu equipo, el pong en XNA…).

¿Me va a tocar viajar?

Ocasionalmente. El puesto que vas a ocupar ‘Software Development Engineer’ no debería exigir que este todo el día con la maleta, pero viajar no te debe importar demasiado.

¿Cuánto voy a ganar?

El sueldo que seas capaz de justificar, no tenemos un límite claro por arriba… ni por abajo. Este aspecto, dentro de lo razonable, no va a ser un problema. Si eres una autentico crack, lo sabremos valorar. Queremos a los mejores en nuestro equipo.

¿Y además de sueldo?

Vas a tener la oportunidad de formarte, de acudir a eventos organizados por Microsoft, de acudir a cursos de tu interés, etc…

¿Y el horario?

Pues el que mejor te venga, casi todos hacemos entre las 8:00 y las 18:00. Paramos a comer sobre las 13:30. Los viernes para las 15:00 nos solemos ir a casa. Nadie va a medirte por las horas que tu culo pasa en la silla, sino por tu capacidad para obtener resultados, cumplir tus compromisos y logra que nuestros clientes estén satisfechos.

¿Quién sería mi jefe directo?

Ibon Landa, Software Development Team Lead de Plain Concepts.
http://geeks.ms/blogs/ilanda
http://es.linkedin.com/in/ilanda

¿Cuándo tendría que incorporarme?

ASAP.

¿No os pasáis un poco pidiendo?

Es por tu bien, ¿no querrás ser el menos hábil de Plain Concepts? 😉

¿Puedo saber más de Plain Concepts?

En serio no sabes que existe Google… ;).
Pero no dudes en preguntar.

Tengo más preguntas, ¿qué hago?

Utiliza los comentarios del post para preguntar.

¿Y si prefiero contactar en privado o enviar mi currículo?

Escribe a rcorral at plainconcepts dot com, con el subject ‘Desarrollador Bilbao’.
El subject es importante, si no le pones bien, descartado, por no fijarte en los detalles ;).

Un saludo.

Videos de la Conferencia Agile Spain 2010

Ya están disponibles los videos de la Conferencia Agile Spain 2010.

En concreto podéis ver la ‘keynote’ de Henrik Kniberg autor de Scrum and XP from the trenches, que es más que recomendable. Un resumen de su interesante libro sobre Scrum y Kanban, Kanban vs Scrum, How to make the most of both, traducido al español por un grupo de miembros de Agile Spain, entre los que me encuentro.

El otro video es la sesión plenaria, una mesa redonda con pilares del agilísimo patri, introductores del agilísmo en la universidad… y un servidor haciendo el hooligan.

Un saludo.