Publicado en
En un proyecto ágil, los programadores tienen una misión: entregar periódicamente (cada 2, 3 o 4 semanas dependiendo de la duración de las iteraciones) software que funcione y esté probado. Para lograr esto, los programadores requieren mantenerse ágiles tanto a sí mismos, como al código que generan. Esto requiere mucha disciplina. El código ágil es aquel que solamente implementa los requerimientos actuales, tiene pocos defectos y se basa en un diseño robusto que permite extenderlo fácilmente para incorporar requerimientos adicionales en futuras iteraciones. Un código ágil está factorizado adecuadamente, y bien protegido por pruebas unitarias. Entre los métodos ágiles, Extreme Programming (XP) es posiblemente el que entre en mayor detalle acerca de como los programadores pueden hacer código ágil. Cada vez es más común encontrar equipos ágiles que aunque no apliquen XP en su totalidad, sí apliquen al menos algunas prácticas de XP que tienen que ver con la forma de trabajar de los programadores.
Dichas prácticas son:
• Desarrollo dirigido por pruebas
• Refactorización rigurosa y constante
• Integración continua
• Diseño simple
• Programación en pares
• Compartir una base de código entre los programadores
• Adherirse a un estándar de programación
• Un área de trabajo común
Estudiémoslas en mayor detalle.
Desarrollo dirigido por pruebas
Tener pruebas unitarias para solamente algunas partes de nuestro código puede resultar en código de baja calidad. Por otro lado, cubrir el 100% no es muy práctico y resulta en baja productividad. Una cobertura de pruebas unitarias de entre 75% y 85% del código es típicamente considerada como óptima. Una excelente forma de lograr tener estos niveles de cobertura es aplicar el Test-First programming. Esta técnica consiste en que antes de que creemos el código para satisfacer un requerimiento, primero generemos pruebas unitarias automatizadas que validen dicho código. Tal acercamiento puede sentirse extraño en un principio, sin embargo es de gran utilidad. Pensemos en los escaladores de montañas que crean caminos al ir dejando anclas; hacer esto es mucho más tardado que simplemente escalar, pero será de gran utilidad para los próximas veces que se tome este camino. Para implementar esta técnica, típicamente se utiliza algun framework de la familia xUnit (Junit para Java, Nunit para C#, etcétera). Dichos frameworks facilitan la creación, ejecución y organización de pruebas unitarias. Otra ventaja es que la mayoría de los IDEs soportan estos frameworks. El desarrollo dirigido por pruebas (test driven development, TDD) es un caso especial de test-first programming que agrega el elemento del diseño continuo. Con TDD, el diseño del sistema no es restringido por un diseño estático en papel, sino que el diseño es continuamente retroalimentado por el proceso de creación de pruebas y código de producción. Conforme el código se refactoriza para simplificarlo y clarificarlo, es posible encontrar mejores métodos, clases y modelos que los que establece el diseño original. TDD se basa en la premisa de que no puedes determinar cual será el mejor diseño, hasta que estés implementando el código. Conforme te vas dando cuenta de qué funciona, y qué no, estás en el mejor momento para ajustar el diseño, mientras tienes las ideas frescas. Y para protegerte de que pudieras realizar cambios que afecten elementos ya implementados, estás protegido por tu conjunto de pruebas unitarias automatizadas.
Refactorización
La refactorización (refactoring) es el proceso de clarificar y simplificar el diseño de un código existente, sin cambiar su comportamiento. Esta actividad se realiza de forma continua. El código que no es continuamente refactorizado, se pudre. Dicha putrefacción se puede notar de distintas formas: demasiadas dependencias entre clases o paquetes, asignación incorrecta de responsabilidades en clases, duplicación de código, tan solo por nombrar algunas. Cada vez que cambiamos un código existente y no intentamos refactorizar, la putrefacción aumenta. Sin embargo, hay que estar conscientes de que la única forma de que sea sano y viable refactorizar de forma continua, es que contemos con una buena base de pruebas unitarias automatizadas. Si no somos capaces de ejecutar dichas pruebas cada que refactorizamos código, corremos el riesgo de estar introduciendo defectos sin darnos cuenta. El libro “Refactoring: Improving the Design of Existing Code” de Martin Fowler es una excelente guía que describe oportunidades de refactorización comunes, y distintas formas de resolverlas. Pero la refactorización no solo ocurre a nivel de
código, sino que se puede llevar al nivel de patrones de diseño. En su libro “Refactoring to Patterns”, Joshua Kerievsky explica cómo hacer esto, así como su utilidad.
Integración continua
Programación en pares
suficientemente largo como para incluir la rotación de staff. Esto es porque la programación en pares mitiga el problema de que haya personas que sean “islas de conocimiento”, y que al abandonar un proyecto lo afecten significativamente. Al estar continuamente
compartiendo el conocimiento dentro de un equipo, se reduce el impacto de la rotación. En Extreme Programming se utiliza el término “número de camiones” (truck number) para referirse al número de personas que tendrían que ser atropellados por un camión
para que el proyecto tuviera que cancelarse, y XP busca que dicho número sea lo más cercano al número total de personas en el equipo. No es que no haya especialización entre los miembros del equipo, es solo que todos están enterados de qué es lo que está
pasando, y por qué se hizo así.
Si los programadores se adhieren a un mismo estándar de programación (incluyendo detalles como tabuladores vs. espacios, posicionamiento de corchetes, y nomenclatura de elementos), todo funciona mejor. Es más sencillo mantener y extender código, refactorizarlo, y reconciliar conflictos de integración, cuando se utiliza un mismo estándar a través de todo el código de un proyecto. No importa cual estándar se utilice, lo importante es adherirse a él.
Base de código común
Durante la segunda guerra mundial, cuando Inglaterra se convenció de que necesitaba poder romper los complicados algoritmos criptográficos de los Nazis, ensamblaron un grupo con los mejores matemáticos y criptógrafos. Al hacer esto, no los pusieron en oficinas separadas para que trabajaran aislados, sino que los juntaron lo más posible, fomentando la interacción entre ellos. Este grupo estaba aislado del resto del mundo. Trabajaban, comían y dormían juntos. Fue de esta tumultuosa convergencia que surgieron ideas brillantes que los llevaron a construir las máquinas (computadoras) que hicieron posible descifrar los códigos Nazis. Se ha demostrado en repetidas ocasiones que los espacios de trabajo abiertos facilitan la comunicación en el equipo. Cuando un programador tiene una pregunta técnica, duda sobre algún requerimiento, o encuentra un conflicto de integración, cuenta con ayuda a la mano. Cuando las personas hablan entre sí exactamente en el momento que lo necesitan (en lugar de esperar a la próxima junta), los problemas se resuelven más rápido y mejor.
Conclusión
Invitamos a los equipos de desarrollo de software a adoptar las prácticas descritas en este artículo. Sin duda encontrarán que les permiten desarrollar mejor software de forma consistente.
- Log in to post comments