Code-forensics - Herramienta de análisis dinámico de código (Introducción y llamado a contribuciones)


(Gonzalo Bulnes) #1

Hola a todos, todas,

Esta nota trata de una técnica que encuentro muy interesante y que se ha estado desarrollando en los últimos años, llamada análisis dinámico de código. Explico de qué se trata, para qué sirve, y presento el trabajo de un colega mío. También es una oportunidad para cualquier persona interesada en contribuir en un proyecto de código libre, con un enfoque en ingeniería de software y su aplicación a hacer equipos más felices y productivos.

Sin duda tiene más interés para equipos que mantienen cantidades ce código mayores (de mediana cantidad a grande), pero creo que la lectura puede ser interesante aunque no tengas mucho en qué aplicarla… A mí al menos me impresionó mucho la primera vez que lo vi en acción.

Intro

El presente: análisis estático de código

Las herramientas de análisis estático de código (por ej. Code Climate, Rubocop, go vet…) permiten permiten hacerse una idea de la calidad del código que escribimos. Permiten generar una gran cantidad de indicadores basados en una amplia gama de análisis distintos: análisis de complejidad, validación de sintaxis o de estilo, detección de código duplicado o cantidad de líneas de código contenidas en cada archivo… Esa es su fuerza, pero esa es también su debilidad. A menudo las advertencias y errores no reflejan correctamente la gravedad de la situación y muchas veces los errores importantes terminan pasando desapercibidos entre los errores benignos.

Se llaman herramientas de análisis estático porque analizan el estado del código en un momento dado (de alguna forma son como una “foto” del código).

El futuro: análisis estático + análisis dinámico de código

Silvio Montanari (Redbubble), está trabajando en una colección de herramientas para facilitar el uso de análisis dinámico de código y acaba de publicarlas. (Github: code-forensics)

Su trabajo está basado en las ideas expuestas por Adam Tornhill en su libro Your Code as a Crime Scene. Esas ideas son:

  • como equipos de desarrollo de software, usamos control de versiones (ejemplo: git - hay soporte para git)
  • git guarda registro de cómo el código cambia a lo largo del tiempo, cuan a menudo cambia y quién lo cambia (¡una “película” del código además de las fotos! :heart_eyes:)
  • extraer la información de git es relativamente fácil (Adam escribió herramientas para eso)
  • analizar esa información provee indicadores de cuan importantes pueden ser los problemas detectados durante el análisis estático

Interés del análisis dinámico de código

Con ejemplos todo es más fácil ; )

Ej. 1: Ponderar la “calidad” del código

Imaginemos un archivo con funciones complejas (casi ilegibles, grado “F” en Code Climate). Tiempo estimado de refactoring: 8 horas.

  • Ha sido editado dos veces en los dos últimos años: quizás no vale la pena refactorizarlo y es mejor dedicar esas 8 horas a otra actividad de mayor impacto.
  • Cambia mensualmente y su complejidad ha ido creciendo constantemente durante el último año: quizás valga la pena refactorizarlo ahora en vez de perder una hora mensualmente y terminar refactorizándolo durante 12h en seis meses.

Ej. 2: Detectar dependencias no obvias entre piezas de código

Cuando una aplicación crece y abarca múltiples áreas de negocio, conviene identificar y mantener distintas las partes del código encargadas de soportar cada una de ellas (en inglés). Pero el acoplamiento no siempre es fácil de detectar. El análisis dinámico de código permite destacar entre todos los archivos de la aplicación, cuales vale la pena investigar.

Supongamos por ejemplo que los archivos app/controllers/promotions_controller.rb (A) y lib/search/queries_sanitizer.rb (B) no tienen a priori ninguna dependencia entre si. Pertenecen a dos partes muy distintas del código de la aplicación y los mantienen dos equipos diferentes.

