La calidad no es inyectable, parte 3

Finalmente hoy sí voy a referirme a los métodos ágiles. Tal como lo contamos en el capítulo 18 de Construcción de Software, una mirada ágil, el enfoque de los métodos ágiles es construir con calidad día a día. Esto no es muy novedoso pues bajado a concreto (y en forma simplificada) lo que hacen los métodos ágiles es tomar algunas de las prácticas existentes en el desarrollo de software y llevarlas un paso más allá:

  • Si las revisiones de código agregan valor, entonces directamente escribamos el código de dos (pair programming)
  • Si el feedback del usuario es valioso, entonces trabajemos más cerca de él (on-site customer) y busquemos su validación en forma periódica (iteration review)
  • Si la integración periódica nos facilita el desarrollo, entonces integremos todo el tiempo (integración continua)
  • Si el testing y la aceptación son actividades importantes para la calidad, no las dejemos para el final, integremoslas al ciclo de desarrollo de forma temprana (Definition of Done, BDD)
  • Si creemos que podemos mejorar en la forma que trabajamos, incorporemos entonces un mecanismo explícito para la mejora continua (retrospectivas)

Y sin duda podríamos seguir enumerando casos de prácticas de desarrollo que los métodos ágiles han potenciado.

Adicionalmente hay algunas otras cuestiones, que personalmente no logro identificar con prácticas pre-existentes pero que sin duda son clave en los métodos ágiles y entre las cuales destaco:

La construcción de software es una actividad intelectual llevada a cabo por personas. Si bien puede parecer una cuestión obvia resulta que curiosamente muchos enfoques de construcción de software precedentes parecen haberla pasado por alto.

Fin.

Nuevo proyecto de CI / CD

Hacía fines de diciembre del año pasado me contactaron de una empresa para que los ayudara con una iniciativa de Integración Continua. Intercambiamos un par de mails, tuvimos una llamada telefónica de 20 minutos y acordamos una primera reunión.

Desde mi punto de vista la práctica de integración continua no es un fin en sí mismo sino que es una herramienta. Por ello, una de las primeras cosas que pregunté fue: ¿Cuál es su problema? ¿Qué esperan solucionar con esta práctica? La respuesta fue clara, había dos problemas principales: por un lado la calidad del producto y por otro el desperdicio de tiempo invertido en el despliegue de la aplicación a los distintos ambientes. Esto me permitió entender que la cuestión iba bastante más allá de la integración continua.

El desafió me pareció muy interesante, pues se trataba de una empresa grande, con equipos distribuidos geográficamente en distintos lugares de latinoamérica y cuyo negocio estaba centrado en la venta de soluciones de banca. La empresa contaba con un plataforma de productos que vendía a distintos clientes y cada venta implicaba una implementación/customización de los productos. De esta forma había equipos trabajando sobre los productos y en paralelo un equipo de implementación para cada cliente que compraba el producto.

En términos de administración de la configuración a primera vista la naturaleza del negocio llevaba a tener un trunk de producto con un branch por cada cliente. Fácil decirlo, no tan fácil de implementarlo sobre todo teniendo el código de todos los productos en un único repositorio CVS.

La plataforma tecnológica era Java, un clásico en sistemas de banca. Pero dado que la solución se vendía a distintos clientes la aplicación debía funcionar sobre distintos ecosistemas tanto a nivel base de datos, application server y service bus.

Un último condimento no menor es que gran parte del código venía arrastrándose desde hacía varios años y tenía dependencia con componentes open source ya sin soporte (por ejemplo Apache Hivemind). Adicionalmente también se estaban usando versiones viejas de algunas herramientas (por ejemplo java6  y maven2).

Cabe destacar que varias de este cuestiones no las sabia inicialmente, sino que las fui descubriendo una vez empecé a trabajar.

La situación era compleja y las expectativas del cliente eran muy grandes. Mi propuesta fue simple y concreta:

Busca un equipo que esté interesado en trabajar en esta iniciativa. Yo me siento y trabajo con el equipo codo a codo 1 mes para resolver los impedimentos que el equipo considere le impiden construir software de calidad.

Al cliente, le gustó la propuesta y la bola empezó a rodar.

