viernes, 17 de diciembre de 2010

CodeRetreat de Zaragoza... allí estuvimos!

Después de un más que interesante Coding Dojo en Barcelona el pasado viernes, unos cuantos valientes con ganas de más nos íbamos al día siguiente al CodeRetreat de Zaragoza! Para el que no lo sepa, un CodeRetreat consiste, simplificando mucho, en juntarse un grupo de desarrolladores un día entero para programar (da igual el lenguaje, la experiencia... sólo importan las ganas) , en una serie de iteraciones de 45 minutos, una y otra vez el mismo ejercicio (normalmente el Juego de la Vida de Conway), por parejas, usando TDD e introduciendo una nueva restricción en cada una de las iteraciones. Además, por si no fuera suficiente, cada iteración se realiza con una pareja diferente! Viva la promiscuidad!! La verdad es que suena muy freak, y efectivamente lo es, sobretodo si se realiza a 300km de tu ciudad y tienes que levantarte a las 5:30 de un sábado para asistir! pero aparte de eso, es una manera excelente de aprender y mejorar, de conocer gente, de hacer networking y también de divertirse por supuesto!

Así que con muchas ganas y mucho sueño yo y Vicenç cogíamos al AVE las 7 de la mañana dirección Zaragoza. El resto de gente de Barcelona , Javier Gómez y su mujer (ingeniera informática que hace 4 años que no programa, y a la que según Javier había que devolver la sonrisa) iban en el siguiente tren!

Con el tiempo justo y gracias a que nos encontramos a Amalia (con quien habíamos colaborado en la organización delAOS2010) y a Jorge(alias Semurat) conseguimos llegar al peculiar "Water Pavillion", el lugar donde se iba a celebrar el evento.

Digital Water Pavillion

Más de 20 personas estábamos inscritas, y ya mayoría de gente ya había llegado y tenía los portátiles preparados cuanto entramos nosotros! Aparte de mucha gente de Zaragoza y los que íbamos de Barcelona había gente de diferentes lugares de la geografía Española, cómo Madrid, Valladolid, Valencia.. Únicamente tuve tiempo para saludar brevemente a Xavi Gost, que iba a ser el facilitador del evento, a Teresa Oliver (a quién también conocía de la organización del AOS2010 y una de las culpables de la realización del CodeRetreat) y a alguna persona más que conocía de haber asistido al mismo evento justo antes de que llegara los dos catalanes que faltaban y nos pusiéramos manos a la obra.

Después de una breve ronda de presentaciones, donde de se vio que había dos grandes grupos en lo que a lenguajes de programación se refiere (Java y .Net) Xavi nos explicó la dinámica del evento, básicamente la que he explicado arriba, nos explico las 4 reglas del juego de conway que había que implementar y nos dijo que empezáramos!

Antes de empezar


La primera iteración la hice con Vicenç, y después de los primeros 45 minutos, nos pensábamos que teníamos un código bastante bueno y bonito, ingenuos... Al acabar Xavi nos reunió y fue preguntó¡ando a la gente por sus impresiones, por cómo habían enfocado el problema, etc... Hubo un poco de todo,desde gente que había empezado a desarrollar en universo entero donde situar a las células del juego hasta gente que prácticamente no había hecho una sola línea de código. Hay que tener cuenta que mucha gente no había programado con TDD en su vida. A partir de ese momento y durante las siguientes iteraciones, Xavi nos iba poniendo nuevas restricciones a la hora de implementar los tests, por ejemplo:
  • No instanciar nada más allá de lo estrictamente necesario
  • Desarrollar el test dentro del propio test
  • Darle semántica al código (cómo ejemplo, la mayoría de le gente utilizaba una variable boleana para indicar si una célula estaba viva o no, y Xavi nos dijo que una persona cuando muere no está a "False"...)
  • ...
