La deuda técnica en software: una cuestión de presente para abordar el futuro
El objetivo fundamental cuando comenzamos la fase de ideación de software es aportar soluciones a cuestiones que plantean los usuarios del producto software. Pero la forma en la que se desarrolla ese software influirá en su capacidad de adaptación a nuevas necesidades y, con ello, a la generación de futuras versiones. Para lograr un software sostenible a largo plazo será clave que nuevos desarrolladores puedan entender cómo está codificado el sistema y sean capaces de ampliarlo, evolucionarlo o actualizarlo. Es aquí donde aparecen dos conceptos: el código legado y la deuda técnica.
La definición estricta de código legado es un código que ha sido creado por alguien y posteriormente debe ser mantenido por otros desarrolladores. Esto en sí no tiene por qué suponer un problema, siempre que el código cumpla con ciertas reglas para que, si un tercero tiene que hacerse cargo, pueda entenderlo y adaptarlo a las necesidades sin que suponga un enorme lastre en cuanto a inversión de tiempo.
El código legado es, sin duda, un asunto importante que puede preocupar a un ingeniero de software, pero la verdadera preocupación a la hora de asumir el mantenimiento o desarrollo de un software preexistente viene dada por la deuda técnica.
¿Qué es la deuda técnica?
En 1992, Ward Cunningham, programador y coautor del Manifiesto por el desarrollo ágil de software, introdujo el concepto de la deuda técnica. Cunningham quería ilustrar la importancia que la refactorización, es decir la corrección regular del código, tiene para el software. Solo de esta forma es posible evitar que un software genere más deuda con el tiempo debido a las crecientes deficiencias operativas y estructurales. La deuda técnica se da cuando se diseña una solución con mentalidad cortoplacista, o economizando en exceso los recursos, pudiendo responder a los requerimientos, pero sin pensar en contar con una estructura de código que sea legible para los futuros desarrolladores o que lo sea sin requerir un gran mantenimiento. Desarrollar software bajo esta premisa supone a la larga un gran lastre, ya que, para evolucionar ese software, primero habrá que resolver aquellas partes que no se optimizaron o se resolvieron de forma “chapucera”.
Es por eso que es fundamental contar con una ingeniería de software que se responsabilice no solo de resolver los requerimientos establecidos, si no de hacerlo de manera sostenible. Todo software debe evolucionarse y algunas de estas evoluciones afectarán a la parte que ya está construida, lo importante es que, si llega ese punto, quien tenga que acometer estos cambios, sea capaz de hacerlo a partir de lo que tiene de la forma más sencilla posible, porque quien lo diseño ya pensó en esa posibilidad. Si no es así, quien venga tendrá que encontrar un parche para solucionar determinada cuestión y esto irá lastrando el sistema. Afrontar la creación de sistemas desde esta perspectiva requiere disciplina y una mayor inversión de horas, pero a larga será más rentable.
Es fundamental tener en cuenta los diferentes escenarios en los que el software deberá ser capaz de operar, intentando evitar ser restrictivos en la resolución concreta de los requerimientos de los usuarios.
Lo importante cuando nos enfrentamos a la creación de un nuevo sistema software es intentar que, a lo largo del tiempo, según el producto evoluciona y crece, la deuda técnica tienda a cero. Para ello es fundamental tener en cuenta los diferentes escenarios en los que el software deberá ser capaz de operar, intentando evitar ser restrictivos en la resolución concreta de los requerimientos de los usuarios.
Podemos resolver una funcionalidad para un entorno muy acotado y previamente descrito, pero en ese caso, lo que probablemente suceda es que, si posteriormente el ámbito de aplicación de ese sistema varía, el sistema no será capaz de operar en ese nuevo entorno. Por ejemplo, para resolver un problema de conectividad entre máquina y taller, decidimos diseñar un sistema que comunique ese modelo de máquina específica con el sistema operativo del ordenador que utilizan en taller ¿qué pasará cuando cambien de ordenador o de modelo de máquina? ¿Y cuándo incluyan más maquinaria o más ordenadores? Probablemente haya que cambiar de software, hacer un trabajo extra de desarrollo…con lo que el ingeniero de software se encuentra en un constante dilema, entre la priorización de los esfuerzos necesarios para preparar los sistemas para que sean capaces de adaptarse a cualquier situación futura y los costes que esto tiene aparejados.
El objetivo es tener en cuenta aquellas cuestiones que previsiblemente pueden plantearse en la mayoría de los casos. A la larga, esto supondrá una drástica reducción de las horas dedicadas a mejorar funcionalidades o implementar nuevas.
La cuestión que nos planteamos es si la deuda técnica (que se mide en términos de esfuerzo, y por lo tanto de costes financieros del producto) puede tender a cero y la respuesta es sí. Lo que es complicado que no exista legacy code, es decir la cantidad de código utilizado para un software que se va heredando al seguir trabajando en ese sistema. Es bastante común que ese código tenga que ir cambiando, se tengan que ir produciendo mejoras de todo tipo. Pero sí la solución, y por tanto el código, está diseñado para ser sostenible estos cambios serán relativamente fáciles y no supondrán grandes esfuerzos mantener la deuda técnica al mínimo, será una inversión de tiempo y dinero acorde al éxito del producto o sistemas que mantenemos y evolucionamos. Sin embargo, la deuda crece cada vez que se cambia el código de forma no sostenible.
Para un ingeniero de software, el cuidado y mantenibilidad del código fuente debe ser su mayor obsesión
La clave está en dedicar el tiempo necesario no solo para plantear las necesidades que a futuro este software deberá resolver, sino también a desarrollar ese software asegurando la integridad técnica, que el software siempre parezca diseñado y desarrollado por la misma mano, y la integridad conceptual que todas las partes del sistema se comporten de una manera similar, es decir que la experiencia del usuario sea igual impedientemente que use las partes más antiguas, o las partes más recientes. Dado que el sistema está evolucionando y adoptándose continuamente, provocará que se restrinjan las posibles soluciones de los nuevos desarrollos a orientaciones técnicas que puedan será aplicados tanto para el nuevo código como para la parte más legacy del sistema.
Por lo tanto, para un ingeniero de software, el cuidado y mantenibilidad del código fuente debe ser su mayor obsesión, aplicando las buenas prácticas de la ingeniera de software harán que en el futuro sea más sencillo de entender y extender para un tercero. Si este trabajo se hace de manera ortodoxa nuca será problema heredar código, ya que habremos reducido la deuda técnica al máximo.
En cualquier caso, esto no significa que la vida del código de un sistema puede llegar a ser infinita, probablemente lleguemos a un momento en el que haya que empezar casi de cero. La clave es intentar que retrasar ese momento lo máximo posible. Cuanto más se alargue ese ciclo de vida, más exitoso habrá sido el producto, tanto para stakeholders, usuarios e ingenieros de software.