Continuará…

Selección de herramientas de prueba (parte 2)

En la primera entrega de esta serie presenté una arquitectura de prueba de referencia. En esta entrega voy a instanciar esa arquitectura de referencia en Ruby.

Comenzado por las pruebas del programador (unitarias y de componentes), tendremos que nuestro objeto de prueba serán clases programadas en Ruby. Para hacer este tipo de pruebas una de las herramientas más populares es RSpec la cual nos daría una arquitectura de pruebas conformada por:

  • Lenguaje de especificación: Lenguaje de Dominio Específico provisto por RSpec
  • Intérprete: es el propio RSpec
  • Driver: dado que estamos testeando clases Ruby, que estamos haciendo pruebas unitarias y de componentes y que RSpec está hecho en Ruby no requerimos de ningún driver particular. En todo caso nuestro driver es el mismo Ruby
  • Librería de aserciones: es el mismo RSpec
  • Motor de ejecución: RSpec

Un detalle a tener presente es que este tipo de pruebas son pruebas que hace el programador para sí mismo, ya sea para guiar el desarrollo (si está haciendo TDD) o bien para garantizar que sus clases se comportan acorde a lo esperado. Este tipo de pruebas no suelen interesar al usuario, pues son de índole técnica y al mismo tiempo mucho más granulares que las funcionalidades pedidas por el usuario.

arquitectura_developer_tests_ruby

 

 

Pasando ahora a las pruebas de aceptación funcionales, si bien podríamos utilizar el mismo set de herramientas, la realidad es que esperamos que el usuario esté involucrado y por ello usaremos un set distinto de herramientas de cara tener un lenguaje de especificación más «amistoso» para el usuario. Al mismo tiempo el objeto de nuestras pruebas ya no son clases sino la aplicación como un todo:

  • Lenguaje de especificación: Gherkin
  • Intérprete: Cucumber
  • Driver: dependerá de la forma en que pretendamos comunicarnos con la aplicación. Suponiendo que nos comunicamos via HTTP, podríamos utilizar Capybara en conjunto con WebDriver de Selenium.
  • Librería de aserciones: RSpec
  • Motor de ejecución: Cucumber

arquitectura_user_tests_ruby

 

Libro de experiencias

Hace un tiempo que vengo dando vueltas a la idea de escribir un libro de experiencias de desarrollo de software. Seria una especie de compendio de casos de estudio cada uno de ellos escrito en primera persona. No es una idea novedosa, de hecho el año pasado gente de una univesidad de Colombia intentó hacer algo similar, pero hasta donde supe no prosperó.

La semana pasada mientras compraba mi pasaje para el Agile Open Camp tuve una idea para para concretar este libro: proponer una sesión en el open space para escribirlo. La idea seria aprovechar que estaremos 3 dias y dedicar un tiempo fijo cada día de cara a llegar el final de evento con una primera versión del libro. Puede parecer complejo pero en realidad no lo es, básicamente quienes tengan un caso para compartir, deberan sentarse y escribirlo, sin dar muchas vueltas la idea tener el caso contado aunque sea a grandes rasgos, luego se le podremos iterear para agregar detalles y correcciones. El último dia del evento tomamos todos los casos y generamos el libro utilizando la plataforma LeanPub. A partir de ahí, el manuscrito queda en un repositorio Git para que podemos ir puliendo los capítulos, ajutando estilo, agregando imágenes, etc, etc.

Al mismo tiempo, yo como promotor de la idea tomaré la responsabilidad de revisar y unificar estilos (acepto colaboración también para estos temas).

Más aún, podría ser interesante llevar al evento con algunos casos ya escritos y aprovechar alguna sesión del open space para trabajar en cuestiones de revisión y unificación de estilo. ¿Que tal si escribes tu caso durante el viaje? (salvo los patagónicos, el resto de los asistentes tendrá al menos 2 horas de viaje, tiempo más que suficiente para volcar la idea en un mail).

Imagino todos los casos siguiendo una misma estructura:

  • Título
  • Tags
  • Contexto
  • Desafío
  • Solución
  • Conclusión

Para tener una idea más concreta de mi idea de caso, pueden ver este que escribí el año pasado.