Al final hicimos unas 5 iteraciones, en las que tuve la oportunidad de tocar 3 lenguajes de programación (C#, Java e incluso Python!!) y de desarrollar con personas diferentes que tienen diferentes puntos de vista y diferentes maneras de buscar la solución, lo cual creo que es muy enriquecedor e interesante.

Después de la 5ª iteración y de una breve videoconferencia con Enrique Comba desde Londres (Enrique es uno de los firmantes originales del manifiesto por la artesanía del software, además de ser un asiduo facilitador de CodeRetreats) la gente estaba bastante cansada, y se decidió acabar con un pequeño reto a Xavi Gost: Seleccionamos una Kata que él no conocía y tenía que implementar la solución utilizando TDD, sin leerle el enunciado, únicamente a base de tests que Amalia le iba escribiendo! La kata elegida fue la de La Multiplicación a la Rusa, muy muy complicada para realizar con TDD puro y duro, así que hubo que darle alguna pista adicional a Xavi para que pudiera deducir la implementación!

Xavi Gost enfrentándose a "La multiplicación a la Rusa"

Con esto, y unas cervezas cortesía de los chicos de Masterbranch finalizaba "oficialmente" el CodeRetreat!! Y digo "oficialmente" porque el evento se alargaba para que los querían (o podían) con unas cervezas, cena y lo que surgiera! Lástima que nosotros nos tuvimos que volver esa misma noche!!

Cómo conclusión, aparte de las ganas y la motivación de la gente, el buen ambiente y el poder conocer a personas muy interesante (y volver a ver a las que ya conocía) , me quedo con la idea de que es necesario buscar la excelencia en nuestra profesión (cómo en toda profesión de hecho) y que esa búsqueda debe empezar por elevar el grado de auto-exigencia a nosotros mismos, y buscar siempre y de manera continua el ir mejorando poco a poco en todo aquello que hagamos (ya sea código o cualquier otra actividad).

Por suerte parece que empieza a haber cada vez más gente que comparte esa misma idea cómo se puede ver con los diferentes eventos que están surgiendo últimamente en diferentes lugares y de las diferentes comunidades (muchas de ellas ágiles) repartidas por el estado.

Para finalizar: muchas gracias a los organizadores, que hicieron posible este evento, a Xavi Gost por su facilitación y a todos los que asistieron por darme la posibilidad de poder aprender de ellos (especialmente a la gente con la que pude sentarme a desarrollar) y de conocerlos!!

Un saludo!!

PD: Dani Latorre ha recopilado una lista con muchas de las cuentas de twitter de los asistentes! Por si os falta alguna!!

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...

martes, 23 de noviembre de 2010

Diseño Ágil

El presente post está basado en las conclusiones e ideas que surgieron en la sesión del mismo nombre (Diseño Ágil) en el reciente Agile Open Spain 2010 de Barcelona. La sesión, egoístamente propuesta por mi (:P), tenía cómo objetivo el determinar aquellas técnicas o maneras de diseño que mejor pueden funcionar en equipos que trabajan de manera ágil, ya sea con Scrum o con cualquier otra metodología, aunque al final el tema se desvió un poco y se acabó hablando de algunas otras cosas, aunque todas ellas muy interesantes!

Se empezó hablando de la necesidad de eliminar los grandes diseños y arquitecturas iniciales para poder tener una mejor respuesta ante cambios en los requisitos o las necesidades del cliente, y para evitar el sobrediseño, algo que suele suceder muy a menudo. En su lugar se apuesta mas por un micro diseño o arquitectura inicial a alto nivel que permita a las personas que van a trabajar en el proyecto hacerse una idea general del mismo: los diferentes subsistemas que intervienen, como se relacionan entre ellos, etc. pero sin entrar en demasiados detalles. Este micro-diseño se realizaría en el Sprint 0, antes de empezar con el desarrollo de las diferentes funcionalidades del sistema.

A partir de aquí se empezaron a enumerar las diferentes técnicas que utiliza la gente desde el punto de vista del desarrollo para garantizar un buen diseño, por ejemplo:
La conversación, fue derivando entonces hacia la documentación, posicionándose la mayoría de la gente en que la mejor documentación es el propio código (o incluso los tests unitarios), y que documentar exhaustivamente los diseños puede tener un coste elevado, aunque también se aceptó que en ocasiones puede ser interesante que algunos diseños se documenten (por ejemplo con UML) de manera que todo el mundo pueda acceder a ellos, eso si, siempre y cuando esta documentación sea consistente con el código y no esté desincronizada. Una manera de conseguir esto, era tener una tarea en cada Product BackIog Item (o historia de usuario) del Backlog dedicada a ello.

El siguiente foco importante de discusión y comentarios, fue el decidir el momento adecuado de realizar el diseño y análisis técnico de cada historia de usuario. El consenso fue que el diseño de cada historia se debía realizar durante el proceso de estimación y división en tareas de esa historia, en la reunión de planificación de Sprint, momento en el cual el Product Owner está disponible para explicar la historia y aclarar cualquier posible duda que pueda surgir.

Se habló también de como integrar a los desarrolladores juniors o la gente nueva en el proceso de diseño, de manera que sus diseños no afecten o comprometan la calidad del trabajo de todo el equipo. Casi todo el mundo nombró Pair-Programming como la solución a este posible problema, y alguien habló que en su empresa utilizaban un sistema de mentoring, en el cual un desarrollador senior se "hacía cargo" de un junior, de manera que le supervisaba el trabajo, desarrollaban juntos, etc. durante un tiempo y éste último no empezaba a trabajar para un cliente hasta que llevaba un tiempo y ya sabía cómo debía de programar (tanto a nivel de calidad cómo de estilo, estándares, etc)

Hacía el final se empezó a hablar de que hacer con los requisitos no funcionales: seguridad, rendimiento, etc. Aquí hubo un poco más de discordia, ya que había gente que abogaba por intentar optimizar desde el principio y otras personas que preferían desarrollar sin tener muy en cuenta estos parámetros y después optimizar en función de las necesidades del cliente. Aunque casi todo el mundo opinaba que ahora la tendencia es desarrollar pensando mas en la mantenibilidad y en la escalabilidad que no en la optimización del detalle.

Cómo último punto, se trataron las revisiones de código., que todo el mundo consideró cómo necesarias. Enumero algunos de los métodos expuestos (además de Pair-Programming cómo revisión continua):
  • En una empresa utilizan una herramienta online (un plugin de JIRA creo) donde se registran posibles mejoras en un código que hace un "moderador". Posteriormente el moderador y la persona que ha realizado el código lo miran juntos y se buscan posibles soluciones y mejoras.
  • En otros lugares realizan sesiones de revisión, donde se junta todo el equipo y se realiza la revisión de un código.
  • En otra empresa de manera periódica hacen una reducción de código de cada proyecto, de manera que se intenta una especie de gran refactorización con todas las modificaciones hechas desde la última vez.
Seguro que salieron muchas mas ideas interesantes que me olvido o que no apunté en su momento, pero fue una sesión muy fructífera y muy entretenida debido al alto nivel de los asistentes y alto porcentaje de gente que participó con opiniones y ideas en la charla!

Espero que alguna de estas técnicas puedan servir de ayuda a equipos que estén intentado trabajar con metodologías ágiles, y si alguien tiene alguna idea o sugerencia sobre el tema, adelante!! Explicadnos cómo realizáis diseño vuestros diseños ágiles!!

Un saludo!!


martes, 16 de noviembre de 2010

ScrumMaster: ¿Parte o no del equipo?

Me ha parecido, en el último Agile Open de Barcelona escuchar en varias ocasiones frases similares a esta. En algunas sesiones, en los pasillos e incluso en alguna de las cenas he oído comentarios y opiniones dándole vueltas a esa idea. De entrada,creo que sería interesante re-formular la cuestión, ya que creo que lo que se intenta debatir no es si el ScrumMaster debe estar o no en el equipo (por supuesto!!) sino si además de sus funciones cómo ScrumMaster, debe también tener otras funciones dentro del equipo (desarrollo, testing, usabilidad...). La pregunta que yo lanzo es ¿ScrumMaster full-time o part-time?

Antes de dar mi opinión, veamos lo que dice el propio Jeff Sutherland sobre el rol en cuestión:

"The ScrumMaster helps the product group learn and apply Scrum to achieve business value. The ScrumMaster does whatever is in their power to help the team be successful. The ScrumMaster is not the manager of the team or a project manager; instead, the ScrumMaster serves the team, protects them from outside interference, and educates and guides the Product Owner and the team in the skillful use of Scrum. The ScrumMaster makes sure everyone on the team (including the Product Owner, and those in management) understands and follows the practices of Scrum, and they help lead the organization through the often difficult change required to achieve success with agile development. Since Scrum makes visible many impediments and threats to the team’s and Product Owner’s effectiveness, it is important to have an engaged ScrumMaster working energetically to help resolve those issues, or the team or Product Owner will find it difficult to succeed. Scrum teams should have a dedicated full-time ScrumMaster, although a smaller team might have a team member play this role (carrying a lighter load of regular work when they do so). Great ScrumMasters can come from any background or discipline: Engineering, Design, Testing, Product Management, Project Management, or Quality Management."

Leyendo el párrafo anterior, la respuesta a la pregunta sería: Depende!! Si puedes permitírtelo, ten un ScrumMaster full-time, sino puedes porque tú equipo o organización es demasiado pequeño, usa a un miembro del equipo a modo part-time (aunque eso sí, aligerando su carga de trabajo en otras responsabilidades). Ahora bien, ¿porqué sería interesante tener un ScrumMaster full-time?

La responsabilidad del ScrumMaster es, entre otras cosas, encargarse del proceso (sí, ya se lo que pone en el Manifiesto Ágil, pero no se me ocurre otra manera de expresarlo!!) El equipo debe "hacer" algo (un producto, un proyecto...) utilizando eso proceso y el ScrumMaster debe encargarse de observar cómo lo hacen, ver como el equipo avanza, e intentar ayudarles a mejorar. Sería algo así cómo si el equipo fuera dando pequeños saltos hacia un punto mientras el ScrumMaster observa cada uno de esos saltos e intenta que el equipo aprenda a saltar mejor cada vez. Pero para que esta observación sea efectiva, es necesaria cierta neutralidad.Se debe poder mirar el proceso con un poco de perspectiva para poder obtener información objetiva sobre el mismo. Si el ScrumMaster es parte del equipo, puede perder la perspectiva, su visión puede quedar sesgada ya que su foco se está centrando también en producir (multitasking?) y la mejora continua necesaria en todo equipo Scrum es probable que sea menor.

Esto seria lo ideal, pero, cómo hemos leído en la definición de Jeff Sutherland, es posible que en equipos o organizaciones demasiado pequeñas un ScrumMaster no tenga suficiente volumen de trabajo para ejercer ese trabajo full-time. Además, muchas organizaciones dedicadas al desarrollo de software seguramente no estén aún preparadas para tener a una persona "que no produce" (nótese la ironía) a tiempo completo.

¿Entonces que hacemos? Scrum es una metodología de inspección y adaptación. Empecemos con lo que tenemos, y mantengamos la visión ideal del ScrumMaster full-time en el horizonte y, aunque es posible que nunca se llegue a completar, intentemos trabajar en esa dirección. ¿Cómo? Que varios equipos compartan SM, haciendo que el ScrumMaster sea una persona de otro equipo... o con otras opciones mucho mas creativas que las que se me ocurren ahora mismo a mi.

Como nota final, apuntar que aún más importante que decidir si el ScrumMaster es full-time o no, es escoger al candidato correcto. ¿Y quien es el candidato correcto? Pues sencillamente aquel que tiene los skills necesarios! Os remito a un interesante artículo de Xavier Albaladejo sobre el tema: "El buen gestor de un equipo ágil".

¿Que opináis? ¿Debería ser el ScrumMaster un rol full-time?¿O mejor un miembro del equipo?¿Puede llegar a trabajar sin ScrumMaster un equipo?

Espero vuestras opiniones! Un saludo!





domingo, 14 de noviembre de 2010

Se acabó el AOS 2010!

Ha finalizado el Agile Open Spain 2010. Ha sido mi primera asistencia a un evento en formato Open Space y las sensaciones han sido inmejorables. Mas allá de la calidad de las sesiones a las que he asistido (que difícil ha sido elegir entre las numerosas propuestas de los asistentes), con lo que me quedo es con las ganas y la energía que que han mostrado todos los asistentes que han hecho el esfuerzo de acercarse a Barcelona desde diferentes lugares de España, Europa e incluso algunos del otro lado del charco, para compartir con todos sus opiniones y experiencias en esto que llamamos Agilismo. A lo largo de los casi dos días del evento, he tenido el placer de escuchar, charlar y discutir ideas y opiniones con mucha gente, algunas con verdaderos expertos en metodologías ágiles y otras con gente que se acercaban por primera vez a ellas, pero todas han sido igual de enriquecedoras.

Sesiones técnicas, sesiones sobre gestión de proyectos (o Project Support cómo prefiere llamarlo Alan Cyment...) e incluso sesiones que podríamos considerar algo así cómo teórico-filosóficas... :P de todas ellas me llevo cosas para reflexionar e intentar mejorar tanto a nivel profesional cómo personal. Más adelante intentaré concretar alguna de estas ideas en siguientes posts.

Espero que este evento sea un punto y seguido que ayude a la comunidad Agil Española a seguir creciendo y consolidándose, utilizando para ello, quizás, algunos de las propuestas surgidas en la Retrospectiva del evento (facilitada de manera magistral por Ariel Ber a quién desde aquí doy las gracias por su colaboración y ayuda durante todo el evento), cómo por ejemplo la realización de eventos Open Spaces a escala local, la realización de eventos temáticos o sobretodo la propuesta estrella de la noche: fomentar el agilismo entre las mujeres!!

Cómo punto final, dar las gracias a todos los que han hecho posible este evento: los patrocinadores del evento (en especial al patrocinador oro Plain Concepts), a la gente de la organización, a la asociación agile-spain y sobre todo, y aquí me repito, a la gente que ha hecho el esfuerzo de acercarse al evento, ya que sin la gente no hubiera sido posible realizarlo!

Os dejo una foto de la configuración de la agenda, totalmente autoogenerada entre todos los que asistimos al evento!



Un saludo, y espero volver a coincidir con muchos de los que habéis estado en el AOS (no pongo nombres porque seguro que me dejo a gente) y sobretodo espero ver a mucha gente nueva en próximos eventos. Para empezar en el xp2011 en Madrid!!


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.

miércoles, 27 de octubre de 2010

Entrenando tu código

Kata (型 o 形) es un término Japonés utilizado, normalmente en el ámbito de la artes marciales, para describir una serie de ejercicios o movimientos preestablecidos que pueden practicarse sin rival y sirven al practicante como entrenamiento para aumentar sus capacidades. Es, de la misma manera que en otras disciplinas como la música, a través de la repetición continua y rigurosa de estos ejercicios la única manera en la que el estudiante puede llegar a dominar la técnica en su máximo nivel, además de llegar a comprender el espíritu del arte marcial en cuestión.

De la misma manera que los practicantes de artes marciales, los desarrolladores también tenemos formas de entrenar nuestras capacidades, y una de las mejores son las Katas de Código. Estas consisten en el planteamiento de diferentes problemas que tenemos que intentar resolver de la mejor manera posible. Cómo en las artes marciales, la práctica y la repetición de este tipo de ejercicios nos permiten mantener nuestras capacidades al máximo nivel. Hay que tener en cuenta que lo mas importante no es la resolución del problema, si no el proceso que lleva a la resolución del mismo.

Gracias a este tipo de ejercicios se persigue obtener una excelente base técnica, que nos permita enfrentarnos a problemas en proyectos reales con una alta garantía de éxito y centrándonos mayoritariamente en el dominio del problema y no en los aspectos técnicos del mismo.

Las katas de código pueden ser de diferentes tipos y naturaleza (algoritmos, matemáticas, modelado, centradas en tecnologías, de refactorización...) y de diferentes niveles de dificultad.

Algunos sitios web donde se pueden encontrar Katas son:

http://codingkata.org/

http://codekata.pragprog.com/

http://codingdojo.org/cgi-bin/wiki.pl?KataCatalogue

Ya podéis empezar a entrenar vuestro código!!

Un saludo!!

domingo, 26 de septiembre de 2010

Reestimando historias

Suele pasar en ocasiones que finalizar alguna historia de usuario nos lleva mucho mas tiempo del que a priori podíamos esperar. Esta situación suele llevar a la pregunta de si se debe reestimar o no la estimación hecha para esa historia de usuario. En este post vamos a tratar de explicar en qué situaciones se debe reestimar y en cuales no, basándonos en lo explicado por Mike Cohn en su libro Agile Estimating And Planning

Para ello vamos a ayudarnos de un ejemplo. Imaginemos que tenemos las siguientes historias de usuario en el backlog:


IDHistoriaEstimación
1Historia A3
2Historia B5
3Historia C3
4Historia D3
5Historia E3
6Historia F5


Supongamos que que las historias A, B y C tienen todas que ver en en cuanto a tamaño y complejidad ya que lidian con el mismo tipo de tecnología (por ejemplo una integración con un sistema externo mediante servicios web). Revisando las historias el equipo decide incluir en cada sprint las siguientes historias:

Sprint 1
Historia A 3
Historia B 5
Historia F 5
Sprint 2
Historia C 3
Historia D 3
Historia E 3

Al finalizar el primer sprint únicamente se ha completado la historia A y la F, es decir un total de 8 PH. El equipo sabe que la historia A es el doble de compleja que lo que habían estimado, así que tienen que decidir que hacer con las estimaciones de la propia historia y de las historias similares (B y C)

1. No reestimar

Si deciden no reestimar ninguna de las 3 historias, para el siguiente sprint deberían, en principio seguir con las historias B y C, que son un total de 8ph. Debería ser suficiente ya que en el último sprint es exactamente la cantidad de puntos conseguidos, pero el equipo sabe que las historias B y C pueden llegar a ser el doble de complejas que lo inicialmente estimado, así que aunque el total de ph sea 8, el equipo no conseguirá terminarlas en un sprint.

Velocidad estimada: 8PH

Sprint 1
Historia A 3
Historia F 5
Sprint 2
Historia B 5
Historia C 3
Sprint 3
Historia D 3
Historia E 3

Probablemente no se llegue a finalizar el Sprint 2, debido a que las historias B y C pueden ser el doble de grandes.

2. Reestimar únicamente la historia finalizada

Si se decide reestimar la historia finalizada, con por ejemplo el doble de puntos (6 en lugar de 3), el total de puntos del sprint queda en 11 ph. Esto seria suficiente para terminar en el sprint 2 las historias B, C y D. Sin embargo sabemos que las historias B y C pueden llegar a ser aproximadamente el doble de grandes de lo estimado inicialmente, con lo cual es muy probable que el equipo no pueda finalizar los 11ph de historia estimados para el siguiente sprint.

Velocidad estimada: 11PH
Sprint 1
Historia A 6
Historia F 5
Sprint 2
Historia B 5
Historia C 3
Historia D 3
Sprint 3
Historia E 3

Probablemente no se llegue a finalizar todo el sprint 2, debido a que las historias 2 y 3 pueden ser el doble de grandes

3. Reestimar las historias relacionadas entre si.

Si la reestimación se hace para las 3 historias relacionadas (la finalizada A, la B y la C), se consigue aumentar la velocidad del equipo hasta 11ph, pero ademas aumenta el tamaño del trabajo pendiente. En el siguiente sprint el equipo estaría preparado para abordar las historia B, que ahora vale 10ph, la C y la D en el tercer sprint (6ph + 3ph) y la E en el cuarto sprint.


Velocidad estimada: 11PH

Sprint 1
Historia A 3
Historia F 5
Sprint 2
Historia B 10
Sprint 3
Historia C 6
Historia D 3
Sprint 4
Historia E 5

La reestimación de todas las historias relacionadas nos permite obtener la planificación más exacta, aún a costa de ver cómo esta sobrepasa la inicialmente prevista. No reestimar o reestimar únicamente las historias finalizadas para obtener una mayor velocidad por sprint solamente consigue ocultar el retraso hasta los siguientes sprints, evitando así una de las ventajas de las metodologías ágiles : conseguir información por adelantado que nos permita tomar decisiones de manera temprana en el tiempo.

A modo de resumen:

  • No se deben estimar las historias finalizadas con el objetivo de aumentar la velocidad por sprint.
  • Se deben reestimar las historias cuyo tamaño y complejidad relativa hayan cambiado respecto al inicio de las estimaciones.


miércoles, 16 de junio de 2010

Cas 2010 - Día 2

Con el cansancio acumulado del primer día pero con muchísimas ganas daba comienzo el segundo día de la conferencia.

Para empezar, uno de los platos fuertes de la conferencia: una mesa redonda de expertos donde se debatiría sobre el actual estado de las metodologías ágiles en España. Con participación de representantes de la industria, de la universidad y con algunos conocidos agilistas de la comunidad (Ángel Medinilla, José Manuel Beas y Xavier Quesada), lo que pretendía ser un apasionado debate, se quedó en algo un poco más descafeinado, debido a la poca controversia y diferencia de opiniones entre los ponentes. Por otra parte,me sorprendió gratamente ver que desde la Facultad de Informática de Madrid (FIUPM), teniendo en cuenta que la universidad es una institución eminentemente waterfall, se está apoyando y se está colaborando fuertemente en diferentes programas y de diferentes formas las metodologías ágiles.

En cuanto a las sesiones, igual que el primer día todas fueron de un gran nivel. En esta segunda jornada me centré más en sesiones a nivel de gestión o metodología y no tan centradas en prácticas de ingeniería, asisitiendo a Gestión de Ágil de Equipos e Itinerario de Implementación Ágil en la Empresa( Angel Medinilla) , Gestión ágil de requisitos (José Luis Soria), Prácticas recomendadas para la relación Cliente-Equipo... (Juan Garbajosa y Agustín Yague) y Diez maneras infalibles de asesinar Scrum (Rodrigo Corral).

Todas ellas excelentes, aunque me quedé con ganas de asistir a la sesión de Fórmula-1 y a la de TDD, pero la imposibilidad de dividirme en 2 personas, me obligó a tener que elegir unas y descartar otras!

Para finalizar, una sesión de retrospectiva, donde los asistentes podíamos decirle a la organización aquellas cosas que considerábamos se podían mejorar, aquellas que no nos habían gustado y claro está, las que se habían echo bien!! Una gran manera de involucrar a los asistentes a la vez que de intentar mejorar para futuras ediciones!

Como conclusión final, una gran conferencia, que ha sido todo un éxito tanto de asistencia como de contenidos (a mi juicio). Es estimulante saber que hay mucha gente que comparte las mismas inquietudes profesionales que tú, y es de esperar que eventos de este tipo ayuden a difundir el mensaje de que las metodologías ágiles pueden ayudar a las empresas que desarrollan software, no sólo, a ser más productivas y competitivas, sino a hacer del trabajo algo mas sostenible, motivador y ¿por qué no? , divertido!!

Un saludo!!



jueves, 10 de junio de 2010

CAS 2010 - Día 1


Hace poco más de 3 horas que ha finalizado la primera jornada de la conferencia agile-spain 2010, y sin necesidad de esperar a la segunda creo que se puede afirmar que va a ser todo un éxito. La asistencia ha sido muy alta (incluso se ha tenido que quedar gente fuera de la conferencia por problemas de aforo) lo que demuestra que el movimiento ágil está empezando a irrumpir con fuerza entre todos aquellos dedicados al mundo de las tecnologías de la información.

Resumiendo un poco este primer día, el plato estrella del día ha sido la KeyNote a cargo de Henrik Kniberg, sin duda una de las personas más relevantes del mundo en la divulgación de las metodologías ágiles, cosa que se puede entender viendo la soltura con la que se ha movido en el anfiteatro donde se llevaba a cabo la presentación. Henrik se ha metido al público en el bolsillo desde el minuto 0, y no lo ha dejado ir hasta el final, mientras iba explicando, de forma muy amena, conceptos de Scrum, Kanban o Xtreme Programming (a nivel introductor eso si). Sin duda alguna un gran inicio para la conferencia.

Después de la KeyNote han empezado los talleres y sesiones de la conferencia. La selección ha sido dura, pero finalmente he presenciado aquellas sesiones que creo que más me pueden ayudar en mi trabajo diario. Entre ellas ha habido sesiones relacionadas con prácticas técnicas, BDD o Diseño guiado por comportamiento, como montar un entorno completo de Integración Continua o una sesión (de nivel muy básico eso si) sobre buenas prácticas de desarrollo. Por otro lado he presenciado una sesión sobre como enfocar la implantación de Scrum en empresas grandes, y otra muy interesante sobre métricas y control de proyecto con metodologías ágiles.

Todas las sesiones han sido de un gran nivel y todos los ponentes lo han hecho estupendamente.

También la organización ha realizado un gran trabajo, e incluso haciendo honor al lema de que los cambios son bienvenidos en la agilidad, se ha solventado un problema de aforo en una sala (que era demasiado pequeña la verdad) realizando en poco minutos un traslado a otra sala mucho mas grande. Chapeau!!

Para resumir, algunas de las ideas con las que me quedo, para intentar mejorar en la implantación de Scrum de mi empresa:
  • Tener un Product Owner que haga bien su trabajo es condición, casi indispensable para que una metodología ágil funcione.
  • Las estimaciones de tareas a desarrollar mejoran, a medida que el número de personas implicadas en la misma aumenta.
  • Las estimaciones NO SON CONTRATOS!! Son inciertas y hay que aprender a vivir con ello.
  • Haz las cosas simples (KISS, Don't repeat yourself, YAGNI...). Que sea simple no quiere decir que sea fácil.
  • Necesitamos métricas explícitas para controlar los proyectos. Las métricas cuestan dinero. Minimiza el trabajo para conseguir las métricas que necesites.
Hay muchas más cosas, pero son demasiadas ideas para plasmarlas aquí, y además mañana continuamos con otro buen montón de sesiones, que a buen seguro van a se interesantísimas!

Esperemos que este tipo de eventos ayuden a difundir la cultura del agilismo en nuestro país, y que la gente involucrada de una manera u otra se den cuenta de que hay una manera mucho más sostenible, rentable, lógica e incluso divertida de llevar a cabo los proyectos tecnológicos.


jueves, 6 de mayo de 2010

Programa CAS2010

Como ya anunció mi amigo Vicenç en Haciendo realidad la agilidad, los días 10 y 11 de Junio se celebra en Madrid la primera conferencia sobre métodos ágiles en España, con el reclamo de Henrik Kniberg como ponente principal del evento.

Pues bien, ya se ha hecho público el programa de la conferencia, donde además del mencionado Kniberg se van a dar cita algunas de las figuras mas importantes a nivel nacional dentro del movimiento de desarrollo y metodologías Ágiles cómo Angel Medinilla, Xavier Quesada, Rodrigo Corral o Xavier Albaladejo entre otros y donde podréis escoger entre sesiones y talleres de todos los gustos y colores.

Os recomiendo encarecidamente a todos los que tengáis algún tipo de interés o relación con las metodologías ágiles que no dudéis en pasaros por allí porque va a ser una gran oportunidad de aprender de la mano de los que más saben del tema, además de una gran oportunidad para intercambiar experiencias y conocimientos. Ahora el verdadero problema va a ser elegir entre tanta sesión de calidad!

Un saludo y nos vemos en Madrid!!

PD: Viendo el alto nivel de los ponentes no es de extrañar que mi propuesta de sesión sobre integración continua no haya pasado el corte (de todas maneras lo volveré a intentar el año que viene).

martes, 23 de marzo de 2010

Tratando con Bugs en Scrum

¿Se deben o no se deben estimar los BUGS usando Scrum? Nos preguntábamos hace unos días en el trabajo esta cuestión, sin llegar a tener claro cual debe ser el enfoque a utilizar para introducirlos de manera fluida en el ciclo de Scrum.

Durante mucho tiempo he defendido la idea de que los Bugs debían ser tratados cómo si fueran nuevas historias de usuario, , añadiendolos al backlog y realizando su correspondiente priorización y estimación en Puntos Historia. Esto funciona razonablemente bien si los Bugs detectados no son los suficientemente críticos cómo para poder esperar al siguiente Sprint para corregirlos, pero no es un buen método cuando los Bugs tienen que ser arreglados ya.

Además este enfoque presentaba algunos problemas teóricos relacionados con la metodología, a saber:

  • Estimación de un bug, implica contabilizar dos veces el mismo trabajo (uno cuando se estima la historia, y otro cuando se estima el trabajo para arreglar lo que se ha hecho mal en la historia)
  • Estimación en Scrum se utiliza para contabilizar el valor (relativo) que cada funcionalidad aporta al cliente, cómo los Bugs no aportan valor (más allà de solucionar un error cometido por nosotros mismos) no deberian estimarse.

En cambio, creo que el enfoque correcto (o el que a mi me gusta más) es el de tratar los Bugs como “tareas adicionales” dentro de la historia donde se ha generado.

Usando este enfoque, la estimación de la historia no varía, pero si que variará el tiempo dedicado a finalizarla, poniendo de relieve el impacto de los mismos en aquellas historias donde se producen y consiguiendo que la velocidad del equipo no sea un dato falseado (hacer muchos puntos en cada Sprint, pero teniendo que arreglar muchas de las historias en el/las siguiente/s iteraciones). Cómo consecuencia de esto, al tener más consciencia sobre el impacto de los Bugs en las historias implementadas, se puede lograr una disminución importante en los defectos de futuras iteraciones.

¿Cuál os parece a vosotros el enfoque mas adecuado? ¿Qué otro tipo de enfoque utilizáis para tratar los defectos ? Espero vuestros comentarios y aportes.


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í.