Hace unas semanas Enrique Ávila, COO de ING en España, me lanzó un reto tras leer mi post: “¿Confías en el código que escribes?”. Él me preguntó: “¿Crees que puedes demostrar por qué el código de test es más importante que el código de tu producto?”. Acepté el desafío, a pesar de las fechas navideñas que se avecinaban y los finales de año son siempre intensos. Afortunadamente, Alejandro Pérez, CTO de Autentia y de Carlos Blé, gurú y artesano del software Codesai, se ofrecieron voluntarios -a través de Twitter- a colaborar y yo he aceptado su ayuda encantado. Estoy tranquilo porque ellos saben mucho más que yo y no sólo espero de ellos que me den feedback sino también su apoyo para que en varias iteraciones quede de esto un trabajo digno a partir del que alguien pueda apoyarse. Bueno, vamos a ello.

Para construir software seguimos un proceso creativo que históricamente hemos tratado de sistematizar con objeto de reducir el riesgo a fracasar. Esa sistematización es lo que llamamos ingeniería del software, y, como cualquier otro proceso de ingeniería tiene como objeto ayudarnos a entender el problema y a encontrar la mejor solución para resolverlo. Durante la primera fase es muy importante lograr interpretar y describir adecuadamente lo que el cliente quiere. Puesto que el lenguaje natural es inherentemente ambiguo, es necesario utilizar otro tipo de herramientas que evite una incorrecta interpretación. La viñeta que se muestra a continuación refleja fielmente las diferentes interpretaciones que pueden percibirse de una misma realidad:

 

vignetas

 

Una de las herramientas más conocidas en el contexto de las Metodologías Ágiles que nos ayuda a reducir este riesgo es “Specification by example”. Ésta consiste en describir, de forma colaborativa junto con el cliente, el comportamiento del producto mediante la utilización de ejemplos en lugar de ideas o conceptos. De esta manera, se mejora la capacidad de entendimiento entre las partes y se reduce la cantidad de correcciones necesarias. Estos ejemplos, una vez refinados, se convertirán en las pruebas de aceptación del producto que estamos construyendo y nos ayudarán a verificar su funcionamiento.

Antes de seguir avanzando, creo que es importante aclarar el significado de los conceptos “verificar” y “validar”, debido a que tienen matices muy importantes en el contexto de la ingeniería del software. Ahora comprendo mejor la insistencia sobre este punto de mi profesor de Ingeniería del software I y II cuando estábamos tratando de aprender estos conceptos. De esto hace algunos añitos ya… En fin, aquí van las definiciones:

  • Verificar: Asegurar que el producto cumple correctamente con todos los requisitos. La herramienta más habitual para hacerlo son las pruebas.
  • Validar: Asegurar que el producto, además de cumplir con todos los requisitos, hace lo que verdaderamente el cliente espera. La herramienta más habitual para validar el producto es el “feedback”.

Bueno, sigamos trabajando en el reto. Estábamos comentando que las pruebas de aceptación nos ayudan a verificar el funcionamiento del producto y que si queremos realizar esta verificación con frecuencia deberemos automatizarlas. Una aproximación muy habitual a la hora de desarrollar software es la de combinar la especificación de requisitos (en este caso utilizando ejemplos) con la automatización, produciendo lo que se llama “requisitos ejecutables”. Este concepto es de los más potentes que conozco en lo que se refiere a la construcción de software y, sinceramente, hoy en día no concibo otra manera de construir productos digitales. Por un lado, tenemos una descripción (que es poco ambigua puesto que se basa en ejemplos) del comportamiento del producto; y por otro, un mecanismo automático para verificar si el producto final lo cumple o no. ¿Sabéis cómo se llama a esto? Se llama Behaviour driven development y hoy en día, junto con Test driven development, son las prácticas que, desde mi punto de vista, permiten construir productos software de calidad y con éxito.

Continuemos. Ahora toca repasar los artefactos que tenemos al aplicar este proceso de ingeniería: los requisitos, el código de test (tanto unitario como de aceptación) y el código de nuestro producto. Los dos primeros están dentro del dominio del problema y el tercero dentro del dominio de la solución. Los tres artefactos están conectados entre sí de tal forma que puedes verificar cada uno con el anterior y todo ello de forma automática. Sin embargo, realizar el proceso inverso no es posible. Para realizar el proceso en sentido contrario es necesario aplicar técnicas de ingeniería inversa. Y si bien es posible obtener algunos artefactos de diseño automáticamente a partir del código del producto, no es posible obtener automáticamente artefactos del dominio del problema. Un diagrama de clases, un diagrama de la base de datos, un diagrama de estados o un diagrama de flujo pueden ser recuperados aplicando ingeniería inversa, pero son artefactos que se refieren al dominio de la solución. Para poder obtener un artefacto del dominio del problema a partir de artefactos del dominio de la solución es necesario realizar una interpretación. Esto es lo que hace permanentemente un ingeniero de software al leer código: tratar de interpretar qué problema resuelve el producto. Se trata de una actividad totalmente empírica y normalmente no es posible recuperar el 100% de los requisitos originales solamente a partir del código. Por eso es más importante el código de test que el código de tu producto. Porque siempre puedes recuperar el código del producto a partir del código de test pero no es posible hacerlo en sentido contrario.

El código fuente del producto es la documentación de más bajo nivel y en demasiadas ocasiones, la única verdaderamente fiable. No tener documentado el problema que resuelve tu producto o no poder asegurar si está o no actualizada esa documentación, te obliga a leer el código del producto para realizar una interpretación. Y esto es un pozo de dinero, tanto por el tiempo que tienes que dedicarle, o lo que es mucho más grave, por los posibles errores que puedas introducir al realizar interpretaciones erróneas. Por eso, te recomiendo que la próxima vez que trabajes en un producto, le des una oportunidad a “Specification by example”, Behaviour driven developmentTest driven development. Ahorrarás mucho tiempo y dinero, además de generar un producto de calidad 😉

Muchas gracias por leerme,
José San Román A. de Lara