← Volver

Por qué el software se corrompe

Los requisitos confusos, los cambios caóticos, las pruebas insuficientes y la falta de refactorización pueden hacer que una aplicación se vuelva difícil y costosa de mantener.

Software Quality

Lo he visto en demasiadas ocasiones: una aplicación se concibe inicialmente para realizar un conjunto reducido de tareas, pero, con el tiempo, se intenta incluir más y más funcionalidad. Lo que debería ser un éxito (se pide nueva funcionalidad porque lo anterior funciona y es útil) termina convirtiéndose en una auténtica patata caliente: es imposible de mantener y cada nuevo cambio cuesta más esfuerzo y dinero.

También lo he visto —y sufrido— demasiadas veces: los responsables de esas aplicaciones son reacios a reconocer el problema, suelen echar balones fuera y se mantienen dentro de cierto caos antes de asumir profesionalmente que se ha alcanzado un punto crítico en el que hay que tomar decisiones desagradables.

El resultado siempre es el mismo: después de mucha frustración, se llega inevitablemente a la conclusión de que hay que rehacer partes completas de la aplicación, cuando no tirarla a la basura por completo y comenzar desde cero.

No podemos perder la perspectiva: si se trata de un proyecto con cierto carácter lúdico, un repositorio que apenas mantienes en GitHub o CodePlex, no pasa nada, salvo por el tiempo que se haya podido perder. Pero si se trata de un proyecto empresarial, todo lo anterior se traduce en costes dolorosos y, seguramente, en un equipo frustrado por trabajar en una aplicación difícil.

Este es un mantra que conviene no olvidar nunca: todo software requerirá cambios inevitablemente (y ese es el fundamento del enfoque ágil). Si no se diseña para admitirlos, tarde o temprano nos encontraremos con una aplicación corrupta y con el escenario descrito más arriba.

La buena noticia es que se puede evitar, trabajando desde el inicio del proyecto en la dirección correcta.

Pero ¿por qué llega a corromperse una aplicación con el paso del tiempo, a medida que la hacemos cambiar? A continuación enumero algunas de las razones:

  • Una aplicación se concibe inicialmente como simple o pequeña y se la obliga a crecer de forma muy rápida y descontrolada.
  • No existe una metodología para introducir nuevos cambios: los requisitos llegan de un día para otro, se vuelve atrás con frecuencia, no hay planificación ni una cultura de pruebas o validación de la aplicación antes de entregarla. Así se abona el terreno para el caos.
  • Los requisitos no están claros: la traducción de los requisitos de negocio a los requisitos técnicos no se realiza con exactitud ni con la suficiente comprensión. El resultado es que se implementa una funcionalidad que no es exactamente la que se quería, lo que produce una cascada de cambios y, posiblemente, deja código muerto y obsoleto que ensucia la solución.
  • Se utiliza una variedad dispersa de tecnologías que dificulta la evolución de la aplicación. Para programar bien y de forma mantenible, hay que conocer bien las librerías y los frameworks que se utilizan. Un exceso de estos en una misma aplicación provoca confusión y hace que sea más difícil trabajar con ella. Además, si se usan librerías complejas, la solución se ofusca.
  • No se dedica tiempo a mejorar lo que ya existe, aunque funcione. El desarrollo de software es, en cierta medida, incremental: construimos funcionalidad nueva sobre lo que ya existe, o siguiendo la misma forma de hacer las cosas. Hay que mantener siempre la actitud de mejorar continuamente lo que ya hay.
  • Se intenta mantener a toda costa código obsoleto, mal diseñado o mal probado. A veces cuesta eliminar partes de la aplicación porque recordamos el esfuerzo que nos llevó hacerlas o por simple pereza. Pero arrastrar algo que no está del todo bien es perjudicial. Podemos decir que lo que eliminamos nos sirvió, en realidad, para aprender a hacerlo mejor.
  • No se tiene en cuenta que no solo se mejora el código en sí, sino también el diseño y la organización del proyecto.
  • No se siguen de forma continuada las prácticas de código limpio y refactorización.
  • El proyecto no tiene pruebas o su batería es insuficiente y la cobertura de código es baja. Esto provoca que tardemos en saber qué errores introducimos al hacer cambios. Cuanto antes se detecte un error, más fácil y sencillo será corregirlo. Además, incluir pruebas obliga a diseñar la aplicación con una estructura mejor (software comprobable), lo que nos aleja de enfoques monolíticos y rígidos.
  • El diseño, si es que existe, es pobre.
  • Y, por supuesto, ocurre parte o todo lo que describo en El Libro Negro del Programador.

Lo bien o mal que hagamos todo lo anterior determinará cuándo llegamos a la barrera de la falta de mantenibilidad, tal y como describe la curva o ley de Boehm, que indica el coste incremental de corregir errores en una fase temprana del proyecto o en una fase tardía, cuando el software ya es demasiado corrupto:

Ley de Boehm: el coste de corregir errores aumenta cuanto más tarde se detectan

Nota: Este artículo es un resumen y forma parte del proyecto en desarrollo El Libro Práctico del Programador Ágil. Lanzamiento previsto para julio de 2018.