archivo

Archivo de la etiqueta: extreme programming

Resulta muy tentador comenzar una primera iteración prácticamente desde que se ha dado el pistoletazo de salida al proyecto.

Depende del proyecto, efectivamente. Si se trata de un nuevo aporte económico a otro ya existente y el equipo ha permanecido más o menos estable (tanto por parte de los desarrolladores como de los usuarios) casi que se puede empezar desde el principio, salvo que la evolución a realizar requiera hacer una revisión de la visión que se tenía del producto hasta la fecha y de lo que se preveía que iba a ser su devenir.

Sin embargo, para nuevos desarrollos, para evoluciones significativas de un sistema o para cambios significativos en el equipo de personas que intervienen en el mismo, es necesario hacer una parada para construir una imagen mental de lo que se quiere y que se traducirá en entradas en la pila de producto (que luego se refinará y mejorará conforme vaya avanzando el desarrollo y todas las partes vayan aprendiendo más y más porque las ideas al materializarse y cobrar forma requerirán ajustes y sugerirán algunos cambios de enfoque).

Esta etapa se llama exploración en XP y me parece acertada su denominación, ya que además, contempla la posibilidad de evaluar la tecnología y productos a utilizar durante el proceso de desarrollo.

Ahora bien, esta etapa no debe eternizarse y no conviene traspasar la frontera entre lo que es saber qué es lo que se quiere y obtener un análisis de requisitos detallado (digo que no conviene porque cada proyecto es diferente y tenemos que estar abierto a excepciones) porque de lo contrario habremos invertido (probablemente) esfuerzo que no va a retornar en beneficios, ya que todos sabemos que en el momento en que el usuario empiece a ver producto construido empezará a modificar las bases establecidas.

Tener una visión del producto es otro factor más para desarrollar con intención ya que permite tanto por parte del usuario como por la nuestra tener en cuenta más factores y esto se consigue viendo el producto y los problemas desde una escala más amplia.

Recomiendo la lectura del artículo: Preparando el primer sprint.

Supuestamente dentro de un proyecto de desarrollo de software todo el equipo tiene acceso al código que se está desarrollando y, por tanto, se podría considerar que existe una propiedad colectiva del mismo, sin embargo esa apreciación es más teórica que real, porque lo que suele suceder es que los desarrolladores pongan reparos en que otros toquen lo que han construido. Somos así, ¿qué le vamos a hacer?.

Considero un acierto por parte de XP que considere como práctica la propiedad colectiva del código, es decir, que se fomente que cualquiera pueda trabajar y mejorar con cualquier sección del código la hubieran desarrollado ellos o no. Y no lo comento solo por motivo de dar una mayor flexibilidad o disponibilidad al equipo, sino porque otro punto de vista generalmente suele ser positivo (por eso ese mismo enfoque de desarrollo tiene entre sus recomendaciones la programación por pares).

Para que este concepto se aplique de manera efectiva en un proyecto es fundamental el respeto. En el momento en que se pierden las formas por la solución en que una persona ha realizado un desarrollo, se empiezan a levantar muros. Y es que es fácil reirse o llevarse las manos a la cabeza por determinadas codificaciones pero realmente haríamos lo mismo si revisásemos código nuestro construido hace años (o tal vez no desde hace tanto tiempo).

También es importante no olvidar que se tiene que desarrollar con intención con propiedad colectiva o sin propiedad colectiva, es decir, no se trata de ponerme a retocar tal o cual funcionalidad o a refactorizar tal o cual clase o módulo, sin un propósito o poniendo en riesgo los compromisos que el equipo ha pactado para el sprint.

Kent Beck, creador de la metodología de programación extrema, realiza en su libro “Extreme Programming Explained” la siguiente reflexión (traducción libre):

“El problema (de los proyectos de desarrollo de software) no es el cambio porque el cambio se va a producir; el problema, más bien, es la incapacidad de afrontar el cambio cuando se produce”.

