Migración a un registrador con Sensei

Publicado el 30 de noviembre de 2020
por Alan Richardson
ESTUDIO DE CASO

Migración a un registrador con Sensei

Publicado el 30 de noviembre de 2020
por Alan Richardson
Ver recurso
Ver recurso

Migración a un registrador con Sensei

Este post describe la creación de una receta para migrar de System.out.println a usar un Logger de Java.

Cuando estoy hackeando el código, en lugar de usar TDD, y cometo errores, tengo la mala costumbre de imprimir una línea en System.out, y he querido despojarme de ese hábito.

He cometido un montón de errores al escribir el código de abajo :

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


Inicialmente, escribí countdown++ y el bucle no terminó.

Y usé la cuenta atrás > 1 por lo que no obtuve la salida que quería.

Al final, llené mi código con System.out.println para ayudarme a depurar. Y la experiencia reforzó que necesito aprender a usar un registrador como mi enfoque por defecto.

Investigar

Afortunadamente, leí la documentación deSensei y decidí usar la guía "Getting Started" para ayudarme a crear una receta para convertir de System.out.println y animarme a usar un registrador:

  • java.util.logging.Logger

Creación de una receta

Lo primero que hago es pulsar el println y luego alt+enter para crear una nueva receta.

Sistema de impresión Crear una nueva receta


Lo creo con los siguientes datos:


Nombre: Logger: utilizar logger en lugar de println
Descripción: utilizar logger en lugar de println - recuerde dejar de utilizar System.out.println
Nivel: Error


Y voy a empezar por hacer coincidir methodcall con el nombre println


buscar:
  methodcall:
    nombre: "println"

Y la vista previa me muestra todas las coincidencias de mi código.


Método de configuración de recetasllamar a Println


Puedo ver que todas las coincidencias en mi código son para System.out.println pero no confío en que a largo plazo esta sea la única coincidencia. Quiero que coincida con una declaración más calificada que quiero cambiar.

Amplío el matcher para buscar un methodcall en un campo nombrado en la clase System.


buscar:
  methodcall:
    nombre: "println"
    "on":
      campo:
        en:
          clase:
            nombre: "Sistema"
        nombre: "out"



Podría, si quisiera, calificar completamente el nombre System a java.lang.System

Método de configuración de recetasSistema de nombres de llamada

Modificación del Código para registrar


A continuación, quiero crear el QuickFix.

Primero quiero modificar la línea de código que registra la salida:


availableFixes:
- nombre: "use Logger"
  acciones:
  - Reescritura:
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



No tengo que recordar el formato de la plantilla del bigote. Utilicé la opción de mostrar variables en la interfaz gráfica de usuario para que me mostrara el argumento y hice doble clic en él. Entonces la GUI rellenó la plantilla de bigote correspondiente.



Cuando lo pruebo, veo que todavía tengo que pulsar alt+enter para importar el Level enum. Pero si modifico mi QuickFix para que tenga un elemento totalmente cualificado, entonces Sensei añadirá la importación por mí, por ejemplo

  • Sustituirá System.out.println(output); por

logger.log(Level.INFO, output);

  • Y añade una importación para el enum:

import java.util.logging.Level;

  • Si vuelvo a escribir a:
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})

Y esto funcionará, pero todavía tendré que recordar la sintaxis para instanciar el registrador en primer lugar.

Sintaxis para instanciar el registrador en primer lugar


Modificación del código para añadir el campo de registro

Puedo modificar mi QuickFix para que me cree el campo también.

Primero codificaré el registrador y luego lo añadiré a mi receta para no tener que volver a codificarlo.

Logger2 = Logger.getLogger(SysOutTest.class.getName());


Suelo escribir primero el código de ejemplo que quiero que se genere porque así puedo utilizar el completamiento de código de IntelliJ y la comprobación de sintaxis para asegurarme de que lo hago bien. Como efecto secundario, luego estará en la vista previa del código cuando edite la receta para añadir las líneas de QuickFix que crearán ese código.

Y cuando escribo el código de ejemplo, quiero usar un nombre de campo diferente (aquí estoy usando logger2) porque Sensei es lo suficientemente inteligente como para no añadir un campo duplicado, así que tengo que engañarlo usando un nombre diferente.

Así que voy a modificar la receta para crear este código añadiendo un campo llamado logger.

availableFixes:

- nombre: "use Logger"
  acciones:
  - Reescritura:
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField:
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
      objetivo: "parentClass"


Tenga en cuenta que he cambiado SysOutTest para ser una variable de bigote para que recoja el nombre de cualquier clase en la que utilice esta receta. Y de nuevo, no recordaba la sintaxis del bigote, utilicé la GUI Show Variables para encontrar el reemplazo que necesitaba.

Al calificar completamente el Logger a java.util.logging.Logger, Sensei añadirá la importación y escribirá la línea de código que quiero, es decir

Logger = Logger.getLogger(SysOutTest.class.getName());