Para mi es clave es llegar el final del evento con una primera versión del libro, pues ya he participado en proyectos de escritura/traducción con varios involucrados y resulta verdaderamente complejo lograr compromiso y dedicación cuando uno tiene otras responsabilidades.

Bien, la invitación está hecha,  espero que contar con el apoyo suficiente para terminar el evento con la primera versión del libro.

 

La calidad no es inyectable, parte 2

Hablando sobre calidad no inyectable es inevitable recordar el aporte de Joseph Juran con su idea de Quality by Design. Esta idea hace referencia a que la calidad puede ser planificada y que muchos de los problemas de calidad se deben a la forma en que la calidad es planificada. En el post anterior comenté sobre el enfoque de planificar la calidad en una etapa tardía del proyecto, posterior a la finalización de la etapa de construcción. Quisiera ahora compartir otro enfoque más integral que planifica la calidad como actividades llevadas a cabo a lo largo de todo el proceso de construcción.

Y no, no voy a hablar de métodos ágiles, no todavía. Quiero referirme ahora a un enfoque duro y puro de ingeniería de software. No puedo dejar de asombrarme cuando escucho profesionales del software hablar como si antes de los métodos ágiles hubiera sido todo desorganización. No es cierto, entre la era de la desorganización y la aparición de los método ágiles ha habido muchas ideas, técnicas y prácticas muy valiosas, entre las que destaco:

  • Desarrollo iterativo e incremental
  • Revisiones de código
  • Arquitectura basada en componentes
  • Automatización de pruebas
  • Gestión de la configuración

Si bien estas prácticas estan descritas en diversos libros de ingeniería de software, personalmente me gusta el libro de Calidad en el desarrollo de Software de Guillermo Pantaleo, el cual está escrito en castellano, está enfocado específicamente en cuestiones de calidad, fue publicado en 2011 y esta escrito con la visión mixta de alguien con mucha experiencia académica e industrial como es el caso de Guillermo.

Continuará…

 

 

La calidad no es inyectable

No puedes construir un producto y luego inyectarle calidad, por una simple razón: la calidad no es inyectable.

Si quieres un producto de calidad, debes construirlo con calidad desde el vamos. Esto implica que la calidad de tu producto está directamente relacionada al proceso de construcción del mismo. Por ello tu proceso de construcción debe incluir actividades y prácticas de calidad. Y nada de esto es particular de la construcción de software.

Curiosa y contrariamente a esto, durante mucho tiempo muchas organizaciones de la industria del software han insistido (y algunas lo siguen haciendo)  en separar las actividades de construcción de las actividades de calidad, delegándolas incluso en distintos equipos que trabajan sobre el producto en distintos momentos, generalmente en forma secuencial. Un equipo de técnicos construye el producto y una vez terminado lo entrega al equipo de calidad, como si este pudiera inyectarle calidad, pero realidad ese equipo en el mejor de los casos solo mide la calidad del producto haciendo pruebas. Dependiendo del resultado de esas pruebas, el equipo de construcción vuelve a tomar el producto para «mejorar» su calidad. Esta dinámica de ida y vuelta se repite hasta que el producto alcanza el nivel de calidad deseado (o hasta que se acaba el presupuesto o hasta que se llega a una fecha límite).

¿Es posible generar un producto de calidad de esta forma ? Si, es posible. Pero no es la única forma y posiblemente tampoco sea la mejor para todos los casos. Entonces, ¿cómo seria una mejor forma de hacer esto? ja!, eso es tema del próximo post 😉

 

El placer de trabajar con quien uno gusta

Varios son los beneficios de trabajar de manera independiente, pero dudo que alguno sea más gratificante que el hecho de poder elegir con quien trabajar.

En este sentido ayer tuve  el gusto de compartir una mañana de trabajo con Pablito Tortorella (@pablitux). Pablo y yo estamos trabajando en un cliente, Pablo enfocado en cuestiones de adopción de Scrum y mejora organizacional y yo en cuestiones de integración continua y pruebas automatizadas. Si bien son temas distintos, tienen puntos de contacto y complementación. Ayer en particular estuvimos trabajando armando la infraestructura de prueba con un equipo que está físicamente distribuído.