Ahí, se encuentra desde mi punto de vista, una de los grandes problemas de los proyectos de desarrollo de software y es el hecho de no enfocarse desde el punto de vista de que las especificaciones iniciales van a cambiar, ya sea porque el usuario no ha trasladado adecuadamente lo que quiere, porque el equipo de proyecto no ha interpretado correctamente lo que se le ha pedido o porque los requisitos y/o las prioridades han cambiado.

No es realista afrontar un proyecto de esa manera y sin embargo está a la orden del día encontrarnos con desarrollos que no tienen previsto un mantenimiento y eso es un error tanto aplicando metodologías ágiles como, sobre todo, aplicando metodologías clásicas.

El software se tiene que desarrollar pensando en que va a cambiar y los medios puestos a disposición del sistema de información (o del conjunto de sistemas de información de una organización) deben poder dar respuesta a cuando esos cambios se produzcan, que a veces no sabremos cuando, pero sí sabemos que ocurrirán.

Una vez analizados los principios y valores del manifiesto ágil, en este artículo se va a realizar un breve perfil de sus diecisiete participantes, con el objetivo de que se pueda apreciar que todo el equipo de personas que participaron eran profesionales de reconocido prestigio y que en su trayectoria profesional tenían experiencia e incluso habían publicado artículos y libros sobre la aplicación de estrategias que posteriormente a alto nivel se plasmaron en el manifiesto ágil.

– Kent Beck: Americano. Creador de la metodología de programación extrema y de la metodología de desarrollo guiado por las pruebas (TDD: Test-driven Development). Coautor de JUnit. Promotor de la reunión que dio lugar a la creación de manifiesto ágil para el desarrollo de software.

– Mike Beedle: Americano. Ha sido uno de los pioneros en la aplicación de Scrum (desde 1995) en proyectos de desarrollo de software en diferentes organizaciones y tipos de sistemas (en cuanto al proceso o procesos de negocio que tratan de informatizar).

– Arie van Bennekum: Holandés. Jefe de proyectos y consultor especializado en la metodología DSDM (método de desarrollo de sistemas dinámicos), representó al DSDM Consortium en la reunión.

– Alistair Cockburn: Americano. Creador de la familia de metodologías Crystal. Contribuyó a la expansión de la utilización de los casos de uso con la definición que hizo de los mismos en el libro “Escribir casos de uso efectivos” publicado en el año 2000, propiciando la generalización de su uso para describir el comportamiento de los requisitos software y de los procesos de negocio (a más alto nivel). La creación del concepto de caso de uso es bastante anterior, del año 1986 y fue realizada por el sueco Ivar Jacobson

– Ward Cunningham: Americano. Howard G. Cunningham fue el creador de la primera solución Wiki (WikiWikiWeb) y se considera un pionero tanto en la aplicación de programación extrema como en la utilización de patrones de diseño.

– Martin Fowler: Americano. Especialista en procesos de refactorización de software, programación orientada a objetos, UML y programación extrema. Hizo popular el uso del término “inyección de dependencias”.

– James Grenning: Americano. Especialista en sistemas empotrados. Fue uno de los pioneros en desarrollo de proyectos bajo la metodología de programación extrema. Experto en TDD (Test-driven Development). Ha sido el creador de la técnica de estimación Planning Poker.

– Jim Highsmith: Americano. James A. Highsmith III. Ingeniero de software experimentado que ha participado en proyectos de desarrollo de software en muchos países del mundo. En el año 1999 publicó el libro “Adaptative Software Development” donde puso de manifiesto la naturaleza adaptativa de los proyectos de desarrollo de software. Se ha especializado en la consultoría de proyectos que se realizan en entornos inestables y con una complejidad creciente.

– Andrew Hunt: Americano. Desarrollador de software con gran experiencia. Publicó junto a Dave Thomas en el año 1999 el libro “The Pragmatic Programmer”, en el que realizó una definición de lo que consideraban un programador práctico o pragmático:

– Early adopter.
– Curioso.
– Pensador crítico.
– Realista.
– Aprendiz de todo, maestro de nada.

Fue uno de los introductores en occidente de la programación en Ruby, mediante la publicación en el año 2000 del libro “Programming Ruby: A Pragmatic Programmer’s Guide”.

