#252 Metrics Metrics Metrics
Mediante el cálculo de métricas de código podemos encontrar qué partes de nuestra aplicación pueden mejorarse. Una de las herramientas definitivas para obtener este tipo de métricas en Ruby es metric_fu, que ya vimos en el episodio 166 [verlo, leerlo (en inglés)]. El único problema que tiene esta gema es que es algo complicada de instalar porque tiene muchas dependencias, sobre todo para usarla en una aplicación Rails 3. El Proyecto Caliper era una alternativa interesante porque podía acoplarse a cualquier proyecto en GitHub para obtener sus métricas, pero por desgracia el sitio ha cerrado.
Así que aquí estamos de vuelta, teniendo que ejecutar las métricas en nuestra máquina local. Ahora existe una gema llamada Metrical que facilita esta tarea. Metrical utiliza metric_fu en segundo plano, proporcionando además una herramienta de línea de órdenes que hace más fácil su uso.
Vamos a hacer una demostración de Metrical ejecutándola contra el código fuente del sitio web de Railscasts. Primero vamos a instalar la gema Metrical.
$ gem install metrical
Con la instalación de esta gema también se instalarán otras dependencias. Una vez que estén todas podemos ejecutar la orden metrical
desde el directorio de nuestra aplicación, lo que evaluará varias métricas sobre el código fuente de la aplicación utilizando metric_fu
. Cuando lo hagamos probablemente nos encontremos varios errores, pero los podemos ignorar en su mayoría siempre que la orden termine correctamente, lo que sabremos porque los resultados se abrirán en nuestro navegador.
La primera página enumera las diferentes herramientas de medición de que dispone metric_fu
, y podemos hacer clic en cualquiera de ellas para ver los resultados que ha generado. Por ejemplo si nos fijamos en Reek veremos mucha información útil sobre áreas de la aplicación que se pueden mejorar.
Veamos a continuación otra de las herramientas, RCov. De todas las métricas que utiliza Metrical, RCov es la que casi con toda seguridad fallará porque requiere ejecutar los tests y especificaciones de la aplicación. Si ejecutamos RCov sobre el código de Railscasts, se calculará una cobertura del 0.0%. El problema aquí es que el código utiliza Ruby 1.9, que todavía no está soportado por RCov. Antes de buscar alternativas tendremos que quitar RCov de nuestro juego de métricas. Para configurar el comportamiento de metric_fu
bajo Metrical podemos añadir un fichero .metrics
en el directorio de nuestra aplicación
MetricFu::Configuration.run do |config| config.metrics -= [:RCov] end
Si ahora ejecutamos metrical
veremos menos errores porque la sección de RCov ya no aparece en los resultados. Pero es muy importante saber la cobertura de tests de nuestro código, así que ¿qué podemos utilizar en lugar de RCov? Hay varias alternativas que podemos usar, CoverMe y SimpleCov. Las dos producen buenos resultados, pero nosotros escogeremos usar SimpleCov porque es un poquito más fácil de configurar. Primero tenemos que añadir la referencia a la gema en el Gemfile
.
group :test do gem 'simplecov', '>=0.3.8', :require => false end
A continuación añadiremos las siguientes dos líneas al fichero helper de tests o especificaciones:
require 'simplecov' SimpleCov.start 'rails'
Como siempre, cuando añadimos una gema a una aplicación tenemos que ejecutar bundle
para que dicha gema quede instalada. Después de lo cual podemos ejecutar rake spec
para lanzar los tests de la aplicación y luego open coverage/index.html
para ver los resultados.
Es muy fácil ver qué ficheros son los que tienen más código que no está cubierto por tests o especificaciones porque son los que aparecen en la parte superior. Si hacemos clic en uno de ellos, por ejemplo comments_controller
, podemos ver exactamente qué parte del código no se encuentra cubierta por ningún test.
Con esto podemos ver exactamente para qué código tenemos que escribir más tests.
Ya tenemos una buena solución para la cobertura de código, por lo que ahora veremos las otras dos métricas que proporciona metric_fu, el Informe de Buenas Prácticas ("Best Practices Report") y los Puntos Calientes ("Hotspots").
En la vista de puntos calientes vemos un repaso de varios archivos, clases y métodos, apareciendo los peores en primer lugar. Para determinar cuáles son mejores y peores se tienen en cuenta varios factores, principalmente Reek y Flog, por lo que este es un buen sitio para descubrir qué partes de nuestra aplicación requieren que les dediquemos más atención.
El informe de buenas prácticas de Rails nos dice si nuestra aplicación no cumple con ciertas buenas prácticas de uso general.
La salida de este informe resulta un poco rara cuando se abre en el navegador, pero podemos usar la gema directamente en vez de a través de metric_fu. Como ya hemos instalado Metrical esta gema ya deberíamos tenerla pero si no es así podemos instalarla ejecutando
$ gem install rails_best_practices
La orden anterior nos sugiere visitar el sitio Rails Best Practices , así que le haremos caso.
En este sitio se enumera una larga lista de buenas prácticas que podemos inspeccionar y utilizar en nuestras propias aplicaciones Rails. Bajo la pestaña “Implemented” aparecen las prácticas cuyo uso detecta la gema y que son las que se comprobarán cuando ejecutemos la orden rails_best_practices
.
Si ahora ejecutamos la orden veremos una serie de sugerencias en rojo.
$ rails_best_practices Analyzing: 100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00 <span style="color:#C00;">./app/controllers/comments_controller.rb:53 - move model logic into model (errors use_count > 4) ./app/views/comments/index.rss.builder:10 - law of demeter ./app/views/comments/index.rss.builder:10 - law of demeter ./db/schema.rb:15 - always add db index (comments => [user_id]) ./db/schema.rb:71 - always add db index (spam_reports => [comment_id]) ./app/controllers/comments_controller.rb:28,32,41 - use before_filter for edit,update,destroy ...</span>
El texto rojo puede ser difícil de leer, pero cambiando las opciones podemos pedir que la salida sea en HTML y también podemos hacer que los nombres de fichero sean enlaces para abrirlos en TextMate.
$ rails_best_practices -f html --with-textmate
Esto generará un archivo en HTML llamado rails_best_practices.html
que podemos abrir con un navegador.
El análisis ha encontrado 26 problemas en esta aplicación. Si hacemos clic en cualquiera de los ficheros, éste se abrirá en TextMate. Haciendo clic en el mensaje de error iremos a la página del sitio web donde se nos describe el problema correspondiente y cómo podemos refactorizar nuestro código para solucionarlo. Con todo esto ya tenemos una lista sobre la que trabajar e ir mejorando nuestro código.
Como con toda métrica, estas recomendaciones no deberían tomarse como palabra de Dios. El que una técnica particular sea considerada una buena práctica en general no quiere decir que sea lo mejor para nuestra aplicación. Debemos tomar la lista generada como una guía general para encontrar los sitios de nuestra aplicación que podemos mejorar, pero no deberíamos obsesionarnos con dejar dicha lista vacía, igual que con el resto de métricas que hemos visto. No debemos incorporar todas estas sugerencias sin analizar si son convenientes para nuestra aplicación y si mejoran el código de la misma. Las métricas sólo son pistas que nos indican cómo mejorar el código, nada más.