Fue una mañana intensa, trabajamos todos juntos sentados frente a dos pantallas: una con el Hangout (teníamos miembros del equipo conectados en forma remota) y otra con el código del proyecto.

Logramos el objetivo que nos habíamos propuesto (tener una prueba corriendo sobre la nueva arquitectura), aprendimos, la pasamos bien y acordamos repetirlo la semana próxima.

¡Gracias Pablitux!

Integración continua, principio #3: el principio del tio Ben

Cuando el tío Ben está apunto de morir en los brazos de su sobrino Peter Parker (spiderman) le dice una frase que lo marcará para siempre:

Grandes poderes conllevan grandes responsabilidades

Amo esta frase, creo que aplica a todos los ámbitos de la vida y también al desarrollo de software. En este sentido Tobias Meyer en su libro People Scrum la utiliza para describir la situación de un equipo autoorganizado: el equipo tiene el poder de autoorganizarse y eso automáticamente aumenta su responsabilidad. Analicemos esta situación por el contrario: si a un equipo se le imponen compromisos ¿cuán responsable será ese equipo por esos compromisos impuestos?. Si en lugar de eso fuera el propio equipo el que asumiera los compromisos ¿no se sentiría ese equipo automáticamente más responsable por el cumplimiento de esos compromisos que el propio equipo eligió? Mi experiencia me ha demostrado que efectivamente es de esta forma, lo cual confirma la frase del tío Ben.

Llevando esto al contexto de integración continua creo que la frase puede incluso aplicarse a la inversa, grandes responsabilidades requieren grandes poderes. O sea, si se pretende que un equipo asuma la responsabilidad de mantener un build sano, debe entonces darse a ese equipo las herramientas (poderes) para poder tomar esa responsabilidad. En concreto ello implica, entre otras cosas, que el equipo debe tener acceso total al ambiente de integración continua. Sin excepción puedo decir que todas las implementaciones fallidas que he visto de esta práctica tenían en común que el equipo no tenía acceso completo al ambiente de integración continua.

Integración continua, principio #2: build everywhere

Particularmente la tarea de Build debe poder ejecutarse tanto en el servidor de integración continua como en la máquina del programador. Esto es fundamental para que en caso de falla del build, los programadores sean capaces de reproducir la falla en sus ambientes locales ejecutando la misma tarea que ejecutó el servidor.

Al mismo tiempo esto reduce la dependencia con el servidor de integración continua, ya que el mismo solo agrega un paso previo y uno posterior al build. En concreto:

  • El servidor de IC monitorea al repositorio de código y dispara nuevas ejecuciones en caso de detectar cambios
  • Una vez disparado el build y descargado el código fuente, el servidor de IC ejecutará la tarea de build que es justamente la que debe poder ejecutarse en la máquina de los programadores
  • Finalmente el paso adicional que ejecuta el servidor de IC es la notificación del resultado del build

Integración continua, principio #1: Independencia de IDE

Desde el punto de vista conceptual esta práctica está muy bien descripta en el artículo de Martin Fowler (#lecturaObligatoria), pero a la hora de intentar implementar la práctica, no suele alcanzar con la teoría. En este sentido un libro que me parece muy útil es Jenkins: The definitive guide de John Ferguson.

Luego de la lectura de los mencionados recursos y de haber recorrido un largo camino con esta práctica he identificado algunos principios fundamentales para la efectiva implementación de esta práctica. A partir de hoy y durante los próximos días voy a compartir una serie de post explicando cada uno de dichos principios. Si bien los principios los voy a ir numerando, su numeración no tiene correlación alguna con su importancia. Aquí va el primero.

Independencia del IDE

La generación del build no puede depender de un IDE. Es sorprendente la cantidad de programadores que no son capaces siquiera de compilar su aplicación sin usar un IDE. Esta es una situación que veo en muchos ambiente Java (alta dependencia de Eclipse) y .Net (alta dependencia de Visual Studio). En la actualidad todos los lenguaje de programación cuentan con alguna herramienta de build e incluso si no existe una herramienta específica para algún lenguaje, siempre es posible utilizar alguna herramienta genérica como el noble make.