– Ron Jeffries: Considerado junto a Kent Beck y Ward Cunningham como uno de los creadores de la programación extrema. Participó junto a Beck en el proyecto de 1996 en Chrysler que dio lugar a este concepto.

– Brian Marick: Americano. Especialista en realización de tareas de testing. En el año 1995 publicó uno de sus libros más conocidos: “The Craft of Software Testing: Subsystem Testing Including Object-based and Object-oriented Testing”. Experto en Ruby.

– Robert C. Martin: Americano. Robert Cecil Martin (Uncle Bob). Dedicado a tareas de desarrollo de software desde 1970. Especialista en programación orientada a objetos sobre todo en el área de patrones de diseño.

– Steve Mellor: Americano. Especialista en sistemas empotrados, programación orientada a objetos y MDA (Model Driven Architecture). Creador junto a Sally Shlaer del método Shlaer-Mellor que es uno de los métodos de análisis y diseño orientado a objetos que surgió a finales de la década de los ochenta como respuesta a las principales problemáticas que presentaba el análisis y diseño estructurado, entre las cuales destacaban la complejidad de los diseños estructurados y la dificultad de mantener tanto su documentación de análisis como de diseño.

– Jon Kern: Americano. Inició su carrera profesional en sistemas empotrados en el área militar. Considerado como uno de los pioneros en la aplicación de la programación orientada a objetos. Especialista en programación Java y en MDA.

– Ken Schwaber y Jeff Sutherland: Americanos. Creadores de la metodología Scrum.

– Dave Thomas: Inglés. Autor junto a Andrew Hunt del libro “The Pragmatic Programmer”. También junto al mismo autor se considera uno de los introductores de Ruby en occidente.

En el anterior artículo se describieron los principios en los que se sustenta esta metodología. Ahora toca analizar las distintas fases que conforman su ciclo de vida.

1) Exploración

Se realiza la toma de contacto con el proceso o procesos de negocio que se van a informatizar así como con la arquitectura y tecnología de desarrollo. Básicamente se realizan las siguientes tareas:

Historias de usuario: Suponen una de las principales novedades de la metodología y no por el producto en sí, sino por cómo se elabora. Se trata de especificaciones de funcionalidades deseadas del sistema (podrían ser comparables a descripciones de casos de uso) que realizan los mismos usuarios (el mismo cliente), por lo que sus contenidos están en el mismo lenguaje que los usuarios manejan.

Se trata de especificaciones iniciales cuyo nivel de detalle dependerá de la información que precisen los programadores para realizar una estimación del tiempo que requerirá su implementación. Más adelante, cuando se vaya a abordar el proceso de construcción, los programadores recabarán todo el detalle que necesiten para el desarrollo de la funcionalidad mediante el diálogo directo con el cliente.

A nivel documental, una historia de usuario será como una ficha, a la que se le asigna una numeración (sería como el ID de la ficha), un nombre, un autor, un número de versión (una historia de usuario puede retocarse todas las veces que sean necesarias), una prioridad, un nivel de riesgo, una estimación de tiempo de desarrollo, el número de iteración que se le asigna, una descripción y unas observaciones.

Como es puede apreciar, existen diversos aspectos que cumplimentan los técnicos del proyecto (o el mismo usuario si el técnico le facilita la información), pero la mayor parte de la ficha es responsabilidad del cliente.

– Definición de la arquitectura del sistema.

– Posibilidad de realizar algún prototipo, si fuera necesario, para determinar la viabilidad de determinadas soluciones técnicas o tecnológicas.

2) Planificación:

Los programadores realizan la estimación del tiempo necesario para implementar cada historia de usuario. En algunos casos será necesario complementarlas con spikes, que pueden ser desde simples bosquejos a mano alzada, prototipos estáticos, prototipos dinámicos, etc…, estos, en función de su complejidad, podrán ser elaborados por usuarios, técnicos o de forma colaborativa. El objetivo es intentar disminuir en lo posible el margen de error en la estimación.

Las historias de usuario pueden contener especificaciones de funcionalidades simples o complejas (composición de funcionalidades). Dado que se considera que cada historia de usuario debe ser programada entre una y tres semanas, es necesario realizar ajustes en las mismas para que entren en ese período de tiempo, de manera que si se estima que se desarrollan en menos de una semana es necesario agrupar historias de usuario y si tardan más de tres semanas, dividirlas en partes.

