C√≥digo Muerto ūüíÄ

Una de las an√©cdotas m√°s comunes de un proyecto de software es que siempre hay una clase o una funci√≥n que ser√° recordada por el n√ļmero de l√≠neas que esta tuvo. Estoy seguro de que al menos una vez hemos escuchado:

“No toques esa clase, tiene como 1000 l√≠neas de c√≥digo”

Developer anónimo

Este es un dato particular de acuerdo a los proyectos en los que estuve y conversaciones entre amigos. Lo que es menos com√ļn, es saber cu√°ntas l√≠neas de c√≥digo tiene el proyecto en el que estamos trabajando.

Si en este momento nos hacemos esa pregunta o se la hacemos a otro miembro del equipo, es posible de que no consigan una respuesta concreta. Si bien es cierto no considero necesario ser 100% precisos, he notado que pocas personas se preocupan de esa m√©trica, a menos claro, de que haya alg√ļn costo asociado.

Si no les ha pasado, les comento que casos como este se dan desde hace mucho en proyectos donde se audita c√≥digo. Sin ir muy lejos, Amazon liber√≥ [CodeGuru], un servicio (a√ļn en preview) que analiza el c√≥digo fuente. Como es de esperar, el costo est√° asociado al n√ļmero de l√≠neas y no es el √ļnico producto o servicio que hace este [tipo de trabajos]

Fuente: [Amazon CodeGuru]

¬ŅQu√© es lo que regularmente encontraremos?

He participado en proyectos donde el an√°lisis o auditor√≠a de calidad de software era uno de los objetivos m√°s importantes. Muchas veces el costo de servicios adquiridos ‚Äďu ofrecidos‚Äď estaba relacionado al n√ļmero de l√≠neas de c√≥digo (o LoC por [Lines of Code]).

En cada trabajo era com√ļn confirmar lo encontrado en proyectos anteriores:

  1. Pocas personas conoc√≠an el n√ļmero de LoC o la importancia de este indicador
  1. Una pr√°ctica conocida ‚Äďy en algunos casos, aceptada‚Äď era “agregar c√≥digo de ejemplo, ir cambiando y probando pero guardar la versi√≥n original por si algo se malograba”
  1. Muchas veces se mantenían las carpetas de plantillas y ejemplos de las librerías y componentes de terceros que en algunos casos ya no se utilizaban

Ya en un caso concreto, estuve en un proyecto donde el desarrollo tenía más de un millón de LoC y estaba seguro de que eso no podía ser posible pues las funcionalidades del sistema no reflejaban dicha realidad.

Sabía que estaba frente a un caso de Código Muerto, pero tenía que demostrarlo.

¬ŅQu√© es C√≥digo Muerto?

Sin entrar en detalles (pues es posible que encuentren discrepancias y hasta [una canci√≥n]), el c√≥digo muerto o “Dead Code” es aquel que no aporta valor al negocio.

El código muerto se puede clasificar de la siguiente manera:

  • C√≥digo que no se usa: Muy usual en los proyectos de software, algunas veces no se recuerda su objetivo inicial y por lo general ocurre pues las necesidades van cambiando y el c√≥digo no se depura adecuadamente luego de cada cambio (mucho cuidado con las frases “es que no hay tiempo” o “lo vemos despu√©s”)
  • C√≥digo que se ejecuta pero que no se usa: Aqu√≠ entran los casos como los de variables asignadas o llamadas a funciones cuyo resultado no es utilizado. Esto es nocivo pues adem√°s ser c√≥digo in√ļtil, consume recursos del sistema.

¬ŅC√≥mo identificar C√≥digo Muerto?

Con el paso del tiempo prepar√© una secuencia de an√°lisis que me sirvi√≥ para encontrar casos de c√≥digo muerto bajo la premisa de que si algo se define en el programa, este debe ser utilizado de manera efectiva. La lista puede parecer obvia, pero ya est√° demostrado que en tecnolog√≠a no debemos confiar en las obviedades ūüôā

  • Variables
  • Funciones
  • Clases
  • Comentarios (sean redundantes o c√≥digo que fue comentado para ser utilizado “m√°s adelante”)
  • Elementos de archivos de configuraci√≥n (por ejemplo, secciones comentads o que ya no se utilizan)
  • Archivos de configuraci√≥n
  • Librer√≠as (componentes de terceros)
  • Elementos id√©nticos (funciones, clases archivos, librer√≠as o carpetas distribuidos en ubicaciones distintas)
  • Elementos parecidos (librer√≠as con versiones diferentes, funciones o clases que inicialmente eran una copia de la otra)
  • Carpetas y archivos varios que poco a poco quedan relegados hasta el olvido

Un hecho com√ļn en todos los casos, es que el c√≥digo muerto existe debido al temor a perder c√≥digo o a malograr el sistema construido. Esto tiene relaci√≥n directa con el desconocimiento de que los gestores de versiones permiten volver al pasado si es que se necesita ver algo que ha sido borrado.