Calificando completamente el Logger a java.util.logging.Logger


Una cosa útil de esta receta es que como sólo añadirá el campo logger una vez, puedo usar esto en cualquier código existente donde haya usado `System.out.println` y usar Sensei para cambiar todas las ocurrencias en mi archivo de código al mismo tiempo.


Usar el registrador para arreglar todos los problemas en el archivo



Próximos pasos

Una vez que me acostumbre a esto, eventualmente me entrenaré para dejar de usar System.out.println.

Puedo utilizar Sensei para ayudarme a escribir código de forma proactiva creando una segunda receta que me ayude a crear un registrador.

Por ejemplo, puedo coincidir en una clase, donde no hay ningún campo llamado logger, y añadir uno.

Si creo una receta de nivel Información


Nombre: Logger: añadir logger

Descripción: Añadir un registrador a la clase


Para coincidir con una clase sin campo de registro:

buscar:
  clase:
    sin:
      niño:
        campo:
          nombre: "logger"


Y luego reutilizaré parte del QuickFix que vimos antes:


availableFixes:

  - nombre: "Añadir registrador"
    acciones:
      - addField:
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
          objetivo: "yo"


Observe la diferencia en el objetivo aquí comparado con el primer QuickFix. Este utiliza self porque nuestra Búsqueda coincidió con la clase. El primer QuickFix utiliza parentClass porque hemos buscado código dentro de la propia clase.

Resumen

Esto representa uno de los flujos clave asociados con el uso de Sensei para ayudar a mejorar su conjunto de habilidades de programación personal:

  • crear una receta para ayudar a su "mejor práctica" inmediata
  • una vez que sepa cómo utilizar esa mejor práctica... cree una receta para agilizar su flujo de trabajo


---


Puede instalar Sensei desde IntelliJ usando "Preferences \ Plugins" (Mac) o "Settings \ Plugins" (Windows) y luego sólo busque "sensei secure code".


El código fuente y las recetas para esto se pueden encontrar en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior , en el módulo `pojoexamples`.




Ver recurso
Ver recurso

Autor

Alan Richardson

¿Quieres más?

Sumérjase en nuestras últimas ideas sobre codificación segura en el blog.

Nuestra amplia biblioteca de recursos tiene como objetivo potenciar el enfoque humano de la mejora de la codificación segura.

Ver blog
¿Quieres más?

Obtenga las últimas investigaciones sobre la seguridad impulsada por los desarrolladores

Nuestra amplia biblioteca de recursos está repleta de recursos útiles, desde libros blancos hasta seminarios web, que le ayudarán a iniciarse en la codificación segura orientada a los desarrolladores. Explórela ahora.

Centro de recursos

Migración a un registrador con Sensei

Publicado el 30 de noviembre de 2020
Por Alan Richardson

Migración a un registrador con Sensei

Este post describe la creación de una receta para migrar de System.out.println a usar un Logger de Java.

Cuando estoy hackeando el código, en lugar de usar TDD, y cometo errores, tengo la mala costumbre de imprimir una línea en System.out, y he querido despojarme de ese hábito.

He cometido un montón de errores al escribir el código de abajo :

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


Inicialmente, escribí countdown++ y el bucle no terminó.

Y usé la cuenta atrás > 1 por lo que no obtuve la salida que quería.

Al final, llené mi código con System.out.println para ayudarme a depurar. Y la experiencia reforzó que necesito aprender a usar un registrador como mi enfoque por defecto.

Investigar

Afortunadamente, leí la documentación deSensei y decidí usar la guía "Getting Started" para ayudarme a crear una receta para convertir de System.out.println y animarme a usar un registrador:

  • java.util.logging.Logger

Creación de una receta

Lo primero que hago es pulsar el println y luego alt+enter para crear una nueva receta.

Sistema de impresión Crear una nueva receta


Lo creo con los siguientes datos:


Nombre: Logger: utilizar logger en lugar de println
Descripción: utilizar logger en lugar de println - recuerde dejar de utilizar System.out.println
Nivel: Error


Y voy a empezar por hacer coincidir methodcall con el nombre println


buscar:
  methodcall:
    nombre: "println"

Y la vista previa me muestra todas las coincidencias de mi código.


Método de configuración de recetasllamar a Println


Puedo ver que todas las coincidencias en mi código son para System.out.println pero no confío en que a largo plazo esta sea la única coincidencia. Quiero que coincida con una declaración más calificada que quiero cambiar.

Amplío el matcher para buscar un methodcall en un campo nombrado en la clase System.


buscar:
  methodcall:
    nombre: "println"
    "on":
      campo:
        en:
          clase:
            nombre: "Sistema"
        nombre: "out"



Podría, si quisiera, calificar completamente el nombre System a java.lang.System

Método de configuración de recetasSistema de nombres de llamada

Modificación del Código para registrar


A continuación, quiero crear el QuickFix.

Primero quiero modificar la línea de código que registra la salida:


