Deuda Técnica

Hace poco estuvimos hablando de SonarQube para analizar la calidad del código, y una de las cosas que nombramos ahí fue el concepto de “deuda técnica”, sobre el cual quisiera profundizar en este post.

Tal como contaba en este post, la calidad de código suele decirse que es un atributo interno de calidad, dado que no se hace visible al usuario. Pero llega un momento en el cual este atributo de calidad pasa de ser interno a externo, y esto se da cuando el hecho de tener modificar el código para hacer un cambio lleva mucho más tiempo del que debería.

Con el fin de garantizar una correcta calidad de código se utilizan distintas herramientas de análisis estático de código, como por ejemplo SonarQube, Codacy, Kiuwan, etc. Dentro de las verificaciones que se realizan se encuentran:

  • Código duplicado.
  • Falta de pruebas unitarias, falta de comentarios.
  • Código spaghetti, complejidad ciclomática, alto acoplamiento.
  • Tamaño de archivos de código.
  • Tamaño de métodos.
  • No adecuación a estándares y convenciones de código.
  • Vulnerabilidades conocidas de seguridad.

Estas herramientas permiten realizar análisis estático de código fuente de manera automática, buscando patrones con errores, malas prácticas o incidentes. Además, muchas de ellas son capaces de realizar el cálculo de una métrica conocida como deuda técnica.

El concepto de deuda técnica es una analogía para poder explicar algo tan complejo como la necesidad de hacer “refactoring” o de por qué invertir en la “calidad de código”. Cuando se está codificando bajo presión y con la necesidad de entregar algo rápido, muchas veces se dejan de lado algunas buenas prácticas, pruebas unitarias, etc. Al hacer esto se dice que se está adquiriendo una deuda con el software: hoy lo entrego sin haber hecho todas esas prácticas de calidad, pero me quedo con la deuda de hacerlas en algún momento (cuando tenga tiempo). El problema asociado a la deuda técnica es que, como toda deuda, genera intereses. En el momento en el que el desarrollador vaya a pagar esa deuda, tendrá que volver a ponerse en el contexto de esa funcionalidad que se estaba desarrollando, y así al final habrá invertido más tiempo que habiendo desarrollado con las buenas prácticas de una. Es por esto que se desea identificar cualquier problema en la calidad del código lo antes posible, para pagar la deuda cuanto antes, sin tener que pagar muchos intereses.

La métrica de deuda técnica se mide en horas. Las herramientas tienen una tabla de referencia, según el tipo de incidente, tienen estimado cuánto tiempo se debería invertir para resolver ese incidente. Haciendo la suma ponderada en base a esa tabla, logran estimar una cantidad de días y horas que se deberían invertir para poder pagar la deuda.

Las herramientas de análisis de código generalmente permiten categorizar las incidencias detectadas según su criticidad. Es así que habrán issues bloqueantes, de criticidad alta, media y baja. Se puede establecer entonces una estrategia basando los umbrales de calidad en cuanto a la cantidad de issues que se permiten por cada categoría.

Para entender mejor estos conceptos, es útil revisar el sitio online de SonarQube, donde hay muchos proyectos open source analizados, pudiendo ver qué tipo de incidentes se detectan, cómo se categorizan, y cuál es el resultado de la deuda técnica calculada.

(En el ejemplo que tomé del sitio de SonarQube, este proyecto tiene una deuda de 6 días).

En el caso particular de SonarQube, a través de definir “Quality Gates” es posible marcar los umbrales aceptables en el proceso de desarrollo, los cuales pueden ser determinados en base a distintas métricas. La definición de Quality Gates puede colaborar además a responder preguntas como:

  • No hay issues nuevos que sean críticos o bloqueantes.
  • El code coverage de las pruebas unitarias del nuevo código es mayor a 80%.
  • No hay más de 10% de líneas duplicadas.
  • No hay vulnerabilidades conocidas de seguridad.

Se puede comenzar estableciendo umbrales (Quality Gates) flexibles, y a lo largo del proyecto intentando fijar objetivos más estrictos. Por ejemplo, se podría comenzar exigiendo un 100% de cobertura de métodos públicos, y luego ir aumentando a tener 100% de líneas de código.

Es importante destacar que la cobertura a nivel de código no garantiza estar libre de bugs, ni siquiera la más exigente. En ocasiones no tiene sentido proponer una cobertura de 100% de líneas de código, más que nada pensando en que algún código podría ser generado automáticamente por algún componente o herramienta, y además, porque no todos los módulos del sistema tendrán la misma criticidad. En este sentido, es posible definir distintos Quality Gates para distintos módulos, y es posible ajustar las reglas en las que se basa el análisis estático.

 

¿Tenés este tipo de análisis en tu delivery pipeline? Para comenzar podrías ir viendo primero este post y luego este.

Leave a Reply

Your email address will not be published. Required fields are marked *