Hace casi 20 años Joel Spolsky escribía lo que se conoce como el test de Joel, 12 preguntas que (supuestamente) deberías aspirar a responder afirmativamente para mejorar tu proceso de desarrollo. Para tener 20 años han aguantado relativamente bien, y el hecho de que Stack Overflow lo use en las ofertas de trabajo (seguro que el hecho de que Joel sea fundador no tiene nada que ver) hace que sean conocidillas.
La quinta de ellas dice algo así como:
¿Arreglas los bugs antes de escribir código nuevo?
Suena a perogrullo. ¿Cómo no vas a arreglar los bugs cuando los encuentras? ¿Qué vas a hacer si no, dejarlos sin resolver? ¿Permitir que se acumulen hasta que destruyan tu precioso software? Además, todo el mundo sabe que resolver un bug suele ser más fácil (y por tanto más barato) cuanto menos tiempo pasa desde su introducción, así que el mejor momento para corregirlo es tan pronto como se detecta; idealmente durante el propio proceso de desarrollo.
Si estuviera todo tan claro no estaría escribiendo este post. Ya me conocéis.
No solo no siempre es necesario corregir los bugs según se encuentran, sino que a veces no merece la pena corregir ciertos bugs.
No todos los bugs iguales
Estás trabajando en una nueva funcionalidad. Por ser originales, el típico carrito de la compra de una tienda online. Mientras la implementas descubres que al sumar el precio de las productos se te ha olvidado tener en cuenta la cantidad, así que si alguien compra varias unidades de un mismo producto el cálculo del total falla. ¿Lo corriges ahora o esperas? Ahora, sin dudarlo.
Llegas a la siguiente funcionalidad. Generar un PDF con la factura del carrito de antes. Mientras haces pruebas descubres que la librería que usas para generar el PDF falla cuando el nombre del cliente tiene caracteres coreanos. Y tú no has vendido a un coreano en tu vida, Hulio. ¿Lo corriges ahora o esperas? Pues si corregirlo implica cambiar la librería para generar PDFs y ajustar todo tu código, lo más razonable es pasar del tema, apuntar el bug en algún sitio para que soporte conozca esa limitación, y esperar a que el señor 동현 se queje.
Resulta que algunos clientes se están quejando porque en su resumen de facturación el desglose de impuestos no siempre es correcto. ¿Lo corriges o esperas? Teniendo en cuenta las implicaciones legales, parece necesario corregirlo rápidamente.
Te llega un correo de un cliente que no ha recibido su mercancía. Tras analizarlo, descubres que una terrible coincidencia hizo que una caída de un proveedor de servicios externos, unida a un fallo en el envío de un email, y la ausencia por vacaciones del responsable de almacén se encuentran detrás del problema. ¿Montas un sistema resistente a este tipo de coincidencias o lo dejas como está? Si contruir un sistema tolerante a fallos require cambiar la arquitectura de toda la aplicación y esto sólo te ha pasado una vez en 500.000 pedidos, es probable que puedas asumir el fallo y resolverlo manualmente cuando se produzca.
Mientras revisas otra parte del código encuentras un caso extraño en el que se puede producir un error que impediría servir una determinada página generando un error 500 en el servidor. Compruebas los logs del servidor y ves que en los 2 años que lleva ese código en producción nunca se ha producido. ¿Merece la pena corregirlo? Depende. Técnicamente es un bug, pero si un bug no afecta a nadie, ¿realmente es un bug?
Triaje de bugs
En medicina de emergencias se utiliza la palabra triaje para referirse a la selección y clasificación de los pacientes en función de las prioridades de atención, privilegiando la posibilidad de supervivencia, de acuerdo con las necesidades terapéuticas y los recursos disponibles. Es decir, que cuando no puedes atender a todos los pacientes de forma inmediata y óptima, debes intentar salvar el máximo posible teniendo en cuenta la gravedad de sus lesiones y los recursos disponibles.
Cuando desarrollamos software disponemos de un recurso limitado, el tiempo, y debemos decidir de qué manera hemos de emplearlo para maximizar su valor. Esto implica que a veces será mejor dedicar el tiempo a implementar nuevas funcionalidades, a veces a corregir bugs existentes, a veces a pagar deuda técnica, a veces a investigar nuevas tecnologías, y otras veces a mil cosas más.
Decidir cómo repartir los recursos disponibles entre todas estas actividades es toda una ciencia (o arte, según se mire) y se escapa del objetivo de este post, pero podemos intentar ver algunas aspectos que nos permitan realizar un mejor triaje de bugs para decidir si los corregimos y cuándo los corregimos.
El coste de un bug
Cada bug que existe en un sistema tiene un coste asociado. Puede ser un coste derivado de los clientes que dejan de serlo por la existencia del bug, del tiempo dedicado por las personas de soporte para atenderlo cada vez que se produce, o del coste asociado a las acciones compensatorias que se realizan cuando ocurre, por ejempo, realizar un descuento a los clientes que, por culpa de un bug, han sufrido un retraso en su pedido, o hacer el seguimiento telefónico del envío de un pedido porque no se puede consultar en una página web.
Para comprender (e idealmente mesurar) el coste real de un bug la clave es conocer su impacto de negocio. Para ti, para tus clientes y para tus usuarios (que pueden no ser los mismos que tus clientes, nunca lo olvides).
Una primera dimensión que podemos considerar es la criticidad intrínseca del bug. No es lo mismo un bug que hace que un usuario pierda los datos que lleva introduciendo varias horas en un procesador de texto, que un bug que hace que se pierda el envío de un tweet si se pierde la conexión con el servidor de twitter. No es igual un bug que hace un usuario presente mal su declaración de impuestos y reciba una sanción administrativa por ello, que un bug que hace que las fotos de sus vacaciones aparezcan desordenadas cuando están sacadas en el mismo minuto. Esta criticidad siempre va ligada al valor de negocio de la funcionalidad afectada, por lo que sin comprender éste, es imposible valorarla.
También podemos considerar el número de usuarios afectados y la importancia relativa de esos usuarios para nuestro negocio. Como veíamos antes, no es igual un bug que afecta a todos los usuarios, que un bug que sólo afecta a aquellos usuarios con nombres coreanos si no vendemos en corea, o a los que usan cierta conjunción de funcionalidades y operativas de nuestra aplicación que sólo se da en 1 de cada 10.000 casos.
Además influye la frecuencia con que se reproduce el problema. Un bug de poca criticidad que se produce muchas veces al día y genera muchas llamadas de soporte puede suponer un coste mayor que un bug mucho más crítico que sólo se produce cuando hay eclipse de sol coincidiendo con el paso de Saturno por Sagitario.
El coste de su solución
En cuanto a lo que nos cuesta corregir el bug, hay factores más claros y otros que es más fácil pasar por alto a simple vista.
Lo primero que nos viene a la mente al pensar en el coste de corregir un bug es el tiempo que nos va a llegar. Nada sorprendente. Cuanto más tiempo de desarrollo requiera, mayor será el coste de la resolución y menos tiempo podremos destinar a otras tareas.
Otro factor a considerar es la posibilidad de introducir nuevos bugs con los cambios usados para corregir el primero. Casi puedo oir el nerviosismo de los auténticos crafters: ¡para eso están los tests! ¡Usa TDD para construir una red de seguridad contra regresiones!.
Sí, es verdad. Cuanto mejor sea tu proceso de pruebas y control de calidad (lo que suele implicar tener automatizado buena parte del mismo), menos riesgo corres de introducir bugs al cambiar código para corregir otros. Desgraciadamente, no todas las aplicaciones cuentan con tests de la calidad que nos gustará, y no todas las áreas de la aplicación se pueden cubrir con tests fiables. Por ejemplo, el interfaz de usuario o la integración con dispositivos externos son partes en las que, por muchos tests que tengas, es difícil estar seguro de que un cambio no rompe nada sin hacer pruebas manuales, y según se van complicando las operativas existentes en una aplicación, saber qué pruebas manuales hay que hacer y realizarlas correctamente no es fácil.
Existe otro factor que se tiende a despreciar: la complejidad que introduce la corrección. Aun asumiendo que puedas corregir el bug y que estés razonablemente seguro de que no rompes nada al hacerlo, ¿cuánto se va a complicar el mantenimiento posterior de la aplicación?
Hay ocasiones en que para corregir un bug necesitas hacer cambios importantes en el diseño o en la arquitectura del sistema. Esos cambios pueden convertir un diseño simple en algo mucho más complejo capaz de cubrir los escenarios en los que se produce el bug, y al realizarlos estamos comprometiendo el desarrollo futuro introduciendo fragilidad en el sistema e incrementando el coste de la evolución.
Hacer una valoración cuantitativa de todos estos factores no es trivial, y menos en un momento en que se tiene cierta aversión a las estimaciones y parece que nadie quiere mojarse en nada. Aun así, es importante analizar cada caso y usar una política de decisión algo mejor que una cola FIFO o cuál es el cliente o comercial que más chilla.
Una cuestión económica
Al final, como en casi todas las actividades humanas, decidir si hay que corregir o no un bug es una cuestión puramente económica. Y por económica no quiero decir necesariamente de euros, sino de relación coste/beneficio.
A muchos desarrolladores nos cuesta asumir cuando algo es suficientemente bueno. Tendemos a buscar la «perfección» de nuestro código y nuestras aplicaciones (a veces sólo de las partes que a las que hemos decidido darles más importancia porque nos parecen más divertidas). Nos pone nerviosos asumir deuda técnica.
Sin embargo, hay ocasiones en que lo mejor que podemos hacer con un bug es anotarlo para saber que existe y poder monitorizar su incidencia a lo largo del tiempo y olvidarnos de él por el momento. Igual que alcanzar un 100% de cobertura de código con los tests no suele ser rentable, mantener el sistema 100% libre de bugs tampoco suele serlo. Claro, que esto no vale hacerlo para todos los bugs y que nuestros clientes descubran qué es lo peor de desarrollar software.
Una reflexión muy acertada sobre como afrontar la resolución de bugs. Aprovecho para darte la enhorabuena por el blog, es muy interesante.
Muchas gracias, Andrés!
Interesante! Tomo nota de un par de ideas para el producto con el que anda liado.l ahora. Gracias