availableFixes:
- nombre: "use Logger"
  acciones:
  - Reescritura:
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



No tengo que recordar el formato de la plantilla del bigote. Utilicé la opción de mostrar variables en la interfaz gráfica de usuario para que me mostrara el argumento y hice doble clic en él. Entonces la GUI rellenó la plantilla de bigote correspondiente.



Cuando lo pruebo, veo que todavía tengo que pulsar alt+enter para importar el Level enum. Pero si modifico mi QuickFix para que tenga un elemento totalmente cualificado, entonces Sensei añadirá la importación por mí, por ejemplo

  • Sustituirá System.out.println(output); por

logger.log(Level.INFO, output);

  • Y añade una importación para el enum:

import java.util.logging.Level;

  • Si vuelvo a escribir a:
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})

Y esto funcionará, pero todavía tendré que recordar la sintaxis para instanciar el registrador en primer lugar.

Sintaxis para instanciar el registrador en primer lugar


Modificación del código para añadir el campo de registro

Puedo modificar mi QuickFix para que me cree el campo también.

Primero codificaré el registrador y luego lo añadiré a mi receta para no tener que volver a codificarlo.

Logger2 = Logger.getLogger(SysOutTest.class.getName());


Suelo escribir primero el código de ejemplo que quiero que se genere porque así puedo utilizar el completamiento de código de IntelliJ y la comprobación de sintaxis para asegurarme de que lo hago bien. Como efecto secundario, luego estará en la vista previa del código cuando edite la receta para añadir las líneas de QuickFix que crearán ese código.

Y cuando escribo el código de ejemplo, quiero usar un nombre de campo diferente (aquí estoy usando logger2) porque Sensei es lo suficientemente inteligente como para no añadir un campo duplicado, así que tengo que engañarlo usando un nombre diferente.

Así que voy a modificar la receta para crear este código añadiendo un campo llamado logger.

availableFixes:

- nombre: "use Logger"
  acciones:
  - Reescritura:
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField:
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
      objetivo: "parentClass"


Tenga en cuenta que he cambiado SysOutTest para ser una variable de bigote para que recoja el nombre de cualquier clase en la que utilice esta receta. Y de nuevo, no recordaba la sintaxis del bigote, utilicé la GUI Show Variables para encontrar el reemplazo que necesitaba.

Al calificar completamente el Logger a java.util.logging.Logger, Sensei añadirá la importación y escribirá la línea de código que quiero, es decir

Logger = Logger.getLogger(SysOutTest.class.getName());


Calificando completamente el Logger a java.util.logging.Logger


Una cosa útil de esta receta es que como sólo añadirá el campo logger una vez, puedo usar esto en cualquier código existente donde haya usado `System.out.println` y usar Sensei para cambiar todas las ocurrencias en mi archivo de código al mismo tiempo.


Usar el registrador para arreglar todos los problemas en el archivo



Próximos pasos

Una vez que me acostumbre a esto, eventualmente me entrenaré para dejar de usar System.out.println.

Puedo utilizar Sensei para ayudarme a escribir código de forma proactiva creando una segunda receta que me ayude a crear un registrador.

Por ejemplo, puedo coincidir en una clase, donde no hay ningún campo llamado logger, y añadir uno.

Si creo una receta de nivel Información


Nombre: Logger: añadir logger

Descripción: Añadir un registrador a la clase


Para coincidir con una clase sin campo de registro:

buscar:
  clase:
    sin:
      niño:
        campo:
          nombre: "logger"


Y luego reutilizaré parte del QuickFix que vimos antes:


availableFixes:

  - nombre: "Añadir registrador"
    acciones:
      - addField:
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
          objetivo: "yo"


Observe la diferencia en el objetivo aquí comparado con el primer QuickFix. Este utiliza self porque nuestra Búsqueda coincidió con la clase. El primer QuickFix utiliza parentClass porque hemos buscado código dentro de la propia clase.

Resumen

Esto representa uno de los flujos clave asociados con el uso de Sensei para ayudar a mejorar su conjunto de habilidades de programación personal:

  • crear una receta para ayudar a su "mejor práctica" inmediata
  • una vez que sepa cómo utilizar esa mejor práctica... cree una receta para agilizar su flujo de trabajo


---


Puede instalar Sensei desde IntelliJ usando "Preferences \ Plugins" (Mac) o "Settings \ Plugins" (Windows) y luego sólo busque "sensei secure code".


El código fuente y las recetas para esto se pueden encontrar en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior , en el módulo `pojoexamples`.




Nos gustaría contar con su permiso para enviarle información sobre nuestros productos y/o temas relacionados con la codificación segura. Siempre trataremos sus datos personales con el máximo cuidado y nunca los venderemos a otras empresas con fines de marketing.

Enviar
Para enviar el formulario, habilite las cookies "Analytics". Siéntase libre de desactivarlas de nuevo una vez que haya terminado.