Manejando la deuda técnica

Desmitifiquemos el término para entender las ventajas que nos da estar concientes de la deuda técnica en nuestros proyectos y cómo planear la mejora continua

Introducción

Durante la vida de un proyecto, ya sea desde cero o un código legado, se agrega complejidad al código base del proyecto

Desde el punto de vista de un programador, este problema se ve reflejado directamente como código espagueti, pero esto en realidad va mas allá. En general los problemas que esto trae al equipo son:

  • Fallos en pruebas de regresión - Cada vez que tocamos o modificamos algo, otro componente se rompe
  • Es complejo integrar nuevos cambios - Ya sea que las estimaciones varian demasiado o simplemente es complejo agregar la mas mínima modificación al código
  • Dependencia a un recurso en particular del equipo - Sólo una persona (o un grupo de personas) son de confianza para hacer cambios en el código fuente
Código espagueti

Seamos conscientes

Externar este tipo de deficiencias al negocio no es sencillo, y podemos escuchar comentarios como los siguientes:

  • ¿Por qué no lo hicimos bien la primera vez?
  • ¿Qué nos asegura que esta vez quedará bien?
  • ¿Cuáles son los riesgos que podemos introducir con estos cambios?
  • ¿Cuál es el valor que agrega esto al negocio?

Si bien estos comentarios son válidos, les hace falta la perspectiva del equipo técnico, y para poder llegar a un punto intermedio, se requiere tener buena comunicación y un plan de acción. Recuerda, si el negocio no entiende bien las implicaciones técnicas, es nuestra responsabilidad tener al menos un plan inicial con el cual podamos avanzar

Salud del proyecto

Primero debemos definir como vamos a medir la salud del proyecto, a continuación listaremos algunos de los parámetros mas comunes para tener en cuenta en este tipo de mediciones, sin embargo, estas tendrán que ser discutidas y refinadas para cada proyecto y equipo, pero sirven como un punto de partida

Calidad de código

La calidad del código es un tema muy grande, asi que vamos a delimitarlo a las mediciones clásicas:

  • Análisis de código estático - Nos da una perspectiva del uso de buenas prácticas e indican si existe algún problema potencial (code smell) o de seguridad
  • Code style - Aunque utilicemos buenas practicas, el estilo de programacion puede variar un poco, desde la indentaciòn, uso de llaves, los nombramientos de componentes y variables, etc. Es importante mantener una consistencia en el equipo para reducir riesgos de conflictos durante un merge y facilitar la lectura y navegación en el código

Pruebas

Cada proyecto requiere definir cuales son las pruebas que le brindan mayor confianza al momento de aplicar cambios, pero podemos listar algunas de las pruebas más comunes son:

  • Pruebas unitarias - Prueba sobre cada uno de los componentes a bajo nivel
  • Pruebas de integración - Consumo de servicios a terceros para validar que los componentes relacionados en el downstream sean confiables
  • Pruebas end-to-end - Agregan perspectiva al equipo para validar que desde el click de un boton se realice la dispersion de informacion adecuada entre sistemas y el flujo sea aceptable desde la perspectiva de UX

Cobertura de pruebas

El conjunto de pruebas y la calidad de éstas son las que brindan seguridad en términos de regresión, pero debemos entender que tener un alto nivel de cobertura tampoco garantiza que los cambios sean a prueba de balas. Para esto podemos considerar:

  • ¿Qué tantos componentes tienen pruebas?
  • De los componentes con pruebas ¿Cuántos de esos son de misión crítica? - Por ejemplo, en un comercio electrónico, el proceso de compra es de misión crítica

Documentación

Generalizando un poco, si tenemos un integrante nuevo en el equipo y le resulta complicado entender el negocio, el código o la arquitectura de la solución, es muy posible que haya una falta de documentación sobre alguno de los componentes mencionados

Podemos definir una base de conocimientos inicial constituida por lo siguiente:

  • Topología de la arquitectura del proyecto
  • Integraciones, tipos (sincronos o asincronos), protocolos y contrato del servicio al cual se integran
  • Entidades - atributos y tipos de datos utilizados en el sistema
  • Tareas programadas - Lista de tareas programadas, frecuencia y objetivos

Vendiendo la idea

Ahora que tenemos un análisis inicial sobre nuestro sistema, podemos agregar un puntaje a cada area, esto nos dirá que tan sano se encuentra nuestra solución, por ejemplo:

  • calidad de código: 80%
  • pruebas: 30%
  • cobertura: 10%
  • documentación: 10%

Como puedes observar, incluso en un proyecto donde la calidad de código es alta, la falta de pruebas, cobertura de pruebas y documentación pueden empeorar el estado de nuestro proyecto. Porque recuerda, en este punto no estamos hablando sólo del código, hablamos de la eficiencia del equipo para realizar cambios y los riesgos que estos conllevan

Teniendo esto en mente, podemos comenzar a mostrar estos indicadores al negocio para hacerles saber que podríamos reducir riesgos y aumentar la productividad del equipo si mejoramos la situación actual del sistema

Algunas formas de comenzar a agregar el peso de estas mejoras durante una iteración del producto, sin introducir tantos riesgos en los componentes comprometidos son:

  • Refactorización constante - Desde el punto de vista del código, podremos utilizar el clásico "si lo tocas, lo compones", es decir, si te toca una tarea relacionada a un componente que sabemos que tiene deficiencias, es necesario que realices las mejoras que se hayan identificado
  • Uso de documentación de diseño técnico (TDD) - Documentar a alto nivel cual es la solucion que se le dará a los problemas que se estan enfrentando
  • Utilizar especificaciones como OpenAPI con herramientas como Swagger para el diseño de REST APIs - Permite definir los contratos de las APIs e incluso la generación de código del cliente y request handler
  • Crear tareas para el proceso de integracion continua para tener datos de series de tiempo para medir que tan bien se encuentra la solución y que tanto estamos avanzando en el proceso de mejora
  • Si el nivel de las pruebas es bajo y no es una práctica común en el equipo, podrían considerar implementar con una bandera para activar los cambios (conocido como feature flag o feature toggle)

Conclusiones

Debemos ser conscientes del nivel de deuda técnica que tenemos en nuestro proyecto para poder seguir agregando nuevos módulos y reparando bugs, esto le da un valor directamente al negocio reflejado en la eficiencia del equipo y el nivel de confianza cuando publicamos cambios

Y como programador, debemos recordar que no necesariamente un código bonito lleva a un proyecto sano y fácil de escalar en un equipo

Carlos Jose Martinez Arenas

Carlos Jose Martinez Arenas

Enamorado de la tecnología, con interés en machine learning, código limpio, buenas prácticas y arquitectura de sistemas; música y cine; naturaleza, espacios abiertos y los perritos