Una vez que las tareas de estimación han terminado, el siguiente producto a obtener es el plan o cronograma de entregas (Release Plan), en el que participan todos los actores del proyecto. En él se definen las historias de usuario que se implementan en cada iteración.

Como estamos ante un proceso de desarrollo iterativo e incremental, resulta conveniente la revisión de este Release Plan cada cierto número de iteraciones, con el objeto de ajustarlo en cada momento a la realidad del proyecto (en el desarrollo de las iteraciones pueden aparecer nuevas historias de usuario o modificaciones de las ya existentes) y de corregir aspectos de la planificación que no se hayan estimado convenientemente, como por ejemplo la velocidad del proyecto (número de historias de usuario que se pueden implementar por iteración), ya que lo mismo se ha sido demasiado optimista o pesimista.

Se considera que cada iteración debe llevar a lo sumo dos o tres semanas (hay autores que sitúan el margen entre una y cuatro semanas) y que una entrega completa (el resultado de varias iteraciones disponible para su paso a producción) no debería tardar más de tres meses.

3) Iteraciones

Se desarrolla en cada iteración el conjunto de historias de usuario que se han seleccionado para la misma. Cada una de ellas se clasifica en tareas de ingeniería que vendrían a considerarse como las entradas de trabajo para cada equipo de programadores.

A nivel documental, como sucede con las historias de usuario, las tareas de ingeniería vendrían a ser como una ficha que contendría el número identificador de la tarea, el identificador de la historia de usuario con la que está relacionada, el nombre de la tarea, el tipo (nuevo desarrollo, corrección, mejora, etc…), la fecha de inicio, su fecha de fin, el equipo responsable y la descripción.

Como se comentó anteriormente los detalles que necesite el equipo de trabajo para realizar la tarea de ingeniería los tratará directamente con el usuario.

Cuando se construye se tienen en cuenta todas las prácticas especificadas en el primer artículo: construcción de pruebas unitarias, refactorización, pruebas unitarias, pruebas de integración, etc…

Para cada historia de usuario se definen pruebas de aceptación que deben ser realizadas (como mínimo) al final de cada iteración, donde también se realizan pruebas de regresión (comprobando que se verifican adecuadamente las pruebas de aceptación de iteraciones anteriores).

4) Producción:

Se realizan pruebas adicionales y de rendimiento antes de la puesta en producción efectiva de la versión de la aplicación con la que se ha estado trabajando.

En esta fase, donde el cliente realiza la aceptación del producto que se pasa a producción pueden ser detectadas determinadas correcciones o mejoras a incorporar al sistema previo a su puesta en funcionamiento real. Sobre las mismas se puede tomar la decisión de incluirlas en esta versión o en otra sucesiva, si se decide incorporarlas, se realizarán iteraciones más cortas para llevarlas a cabo.

5) Mantenimiento:

En esta fase el equipo de proyecto debe realizar, si fuera necesario, un mantenimiento correctivo del proyecto mientras puede llevar a cabo nuevas iteraciones.

6) Muerte del proyecto:

No existen más historias de usuario que incluir en el sistema, el cual además es estable en aspectos no funcionales.

La metodología de programación extrema fue introducida por el americano Kent Beck (autor también de la metodología de desarrollo guiado por las pruebas (TDD: Test-driven Development) y coautor de JUnit) en el año 1999, aunque empezó a trabajar en la misma años antes, concretamente desde el año 1996 cuando fue contratado por Chrysler Corporation, para intentar sacar adelante una aplicación para nóminas que hasta entonces tenía importantes problemas en el desarrollo. Cuando empezó a trabajar en el proyecto, detectó una serie de aspectos en el proceso de desarrollo que debían cambiar, aplicando para ello una serie de estrategias, muchas de ellas basadas en buenas prácticas ya contempladas y utilizadas.

