Underc0de - Hacking y seguridad informática

Programación Scripting => Otros lenguajes Scripting => Mensaje iniciado por: DUDA en Abril 27, 2017, 11:58:04 am

Título: CodeNarc: Análisis estático de código Groovy
Publicado por: DUDA en Abril 27, 2017, 11:58:04 am
(https://i.blogs.es/b10ece/codenarc-logo/1366_2000.png)

Cuando escribimos código es importante seguir ciertas normas, buenas prácticas, reglas de estilo, coherencia en el mismo,... pero en ocasiones esto no es tan fácil, y más cuando trabajamos en un equipo en el que, al final, cada miembro tiene ciertas manías. Una forma de mejorar todo esto es utilizando un analizador estático de código.

Para Java tenemos ciertas herramientas como FindBugs, PMD y Checkstyle que llevamos utilizando durante mucho tiempo, pero tienen el problema de que con Groovy (http://groovy-lang.org/) no funcionan correctamente. Para suplir esta necesidad aparece CodeNarc. (http://codenarc.sourceforge.net/)

CodeNarc es un analizador estático de código Groovy que permite detectar defectos, malas prácticas, inconsistencias, problemas con el estilo del código,... y mucho más. Se trata de un framework muy flexible que por medio de reglas fácilmente configurables analiza nuestro código para mostrarnos un detallado informe a fin de que podamos mejorarlo.

Añadiendo CodeNarc a nuestro proyecto

Ok, nos hemos decidido a mejorar nuestro código Groovy, ¿cómo añadimos CodeNarc al proyecto? Tenemos diversas formas de añadirlo según nuestras necesidades y tipo de proyecto:

Tipos de reglas

La última versión de CodeNarc, la 0.27.0, incluye 348 reglas (http://codenarc.sourceforge.net/codenarc-rule-index.html) agrupadas en 22 categorías:
Y existen muchas más como algunas que comprueban imports duplicados, variables sin utilizar, if innecesarios,...

Veamos un ejemplo

Configuración mínima

He creado un pequeño proyecto de ejemplo (https://github.com/genbetadev/codeNarc-example) basado en Gradle con la configuración necesaria y unas cuantas clases con distintas infracciones para poder comprender mejor cómo funciona CodeNarc. Podeis ir revisando los commits (https://github.com/genbetadev/codeNarc-example/commits/master) de manera individual para comprender mejors los cambios.

Lo primero que hacemos es añadir el plugin al archivo build.gradle y configurarlo:

Código: [Seleccionar]
apply plugin: 'codenarc'
...

codenarc {
    toolVersion = '0.27.0'
    configFile = new File(projectDir, 'config/codenarc/rules.groovy')
    reportFormat = 'html'
}

Ahora añadimos el archivo de las reglas. Como veis he habilitado unas cuantas.

Código: [Seleccionar]
ruleset {
    description 'Example Project RuleSet'

    ruleset('rulesets/basic.xml')
    ruleset('rulesets/braces.xml')
    ruleset('rulesets/convention.xml')
    ruleset('rulesets/design.xml')
    ruleset('rulesets/dry.xml')
    ruleset('rulesets/exceptions.xml')
    ruleset('rulesets/formatting.xml')
    ruleset('rulesets/generic.xml')
    ruleset('rulesets/imports.xml')
    ruleset('rulesets/naming.xml')
    ruleset('rulesets/unnecessary.xml')
    ruleset('rulesets/unused.xml')
}

Con esto ya podemos empezar con el análisis del código. Sólo tenemos que ejecutar la tarea check para comprobar (en las primeras dos tareas) que se está ejecutando CodeNarc (codenarcMain) tanto para nuestro código como para los tests (codenarcTest). Eso sí, como no tenemos nada en el proyecto el informe no se ha generado.

Código: [Seleccionar]
$ ./gradlew check
:codenarcMain NO-SOURCE
:codenarcTest NO-SOURCE
:compileJava NO-SOURCE
:compileGroovy NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:compileTestJava NO-SOURCE
:compileTestGroovy NO-SOURCE
:processTestResources NO-SOURCE
:testClasses UP-TO-DATE
:test NO-SOURCE
:check UP-TO-DATE

BUILD SUCCESSFUL

Total time: 0.67 secs

Añadiendo código de dudosa calidad

Vamos a empezar con algo muy sencillo, simplemente creamos la clase src/main/groovy/demo/Example1.groovy con lo siguiente:

Código: [Seleccionar]
package demo

class Ejemplo1 {

}

Si ahora ejecutamos de nuevo la tarea check podemos comprobar que se genera el informe con las infracciones y que además la build falla.

(https://i.blogs.es/702e8f/codenarc-report_01/1366_2000.png)

Primer encontramos un bloque con la fecha de ejecución y la versión de CodeNarc con la que se ha generado el informe. A continuación tenemos un bloque de resumen por paquete con el total de archivos con infracciones y también el total de infracciones de prioridad 1, 2 y 3. Después tendremos un bloque por cada archivo en el que vemos todas las infracciones del archivo con la línea de código en donde están y un pequeño fragmento del mismo. Además el nombre de la regla es un enlace a una descripción un poco más detallada de lo que significa.

Añadiendo más código

Creamos a continuación otro archivo en src/main/groovy/demo/Example2.groovy:

Código: [Seleccionar]
package demo

class Example2 {

    boolean isEvenNumber(Integer number) {
        if (number % 2 == 0)
            println "The number $number is even"
        else
            println "The number $number is odd"
    }

    void lorem() {
        println 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis volutpat fermentum enim. enean in viverra arcu.'
    }
}

Y si ejecutamos de nuevo CodeNarc vemos que tenemos nuevas infracciones: Sentencia if sin llaves, sentencia else sin llaves y longitud máxima de una línea.

(https://i.blogs.es/eb3902/codenarc-report_02/1366_2000.png)

Configurando y deshabilitando reglas

Lo primero que queremos evitar es que CodeNarc haga que falle la build cuando tenemos alguna infracción. Para ello, añadimos a la configuración en build.gradle:

Código: [Seleccionar]
codenarc {
    ...

    ignoreFailures = true
}

Ahora ejecutándolo de nuevo veremos que la build no falla. Aún así seguimos teniendo infracciones con las que puede que no estemos de acuerdo o que queramos personalizar de cierta forma.

Vamos a deshabilitar la regla ClassJavadoc porque aunque sea una buena práctica escribir el Javadoc de todas nuestras clases públicas, para este proyecto de ejemplo no nos interesa.
Para ello, primero tenemos que buscar en qué categoría está incluída la regla. Esto podemos hacerlo directamente en el índice de reglas (http://codenarc.sourceforge.net/codenarc-rule-index.html). Después, editamos el archivo de reglas rules.groovy para deshabilitarla:

Código: [Seleccionar]
ruleset {
    ...
    ruleset('rulesets/formatting.xml') {
        'ClassJavadoc' {
            enabled = false
        }
    }
    ...
}

Si ahora generamos de nuevo el informe vemos que hemos "arreglado" esas infracciones.

(https://i.blogs.es/281c65/codenarc-report_03/1366_2000.png)

Adicionalmente, también podemos excluir una regla en una clase concreta. Imaginad que necesitamos la clase vacía creada anteriormente pero no queremos ni desactivar la regla (porque entonces no detectaría más clases vacías) ni queremos tener de manera perpetua esa infracción en el informe. Para ello podemos hacer uso de la anotación @SuppressWarnings de Java:

Código: [Seleccionar]
package demo

@SuppressWarnings('EmptyClass')
class Example1 {

}

Y entonces, sólo para ese archivo esa regla concreta es ignorada:

(https://i.blogs.es/80eb10/codenarc-report_04/1366_2000.png)

Otra opción que tenemos disponible es configurar algunas reglas para adaptarlas a nuestras necesidades. Así, anteriormente vimos en el ejemplo 2 que teníamos una infracción de tipo LineLength porque una línea era mayor de 120 caracteres. Imaginemos que hemos decidido que queremos permitir líneas de hasta 130 caracteres:

Código: [Seleccionar]
ruleset {
    ...
    ruleset('rulesets/formatting.xml') {
        ...
        'LineLength' {
            length = 130
        }
        ...
    }
    ...
}

Haciendo esto "arreglaríamos" de nuevo esta nueva infracción.

¿Y como configuro esto para empezar?

Si no sois muy cuidadosos con el código que escribís y vuestro proyecto tiene cierto tamaño, lo más probable que ocurra nada más instalar CodeNarc es que tengais cientos o incluso miles de infracciones.
Incluso siendo muy escrupulosos es probable que haya algunas reglas que no os gusten o que su configuración por defecto no se adapte a las necesidades del equipo. Mi consejo es que vayais revisando una por una las infracciones, leyendo la documentación de las mismas y decidais si las desactivais, las configurais para que se adapten a vuestro estilo y finalmente, las respetais y corregís.

Una vez decididas las reglas y configuración con las que el equipo se siente cómodo, el paso final será decidir los umbrales para hacer que la build falle. Esto permite tener builds válidas con ciertos niveles de infracciones según la severidad de las mismas pero que, superados esos niveles, la build finalmente falle y os obligue a corregirlas.
Para hacer esto, editamos una vez más el archivo build.gradle:

Código: [Seleccionar]
codenarc {
    // Es necesario eliminar esta opción
    //ignoreFailures = true

    maxPriority1Violations = 0
    maxPriority2Violations = 5
    maxPriority3Violations = 9
}

Así, la build no fallará a menos que superemos alguno de esos umbrales.

Conclusiones

Hemos visto por qué es importante asegurar el estilo y la calidad del código en nuestro proyecto y cómo una herramienta de análisis estático de código como CodeNarc nos puede ayudar a conseguirlo. Además también hemos comprobado que es muy fácil de añadir a un proyecto y de configurar y personalizar para adaptarlo a nuestras necesidades.

Porque en ocasiones no basta sólo con creer que escribimos buen código y además también testearlo (https://www.genbetadev.com/herramientas/testeando-tus-aplicaciones-java-con-spock-tests-mas-expresivos-faciles-de-leer-y-mantener), sino que hay que tener herramientas que nos aseguren su calidad, homogeneidad y estilo. Para todo esto cuando se trata de código Groovy, sin duda CodeNarc es el mejor.

Gracias por leer!
DUDA

Fuente: GenbetaDev