martes, abril 03, 2007

TDD y la matriz de trazabilidad

En MoProSoft y CMMI constantemente nos encontramos con que la matriz de trazabilidad es necesaria para poder medir el impacto que un proyecto tendrá al momento de realizar un cambio. Dicen que es necesario el conocer esto para poder estimar y una vez aprobado el cambio, saber que áreas debes de cambiar.

TDD ofrece un enfoque un tanto distinto. En un principio nos obliga a tener un diseño altamente desacoplado por pensar primero en como usar el código antes de pensar en como hacerlo y principalmente por refactorizar constantemente. Esto nos trae como ventaja que el impacto en distintos componentes de código sea minímo.

Ahora si, partimos de que el impacto es minímo, ¿cual sería la necesidad realmente de tener la trazabilidad si sabemos que pocos componentes se verán afectados?. Por otro lado, gracias a ese diseño desacoplado, ahora sabemos que conocemos los limites y repercusiones del cambio por lo que la estimación es fácil. Hasta aquí cumplimos con el propósito de la matriz de trazabilidad.

La verdad es que ninguno de los dos enfoques es mejor que el otro como para determinar el impacto a los componentes. Algunos dirán que la matriz de trazabilidad da una mejor visibilidad lo cual es cierto, TDD no te la da (no directamente, ya veremos más adelante), pero te da confianza al hacer los cambios. El problema es que tener esa visibilidad viene con un gran costo, el mantener la matriz muy bien actualizada y con alto nivel de detalle, esto sin duda consume mucho tiempo, probablemente más que el necesario para hacer los cambios que pudieran presentarse al proyecto.

Partiendo de que ninguno de los dos enfoques es exacto al preveer el impacto en los componentes afectados, la desventaja de la matriz de trazabilidad es que no es capaz de identificar realmente el impacto que tuvo el cambio una vez realizado y ahí es otra área donde las pruebas que tenemso al usar TDD tienen su alto valor.

Digamos que hacemos un cambio al código y nuestra matriz nos dice que tenemos que cambiar el componente A, C y D, hacemos el cambio en los tres lugares esperados, verificamos que funcionen bien, se integra y antes de liberar aún tenemos que revisar que B no haya sido afectado y probablemente nos daremos cuenta de que B sufrio cambios hasta las pruebas de aceptación y será muy tarde para ver quien introdujo ese error y tratar de corregirlo a tiempo para liberar el producto y volvemos a la fase anterior sin poder liberar.

Viendo el mismo ejemplo en un proyecto que utilizo TDD desde un principio, estamos confiados a que sólo A necesitará un cambio ya que las dependencias entre los otros componentes son muy debiles, realizamos el cambio, damos check in se corre una serie de pruebas automatizadas que nos muestran que B ya no funciona como se esperaba. Ya le habíamos cotizado al cliente sabiendo que sólo tendríamos que cambiar A. En este momento estamos a buen tiempo de para:
a) Corregir el impacto causado en B y volver a dar check in a ver que pasa.
b) Explicarle al cliente que costará más de lo esperado y tomará más tiempo,
c) Que el cliente decida que prefiere si retrasar la entrega del proyecto por su impacto en B o no incluir el cambio propuesto y continuar con la fecha de entrega como se planeo originalmente.

La ventaja de TDD sobre la matriz de trazabilidad es que tiene otras ventajas adicionales a las de poder estimar conociendo el impacto sobre los componentes al hacer un cambio y aunque no nos da visibilidad nos da seguridad que muchas veces es más imporante. Sin embargo, es muy sencillo hacer una pequeña matriz de trazabilidad de Requerimientos-Pruebas-Implementación si se busca cumplir con algún modelo como MoProSoft, CMMI, ISO o simplemente se necesita usar para tener un poco de mejor visibilidad.

¿Cómo hacemos esta matriz usando TDD? Simple, nuestros requerimientos ya los tenemos dados de alta en Team System como Work Items, seguramente como Sprint Backlog Items, Tasks o lo que sea que manejen, un Work Item digamos Requerimiento 1, puede estar relacionado con Tarea 1 y Tarea 2, así que tenemos la trazabilidad directa desde la herramienta de requerimientos a actividades. La actividad usando TDD empezará por realizar una prueba unitaria, por lo que ahora relacionamos Tarea 1 con Tarea1Test y Tarea1FailsTest. Desde las pruebas en código, podemos navegar dando click en "Go to Definition" en el metodo o clase que estamos probando, por lo que tenemos navegación completa de requerimientos hasta implementación. Por otro lado si se tiene una capa de acceso a datos, sabremos claramente que partes de la base de datos se usan y por otro lado esta altamente desacoplado (o debería).

Nos falta otra parte de la navegación, que es desde implementación hacía requerimientos, esta parte es un poco más difícil de seguir, ya que un metodo o clase podría ser usado en diversas áreas, sin embargo dando click en "Find all referencies" llegamos a nuestras pruebas y de las pruebas ya podemos ver que tareas estan relacionadas con esta. Team System no ayuda mucho con la navegación bidireccional entre Work Items pero podrían hacerse algunos queries si fuera realmente necesario.

Resumiendo, con TDD
Tenemos diseños desacoplados que ayudan a minímizar el impacto a los diferentes componentes.
Nos da seguridad y confianza al hacer los cambios sabiendo que tenemos un buen diseño y en caso de errores detectaremos rápidamente si otros componentes se impactaron.
Podemos obtener visibilidad a través de la navegación entre Work Items, Pruebas e Implementación.