La programación extrema se sitúa en una posición diferente a los ciclos de vida tradicionales. Ya no se trata de requisitos que se cierran en etapas tempranas del desarrollo y que constituyen el contrato de lo que posteriormente se va a desarrollar (y que los usuarios no ven hasta mucho después) sino de requisitos que están vivos y que son modificables a lo largo del ciclo de vida.

La programación extrema se centra en cinco principios:

– Simplicidad: Conforme en el proceso de construcción un sistema va creciendo paulatinamente (aplicable también a mantenimientos sobre sistemas ya construidos), la complejidad del código va creciendo de manera proporcional (o incluso exponencial en función del tamaño del proyecto y del número de personas que participen en el proceso).

Mediante la refactorización, se intenta mantener el código en unas condiciones donde la complejidad esté controlada y facilite la escalabilidad del sistema. Esto requiere disciplina y creer que esta metodología produce resultados ya que resulta complicado tomar la decisión de tocar código que ya funciona (esto va en contra de una de las máximas de la programación que consiste en que no toques algo que funciona, aunque también es cierto que la misma viene derivada de las malas experiencias provocadas por la crisis del software).

La integración continua resulta esencial en esta metodología, ya que ofrece la oportunidad de probar con una cierta regularidad la integración de los componentes, de manera que este tipo de problemas se puede detectar lo antes posible.

El control de la calidad del código se complementa con otras estrategias como por ejemplo el intento de que el mismo sea lo más autocomentado posible (sin prescindir de comentarios cuando sean necesarios). ¿Por qué la metodología prioriza la autodocumentación? Como el proyecto es algo que está vivo, el código se modifica con cierta frecuencia (sobre todo en el proceso de construcción), ¿por qué preocuparse en comentar un código que tal vez tenga que modificar muy pronto ya sea por una modificación funcional, por una corrección o por una refactorización? A esto hay que añadirle el peligro de que empiecen a quedarse atrás comentarios que no se han eliminado y que no se correspondan con la realidad del código. Si el código está autodocumentado evoluciona de la misma manera que lo hace el proyecto.

Para esta metodología lo más importante del proceso de desarrollo de software es el código, la base para esto tiene un razonamiento simple, sin código no hay aplicación. Se considera que una aplicación que funciona según las necesidades del cliente tiene mucho más peso que el hecho de que esté documentada al detalle.

Para sostener esta afirmación en sistemas de un cierto tamaño es fundamental un código de mucha calidad. De no ser así, el cambio de un equipo de desarrollo por otro puede provocar un riesgo importante para conseguir una continuidad en el mantenimiento del proyecto ya que se estará caminando por un terreno lleno de trampas y con poca luminosidad.

– Comunicación: Fluida y continua. Para ello se programa por parejas (pair-programming, un ordenador, dos personas) y los usuarios designados por el cliente forman parte del equipo de desarrollo (se eliminan fronteras). Pero la comunicación va más allá de eso, un código comentado (autodocumentado) y con pruebas unitarias definidas expresa información para la comprensión del mismo, es como una caja del tiempo o un mensaje en una botella y que será muy útil cuando se tengan que realizar modificaciones.

Algunos de los críticos de esta metodología comentan que la tendencia de los programadores a considerar el código desarrollado como propio dificulta el proceso de comunicación ya que cada cual considera que sus opiniones y decisiones son y han sido las mejores, que su código es difícilmente superable (o por lo menos que era complicado hacerlo mejor en el tiempo que se ha dispuesto para desarrollarlo) y además no se suelen aceptar de buen grado las correcciones (sobre todo si están relacionadas con la calidad).

Para resolver ese inconveniente la programación extrema considera que el código es colectivo, no hay parcelas, de manera que cualquier integrante del equipo de proyecto puede realizar contribuciones a cualquier parte del mismo.

Las pruebas unitarias resultan esenciales, ya que permiten automatizar la revisión del funcionamiento de cada módulo y así tener la posibilidad de realizar este tipo de tareas con frecuencia. Hay que tener en cuenta también que el código está en continua evolución por lo que las pruebas de regresión cobran importancia. El objetivo es detectar posibles errores lo antes posible. La detección tardía de errores es más costosa y su corrección además tiende a ensuciar el código (cuando el tiempo aprieta lo importante es apagar el fuego).