Sin embargo, basándose en la información del último año, cada vez que se modifica el archivo A (una vez a la semana en promedio), existe una probabilidad de 77% de que se modifique el archivo B. Puede que sea una coincidencia, pero también puede ser que el diseño de la aplicación lleve esas dos piezas de código a estar íntimamente relacionadas. Si la correlación es suficientemente alta, puede valer la pena dedicar un par de horas para confirmar o no la existencia de una dependencia oculta antes de que se vuelva demasiado cara de resolver

Ej. 3: Hablemos de equipos!

El texto, código, etc. es una cosa, pero donde esto se vuelve realmente interesante es cuando un uso astuto de la información disponible permite aumentar la felicidad de las personas.

Sabemos que la comunicación es clave en cualquier equipo que emplee métodos de trabajo ágiles (“Individuos e interacciones…”).

Visualicemos los archivos del área de búsqueda (lib/search/* y app/models/search*.rb), y asignemos un color a cada miembro de nuestro equipo (escalas de verde para el equipo de búsqueda, tonos de rosa para el equipo de productos, serie de azules para el equipo encargado de la experiencia de compra).

Cada archivo recibe el color de la persona que lo modificó más a menudo durante los últimos seis meses. La expectativa es que todos los archivos del área de búsqueda sean de algún tipo de verde. La realidad es que pueden pasar muchas cosas, entre ellas:

  • Todos los archivos del área de búsqueda son verdes: bien, el equipo de búsqueda está manteniendo esos archivos, nada que señalar.
  • El archivo lib/search/categories.rb es rosado. Será que cada vez que se lanza un nuevo producto ese tiene que actualizar la definición de las categorías de búsqueda? Si es así, la expectativa es que el equipo de búsqueda y el de productos estén hablando a menudo. No cuesta nada confirmarlo. Y si no lo están haciendo, organizar media hora de sincronización semanal probablemente ayude a evitar cambios inesperados, bugs y frustración en ambos equipos. Un análisis puramente estático del código no hubiera entregado esa información.

Hay muchos más ejemplos, y falta inventar aún más. Explotar los resultados de análisis dinámico de código es una disciplina que está naciendo.

El trabajo de Silvio y cómo puedes ayudar

Hay una cosa cierta acerca de las herramientas de control de versiones: entregan una cantidad masiva de información, tanta que no hay chance de sacar nada útil de esa información mirando solamente las columnas de números, se tienen que utilizar herramientas gráficas para interpretarla.

Silvio ha estado componiendo una colección análisis configurables para hacer la tarea más fácil (capturas de pantalla? están aquí). Todos los análisis son interactivos, y cada uno está detalladamente documentado en la wiki del proyecto (en inglés). Si quieres entrar al mundo del análisis dinámico de código, es un excelente lugar donde empezar.

Estos son análisis que Silvio ha diseñando para explorar la parte central de nuestro código (una aplicación Rails de 10 años de edad que sirve a muchos millones de compradores y artistas independientes mensualmente. Es mucho código y en algunas partes es código más complejo de lo que quisiéramos). Están basados en la experiencia de Silvio como ingeniero y como líder técnico en un equipo que ha cambiado mucho el los últimos diez años.

Las encontramos útiles, pero queremos validación. Nos interesa saber qué tipos de análisis encuentras más interesantes en un equipo como el tuyo, con un código con las características del tuyo.

Silvio describe code-forensics como "un poco de Javascript para procesar la información producida por Code Maat" (la herramienta que mantiene Adam). Está escrito de forma modular usando NodeJS y la biblioteca D3. Es código libre.

La documentación es impresionante (mi opinión), el área es muy interesante y estamos seguros que se va a desarrollar en los años que vienen. Es la clave para llegar con datos a momento de justificar inversión en refactoring, y es clave para identificar las métricas que permiten medir el éxito de refactorings complejos.

Puedes contribuir usando las herramientas en tu código, compartiendo tus ideas (abrir issues en Github es la mejor forma de hacer la discusión abierta para todos), contando cómo usas la información para mejorar la organización de tu equipo y la distribución del esfuerzo que le dedica a tu código. Hablemos aquí, hablemos en Github? :wink: