Una de las mejores maneras de desarrollar software es utilizar una metodología Iterativa e incremental. En las metodologías tradicionales el equipo de desarrollo entrega el software completo al cliente tras la programación de todos los requisitos solicitados por el cliente. Esto tiene un grave inconveniente y es que el cliente no ve la aplicación hasta que este terminada y en ese caso puede gustarle o no.
En las metodologías iterativas e incrementales, el equipo de trabajo desarrolla pequeñas porciones de la aplicación y las va mostrando al cliente en intervalos de tiempo establecidos de antemano. Estos periodos de tiempo/trabajo se llaman iteraciones y pueden agruparse en Releases.
Una Release es una versión de la aplicación que recoge un conjunto de funcionalidades determinadas. Evidentemente el cliente necesitará que todos los requisitos de la aplicación que nos ha solicitado estén implementados, pero no necesariamente tienen que estar todos implementados a la vez. Podemos acordar con el usuario liberar versiones de la aplicación en diferentes fechas que recojan parte de los requisitos totales de la aplicación.
Esta manera de trabajar tiene muchas ventajas:
Todas estas características y ventajas nos han llevado a elegir este tipo de Metodología para MEDEA y dentro de las metodologías iterativas e incrementales hemos escogido Scrum en particular.
Scrum es una metodología ágil de gestión de proyectos que implementa el paradigma de desarrollo iterativo e incremental y que se está utilizando en ÁTICA desde el año 2009 por parte de algunos grupos de trabajo y que nos ha probado suficientemente su utilidad. Es por esto que hemos decidido adoptarlo oficialmente en MEDEA.
Si quieres conocer como funciona Scrum puedes consultar el libro Scrum y XP desde las trincheras donde se da un ejemplo de cómo trabaja Scrum. Aquí vamos a dar una visión muy rápida de cómo utilizarlo en nuestros proyectos.
Como no se trata aquí de hacer un curso completo de Scrum vamos a centrarnos en el trabajo en una iteración. Para empezar incluiremos algunas definiciones.
Cada sprint comienza con una reunión de planificación del sprint. En ella se deciden las historias que van a desarrollarse durante el sprint, las fechas de comienzo y finalización del sprint y el equipo de trabajo.
Antes de comenzar esta reunión hay que preparar lo siguiente:
Los participantes en esta reunión son:
En primer lugar el jefe del proyecto determina la duración del sprint, fecha de comienzo, fecha de fin y fecha de demostración de sprint.
Una vez determinada la duración del sprint el jefe de proyecto calcula la velocidad. La velocidad es el sumatorio, para cada uno de los miembros del equipo, del número de días que van a trabajar durante el sprint, considera posibles ausencias, el tanto por ciento de decicación al proyecto, es preferible que sea el 100%, y su rendimiento. Rendimientos de experto son del orden de .75 y de programadores junior de .5.
Conocida la velocidad del sprint debemos estimar las historias en el orden en que determine el product owner. Para estimar cada historia se establece un diálogo entre el product owner y el equipo de trabajo hasta que el equipo consigue saber lo que demanda el product owner. Una vez lo tienen claro, el equipo descompone la historia en tareas y estima individualmente cada una de las tareas. La estimación de cada tarea se realiza mediante el Scrum poker. Cada uno de los miembros del equipo tiene un mazo de cartas con distintas puntuaciones. Una vez discutidas entre los miembros del equipo las características de la tarea, cada uno de ellos coloca en la mesa una carta boca abajo. Cuando todos han depositado su carta, se vuelven boca arriba. Este juego se repite hasta que todos los miembros del equipo están de acuerdo en una determinada estimación para la tarea.
Esto se va repitiendo con cada una de las historias y de las tareas hasta que la suma de las estimaciones de las tareas alcanza la velocidad del equipo para el sprint. Si se sobrepasa la velocidad es el product owner el que debe priorizar que entra y que no entra en el sprint, pero nunca se debe asumir más trabajo del que marca la velocidad.
Una vez se tiene claro las historias/tareas que componen el sprint, se prepara una pizarra o un tablón con tres columnas, la primera para las tareas propuestas, la segunda con las tareas que están realizandose en un momento dado y por último otra con la tareas que ya se están realizando. Durante el sprint las tareas van moviendose de izquierda a derecha según van asumiendolas los distintos miembros del equipo y van resolviéndolas. Además se prepara una gráfica en la que se situan en el eje de ordenadas la velocidad del sprint y en el de las abscisas los días de trabajo del sprint. Se une con una línea roja el punto (0,velocidad) con (último día, 0). Esta línea nos marca el ritmo ideal de trabajo del equipo.
Cada mañana, el equipo de trabajo se reune, y cada uno de los miembros del equipo realiza lo siguiente:
Esta reunión no debe durar más de 10-15 minutos. Al finalizar el jefe de proyecto dibuja en la gráfica, para el día correspondiente, un punto con los puntos de historia que todavía faltan para finalizar y une este punto con el del día anterior. Si la línea resultante está situada por encima de la línea que marca el ritmo ideal es que el equipo va más lento de lo previsto. Si la línea va por debajo es que el equipo va más rápido de los sugerido.
Al finalizar el sprint, el equipo de trabajo organiza una presentación para el cliente y otros grupos de trabajo de ÁTICA en el que muestra lo realizado durante el sprint. Lo que se muestre debe ser software “funcionando”, nada de presentaciones, y debe ajustarse a lo planificado en la reunión de planificación de sprint.
Básicamente esta es la manera en que Scrum gestiona una iteración. En un proyecto determinado tendremos tantos sprints como sea necesario.
Lo que hemos explicado en el apartado anterior nos ha servido de muestra de como trabajaremos con Releases e iteraciones en un proyecto software. El software responderá a una serie de requisitos propuestos por el usuario/cliente. Los requisitos serán tanto de producto como de proyecto. Agruparemos estos requisitos en releases, de manera que tendremos distintas versiones de la aplicación desarrollada que comprendan subconjuntos de requisitos de la aplicación. Lo normal es que en cada release las funcionalidades de la aplicación sean cada vez mayores, hasta que en la última release estén implementados todos los requisitos solicitados por el cliente/usuario.
A su vez, para conseguir desarrollar todo el software necesario para una release dividiremos el trabajo en iteraciones. Al final de cada una de las iteraciones estamos obligados a tener software funcionando, para evitar perdernos por las ramas, lo cual no significa que tenga que ser software que vaya a ser puesto en producción.
La división de los requisitos en release e iteraciones es tarea del Product owner o responsable del producto o cliente, como queramos llamarlo. A nosotros, como equipo de desarrollo debe darnos igual. Únicamente debemos procurar que al comienzo del proyecto se implemente aquellas historias que nos permitan montar la arquitectura necesaria para el proyecto, pero a partir de ahí ¿a tí que más te da?.
Como hemos repetido ya varias veces el objetivo de una release es tener software en producción, por tanto, no es suficiente para liberar una release con codificar los requisitos. Al tratarse de software que va a estar en producción ha de someterse a los oportunos controles de calidad. Debes ser consciente que, además de codificar la aplicación debes:
Una vez hayas realizado todos los controles de calidad necesario, pruebas funcionales, de rendimiento, de usuario, haber realizado material de ayuda e impartido formación a los usuarios, sólo entonces estás en condiciones de liberar la release.
El objetivo final de una iteración es tener software funcionando, por tanto no basta con la codificación. Además del trabajo de codificación debemos realizar test unitarios de los componentes software que desarrollemos. Esto nos permitirá desarrollar un software de calidad. Además la utilización de un servidor de integración contínua como Jenkins nos permitirá ejecutar automáticamente todos los test unitarios y saber si hemos “estropeado” algo durante el desarrollo/modificación de los nuevos componentes.
Como ya hemos visto la división del trabajo de desarrollo del software en iteraciones y release nos permite mejorar la comunicación con el usuario, de manera que el usuario ve rápidamente el software que estamos desarrollando y puede indicarnos mejor cualquier modificación.
La otra gran ventaja de este tipo de desarrollo es que las “unidades de planificación” son mucho menores en tamaño que un proyecto completo, por lo que las planificaciones que se realicen son muchos más precisas que en un proyecto tradicional. Además esta manera de trabajar nos permite acomodarnos a las posibles desviaciones de las planificaciones, replanificando tras cada iteración.
En este tipo de proyectos, las planificaciones se pueden hacer a dos niveles, a nivel de iteración y a nivel de release.
El proceso de planificación a nivel de iteración es tal y como lo hemos contado más arriba en el apartado Desarrollo de la reunión de planificación de sprint.
Al final de este proceso, lo que se tendrá es una fecha de finalización de sprint y un conjunto de características/requisitos/historias o como queramos llamarlo a desarrollar.
Otra manera de planificar iteraciones es determinar de antemano los requisitos que comprenderá la iteración y en función de la velocidad del equipo determinar la fecha de finalización de la iteración.
La experiencia nos ha demostrado que es mejor la primera opción, pero nada impide utilizar la segunda. En cualquier caso, la planificación de un sprint supondrá especificar:
La planificación de una release no difiere sustancialmente de la planificación de una iteración, la mayor diferencia que existe entre una y otra es la precisión con que podemos hacerlo.
Para planificar una release seleccionaremos también un conjunto de historias, definiremos un equipo y su velocidad y estimaremos las historias. Como, evidentemente el conjunto de historias es mayor que en una iteración, el detalle con que podremos examinarlas es menor. Por ello, no dividiremos las historias en tareas, sino que las estimaremos globalmente. Evidentemente esto es menos preciso.
Para paliar esta falta de precisión lo que haremos es para cada historia realizar tres estimaciones:
De esta manera al final de la planificación de la release no tendremos una fecha de finalización de la release, tal y como sucedía en las iteraciones sino que tendremos hasta 4 fechas.
De esta manera al final tendré un rango de fechas con las que trabajar. Ya sé que no es tan preciso como otras cosas, pero ¿no te parece más realista?.
Nada nos impide agrupar las historias en iteraciones, de manera que no sólo tendré las fechas estimadas de la release, sino que estimaré las fechas de cada iteración y las historias que entrarán en cada iteración.
Por último, podemos corregir la planificación de la release según vaya avanzando el proyecto. Podemos sustituir, al final de cada iteración, los esfuerzos estimados por los esfuerzos reales y las historias planificadas para un determinado sprint por las historias que hemos desarrollado en el sprint realmente. De esta manera realizamos un seguimiento durante todo el proyecto que nos permite tener un mayor control sobre él y tomar decisiones más ajustadas a la realidad del proyecto durante todo el ciclo de vida.