Aunque no es obligatorio, se recomienda incluso que las pruebas unitarias de cada componente estén construidas antes de desarrollarlo.

Otro aspecto característico de la metodología son las reuniones diarias, que se realizan de pie y en círculo (stand-up meetings) y que tienen una duración aproximada de quince minutos. En las mismas se habla sobre el estado actual del proyecto y sobre contingencias, problemáticas o dudas que se produzcan en el mismo.

Para favorecer la comunicación se aconseja que todo el equipo de trabajo se encuentre en la misma ubicación física y en entornos despejados.

– Retroalimentación: La participación y proximidad de los usuarios permite resolver dudas casi de forma instantánea, pueden ver funcionalidades concretas construidas parcialmente y opinar sobre ellas. Se comparten opiniones sobre cuál puede ser la mejor solución (es importante lo funcional pero hay que equilibrar lo que se quiere con la complejidad de realizarlo, como dijo Voltaire, lo perfecto es enemigo de lo bueno)

El desarrollo iterativo incremental permite que en cada evolución el usuario pueda expresar su opinión sobre los resultados obtenidos y si es necesario corregir algo, planificarlo para la siguiente o próximas iteraciones.

– Coraje: Optar por esta metodología no es sencillo por muchos factores, por muchos interrogantes. ¿Es sencillo admitir que se programe por parejas?, es decir, ¿puede todo el mundo entender que en cada momento uno toque el teclado y el otro mire?, ¿se puede comprender que esta estrategia no tiene por qué afectar a la productividad?.

La programación en parejas tiene una serie de ventajas:

Las decisiones en la codificación no son algo unilateral de la persona que programa el componente (los arquitectos o analistas orgánicos no pueden llegar a todo el detalle de la programación, ya que ellos determinan el armazón de la aplicación que librerías utilizar, su división en capas, etc…, es decir, establecen el marco general).

El código es revisado en tiempo real, disminuyendo la probabilidad de error e incrementando la calidad del código.

Pero no es solo lo anterior, ¿puede ser admisible que se retoque software que ya funciona con el objeto de mejorar su calidad (simplicidad)?, ¿se puede vivir en un proyecto donde los requisitos están siempre en el aire?, ¿es sostenible un proyecto orientado a entregas continuas cada poco tiempo donde el cumplimiento de los plazos resulta de gran importancia?.

Sobre esto último algunos de los críticos con la metodología consideran que el equipo de trabajo está vendido a las entregas y que al haber muchas y frecuentes, los errores en la planificación provocarán numerosos picos de trabajo con el consiguiente overtime para los distintos integrantes del equipo de proyecto.

Sin embargo los defensores sostienen que el mismo Kent Beck considera que es necesario evitar el cansancio de los componentes del equipo de proyecto, debiéndose respetar su jornada laboral, situándose esta en cuarenta horas semanales. De hecho considera que no se debe haber overtime dos semanas consecutivas. Aplica por tanto el principio de responsabilidad en el sentido de que hay que tener disciplina con las entregas pero que eso no puede estar por encima de un continuo sobreesfuerzo de los integrantes del equipo de trabajo. ¿Por qué defiende esto? Pues porque los programadores cansados escriben código de peor calidad y además son menos productivos.

– Respeto: Algo complicado de encontrar en los proyectos de desarrollo de software y en un mundo tan ombliguista como es este. Se basa en el hecho de que todos los participantes en el equipo de proyecto suman y que es importante que se tenga en cuenta que para que todo vaya bien, todos tienen que dar lo mejor de sí y para que esto se pueda producir hay que crear un ambiente que lo propicie. Las críticas deben ser constructivas, siempre para mejorar, siempre para ir hacia adelante. Es importante que se tenga en cuenta que para que el barco vaya hacia adelante todos tienen que remar y que si se hunde se hunden todos.

Por otro lado cada participante debe asumir su responsabilidad, cada cual tiene su rol y debe entender que tras él hay una serie de tareas que se tienen que realizar, gustén más o gusten menos.

En el siguiente artículo sobre este tema se tratará sobre el ciclo de vida/metodología de la programación extrema.