Otra consecuencia es que a más código muerto, más complejo será el entendimiento de nuestro sistema, la mantenibilidad será afectada y a su vez generará dependencias con un programador en particular (a veces pueden ser más personas). Recuerden, el código es de todos los miembros del equipo y mientras menos dependencias, mejor.

¬ŅQu√© herramientas debemos usar?

Puede que parezca una broma, pero un elemento muy importante es la inspecci√≥n visual. A pesar de ello, esta debe pasar a segundo plano pues debemos evitar confiar totalmente de los presentimientos o “literalmente” de puntos de vista.

De acuerdo a esta premisa, lo primero que debemos hacer es trabajar con [herramientas de an√°lisis est√°tico] que nos brinden un enfoque acertado de lo que est√° ocurriendo.

A pesar de ello, hasta el momento no he encontrado una herramienta que brinde un indicador de código muerto bajo un enfoque holístico. Es así que utilizo principalmente [SonarQube] como base del trabajo a realizar.

Regresando al caso del millón de LoC, encontré pistas que me ayudaron a confirmar la existencia del temible código muerto.

Si queremos empezar con estas prácticas, algo que nos podría ayudar está incluido en las herramientas del navegador web. Una de las que ha llamado mi atención es la utilizada para analizar la cobertura de los archivos JavaScript y CSS. Esta viene en [Chrome] y no es complicado de usar/entender.

¬ŅQu√© consegu√≠ luego de presentar lo encontrado?

El objetivo de mi trabajo en dicho proyecto, fue preparar un informe sobre lo que se estaba construyendo y sobre eso un plan de trabajo para implementar una nueva arquitectura. No me parec√≠a adecuado llegar con una presentaci√≥n llena de indicadores ni menos se√Īalar responsables (aunque en algunos casos ese ha sido mi trabajo), as√≠ que gracias al apoyo y explicaciones que el equipo dio cuando estaba analizando el c√≥digo, ten√≠a el conocimiento necesario para “limpiarlo”, al menos en casos que parec√≠an obvios o donde ve√≠a que complejidad baja o media.

Como este tipo de trabajos me gustan, no par√© hasta eliminar 95% del c√≥digo del sistema. No esperaba llegar a ese n√ļmero pero m√°s de un mill√≥n l√≠neas era c√≥digo muerto que se pod√≠a limpiar f√°cilmente.

Nada mejor que llegar con un informe que tenga un entregable como ese ūüôā

La buena noticias es que el equipo quedó sorprendido. Cuándo me preguntaron cómo lo hice, les comenté que empecé por las obviedades (y ya saben lo que pienso de ellas :)) creo que eso los animó a seguir limpiando (luego de una segunda limpieza el código no superaba las 30 mil LoC)

¬ŅQu√© es lo que aprend√≠?

  • Es posible que este tipo de trabajos sea incomprendido al principio, pero se consigue mucho ense√Īando con el ejemplo. En dicho proyecto ten√≠a que preparar una arquitectura que aproveche lo que ya estaba construido, pero ante las sospechas de c√≥digo muerto, decid√≠ detenerme un momento y evaluar c√≥mo eliminarlo, primero por mi cuenta y luego con el equipo.
  • Lo que he encontrado en muchos casos, es que hay pocas intenciones de refactorizaci√≥n que a veces no se dan por el uso desmedido de frameworks y herramientas. Lo que creo que se debe hacer es sentar una base medible de lo que est√° sucediendo sin olvidar que lo m√°s se hace en un proyecto de software es la construcci√≥n del mismo. Si es as√≠ ¬Ņpor qu√© no saber c√≥mo va creciendo nuestro c√≥digo?
  • La automatizaci√≥n de pruebas es muy importante pero esta se debe postergar si hay casos obvios de c√≥digo muerto, he comprobado que a veces resulta m√°s r√°pido borrar (sin miedo) que ponermos a programar un caso de prueba.
  • Siempre debemos utilizar un gestor de versiones (personalmente prefiero Git sobre GitHub) y tenerlo enlazado a un motor de automatizaci√≥n (como [Jenkins] o [Azure DevOps], ambos me parecen buenos y Azure DevOps es m√°s sencillo de configurar) que ayude a tener visibilidad de la integraci√≥n continua.
  • El equipo de desarrollo pasa a otro nivel de conocimiento, pues adem√°s de entender la importancia de pr√°cticas de limpieza de c√≥digo muerto se abre una nueva puerta hacia la calidad del producto.
  • Si la confianza y comunicaci√≥n son las adecuadas, este tipo de situaciones se convierten en an√©cdotas del equipo.

¬ŅCu√°l fue mi reflexi√≥n final?

Antes de refactorizar o hacer lo que sea en el sistema, eliminen el Código Muerto, no teman.

Un abrazo,

Fuente imagen cabecera: [Finding Dead Code]

1 Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.