Migrer vers un enregistreur avec Sensei
Migrer vers un enregistreur avec Sensei
Ce billet décrit la création d'une recette pour migrer de System.out.println à l'utilisation d'un logger Java.
Lorsque je bidouille du code, plutôt que d'utiliser le TDD, et que je fais des erreurs, j'ai la mauvaise habitude d'imprimer une ligne dans System.out, et j'ai voulu me débarrasser de cette habitude.
J'ai fait un certain nombre d'erreurs en écrivant le code ci-dessous :
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;
}
Initialement, j'ai écrit countdown++ et la boucle ne s'est pas terminée.
Et j'ai utilisé countdown > 1 donc je n'ai pas obtenu le résultat que je voulais.
Au final, j'ai truffé mon code de System.out.println pour m'aider à déboguer. Et cette expérience m'a conforté dans l'idée que je dois apprendre à utiliser un logger comme approche par défaut.
Recherche
Heureusement, j'ai lu la documentation deSensei et j'ai décidé d'utiliser le guide "Getting Started" pour m'aider à créer une recette pour convertir System.out.println et m'encourager à utiliser un logger :
- java.util.logging.Logger
Création d'une recette
La première chose que je fais est de cliquer sur println puis sur alt+enter pour créer une nouvelle recette.

Je le crée avec les détails suivants :
Nom : Logger : utilisez logger au lieu de println
Description : utiliser logger au lieu de println - n'oubliez pas d'arrêter d'utiliser System.out.println
Niveau : Erreur
Je commencerai par faire correspondre l'appel de méthode avec le nom println
recherche :
appel de méthode :
nom : "println"
Et l'aperçu me montre toutes les correspondances dans mon code.

Je peux voir que toutes les correspondances dans mon code sont pour System.out.println mais je ne suis pas sûr qu'à long terme ce sera la seule correspondance. Je veux faire correspondre une déclaration plus qualifiée que je veux modifier.
Je développe le matcheur pour rechercher un appel de méthode sur un champ nommé dans la classe System.
recherche :
appel de méthode :
nom : "println"
"on" :
domaine :
en :
classe :
nom : "Système"
nom : "out"
Je pourrais, si je le souhaitais, qualifier complètement le nom du système en java.lang.System

Modification du code pour l'enregistrement
Ensuite, je veux créer le QuickFix.
Tout d'abord, je souhaite modifier la ligne de code qui enregistre la sortie :
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(Level.INFO, {{{ arguments.0 }}})"
Je n'ai pas besoin de me souvenir du format du modèle de moustache. J'ai utilisé la fonction Show Variables de l'interface graphique pour afficher l'argument et j'ai double-cliqué dessus. L'interface graphique a ensuite rempli le modèle de moustache correspondant.

Lorsque je l'essaie, je constate que je dois toujours appuyer sur alt+enter pour importer l'énumération des niveaux. Mais si je modifie mon QuickFix pour avoir un élément pleinement qualifié, alors Sensei ajoutera l'importation pour moi, par exemple.
- Il remplacera System.out.println(output) ; par
logger.log(Level.INFO, output) ;
- Et ajoutez un import pour l'enum :
import java.util.logging.Level ;
- Si je réécris en :
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})
Et cela fonctionnera, mais je devrai toujours me souvenir de la syntaxe pour instancier le logger en premier lieu.

Modification du code pour ajouter le champ logger
Je peux modifier mon QuickFix pour créer le champ pour moi aussi.
Je vais d'abord coder le logger, puis l'ajouter à ma recette pour ne plus avoir à le coder.
Logger logger2 = Logger.getLogger(SysOutTest.class.getName()) ;
J'ai tendance à écrire le code d'exemple que je veux voir généré en premier, car je peux alors utiliser la complétion de code et la vérification syntaxique d'IntelliJ pour m'assurer qu'il est correct. Comme effet secondaire, il sera alors dans l'aperçu du code lorsque j'éditerai la recette pour ajouter les lignes QuickFix qui créeront ce code.
Et lorsque j'écris le code d'exemple, je veux utiliser un nom de champ différent (ici j'utilise logger2) parce que Sensei est assez intelligent pour ne pas ajouter un champ en double, donc je dois le tromper en utilisant un nom différent.
Je vais donc modifier la recette pour créer ce code en ajoutant un champ appelé logger.
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "parentClass"
Notez que j'ai modifié SysOutTest pour en faire une variable mustache afin qu'elle prenne le nom de n'importe quelle classe dans laquelle j'utilise cette recette. Et encore une fois, je ne me suis pas souvenu de la syntaxe mustache, j'ai utilisé l'interface graphique Show Variables pour trouver le remplacement dont j'avais besoin.
En qualifiant complètement le Logger de java.util.logging.Logger, Sensei ajoutera l'importation et écrira la ligne de code que je veux, c'est-à-dire
Logger logger = Logger.getLogger(SysOutTest.class.getName()) ;

Une chose utile à propos de cette recette est que, parce qu'elle n'ajoute le champ logger qu'une seule fois, je peux l'utiliser sur n'importe quel code existant où j'ai utilisé `System.out.println` et utiliser Sensei pour changer toutes les occurrences dans mon fichier de code en même temps.

Prochaines étapes
Une fois que je me serai habitué à cela, je finirai par m'entraîner à ne plus utiliser System.out.println.
Je peux utiliser Sensei pour m'aider à écrire du code de manière proactive en créant une deuxième recette qui m'aide à créer un logger.
Par exemple, je peux trouver une classe dans laquelle il n'y a pas de champ appelé logger, et en ajouter un.
Si je crée une recette de niveau Information
Nom : Logger : ajouter un logger
Description : Ajouter un logger à la classe
Pour faire correspondre une classe sans champ d'enregistrement :
recherche :
classe :
sans :
enfant :
domaine :
nom : "logger"
Je vais ensuite réutiliser une partie de la correction rapide que nous avons vue plus tôt :
les correctifs disponibles :
- name : "Ajouter un enregistreur"
actions :
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "self"
Notez la différence de cible par rapport à la première correction rapide. Celle-ci utilise self parce que notre Search correspondait à la classe. La première correction rapide utilise parentClass parce que nous avons trouvé du code dans la classe elle-même.
Résumé
Il s'agit de l'un des principaux flux associés à l'utilisation de Sensei pour améliorer vos compétences personnelles en matière de programmation :
- créer une recette pour vous aider à mettre en œuvre votre "meilleure pratique" immédiate
- une fois que vous savez comment utiliser cette meilleure pratique, créez une recette pour accélérer votre flux de travail.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Preferences \ Plugins" (Mac) ou "Settings \ Plugins" (Windows) puis en recherchant simplement "sensei secure code".
Le code source et les recettes se trouvent dans le dépôt `sensei-blog-examples` sur le compte GitHub Secure Code Warrior , dans le module `pojoexamples`.


Un exemple rapide de création d'une recette pour passer de System.out.println à l'utilisation d'un logger Java.
Alan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Réservez une démonstrationAlan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.


Migrer vers un enregistreur avec Sensei
Ce billet décrit la création d'une recette pour migrer de System.out.println à l'utilisation d'un logger Java.
Lorsque je bidouille du code, plutôt que d'utiliser le TDD, et que je fais des erreurs, j'ai la mauvaise habitude d'imprimer une ligne dans System.out, et j'ai voulu me débarrasser de cette habitude.
J'ai fait un certain nombre d'erreurs en écrivant le code ci-dessous :
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;
}
Initialement, j'ai écrit countdown++ et la boucle ne s'est pas terminée.
Et j'ai utilisé countdown > 1 donc je n'ai pas obtenu le résultat que je voulais.
Au final, j'ai truffé mon code de System.out.println pour m'aider à déboguer. Et cette expérience m'a conforté dans l'idée que je dois apprendre à utiliser un logger comme approche par défaut.
Recherche
Heureusement, j'ai lu la documentation deSensei et j'ai décidé d'utiliser le guide "Getting Started" pour m'aider à créer une recette pour convertir System.out.println et m'encourager à utiliser un logger :
- java.util.logging.Logger
Création d'une recette
La première chose que je fais est de cliquer sur println puis sur alt+enter pour créer une nouvelle recette.

Je le crée avec les détails suivants :
Nom : Logger : utilisez logger au lieu de println
Description : utiliser logger au lieu de println - n'oubliez pas d'arrêter d'utiliser System.out.println
Niveau : Erreur
Je commencerai par faire correspondre l'appel de méthode avec le nom println
recherche :
appel de méthode :
nom : "println"
Et l'aperçu me montre toutes les correspondances dans mon code.

Je peux voir que toutes les correspondances dans mon code sont pour System.out.println mais je ne suis pas sûr qu'à long terme ce sera la seule correspondance. Je veux faire correspondre une déclaration plus qualifiée que je veux modifier.
Je développe le matcheur pour rechercher un appel de méthode sur un champ nommé dans la classe System.
recherche :
appel de méthode :
nom : "println"
"on" :
domaine :
en :
classe :
nom : "Système"
nom : "out"
Je pourrais, si je le souhaitais, qualifier complètement le nom du système en java.lang.System

Modification du code pour l'enregistrement
Ensuite, je veux créer le QuickFix.
Tout d'abord, je souhaite modifier la ligne de code qui enregistre la sortie :
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(Level.INFO, {{{ arguments.0 }}})"
Je n'ai pas besoin de me souvenir du format du modèle de moustache. J'ai utilisé la fonction Show Variables de l'interface graphique pour afficher l'argument et j'ai double-cliqué dessus. L'interface graphique a ensuite rempli le modèle de moustache correspondant.

Lorsque je l'essaie, je constate que je dois toujours appuyer sur alt+enter pour importer l'énumération des niveaux. Mais si je modifie mon QuickFix pour avoir un élément pleinement qualifié, alors Sensei ajoutera l'importation pour moi, par exemple.
- Il remplacera System.out.println(output) ; par
logger.log(Level.INFO, output) ;
- Et ajoutez un import pour l'enum :
import java.util.logging.Level ;
- Si je réécris en :
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})
Et cela fonctionnera, mais je devrai toujours me souvenir de la syntaxe pour instancier le logger en premier lieu.

Modification du code pour ajouter le champ logger
Je peux modifier mon QuickFix pour créer le champ pour moi aussi.
Je vais d'abord coder le logger, puis l'ajouter à ma recette pour ne plus avoir à le coder.
Logger logger2 = Logger.getLogger(SysOutTest.class.getName()) ;
J'ai tendance à écrire le code d'exemple que je veux voir généré en premier, car je peux alors utiliser la complétion de code et la vérification syntaxique d'IntelliJ pour m'assurer qu'il est correct. Comme effet secondaire, il sera alors dans l'aperçu du code lorsque j'éditerai la recette pour ajouter les lignes QuickFix qui créeront ce code.
Et lorsque j'écris le code d'exemple, je veux utiliser un nom de champ différent (ici j'utilise logger2) parce que Sensei est assez intelligent pour ne pas ajouter un champ en double, donc je dois le tromper en utilisant un nom différent.
Je vais donc modifier la recette pour créer ce code en ajoutant un champ appelé logger.
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "parentClass"
Notez que j'ai modifié SysOutTest pour en faire une variable mustache afin qu'elle prenne le nom de n'importe quelle classe dans laquelle j'utilise cette recette. Et encore une fois, je ne me suis pas souvenu de la syntaxe mustache, j'ai utilisé l'interface graphique Show Variables pour trouver le remplacement dont j'avais besoin.
En qualifiant complètement le Logger de java.util.logging.Logger, Sensei ajoutera l'importation et écrira la ligne de code que je veux, c'est-à-dire
Logger logger = Logger.getLogger(SysOutTest.class.getName()) ;

Une chose utile à propos de cette recette est que, parce qu'elle n'ajoute le champ logger qu'une seule fois, je peux l'utiliser sur n'importe quel code existant où j'ai utilisé `System.out.println` et utiliser Sensei pour changer toutes les occurrences dans mon fichier de code en même temps.

Prochaines étapes
Une fois que je me serai habitué à cela, je finirai par m'entraîner à ne plus utiliser System.out.println.
Je peux utiliser Sensei pour m'aider à écrire du code de manière proactive en créant une deuxième recette qui m'aide à créer un logger.
Par exemple, je peux trouver une classe dans laquelle il n'y a pas de champ appelé logger, et en ajouter un.
Si je crée une recette de niveau Information
Nom : Logger : ajouter un logger
Description : Ajouter un logger à la classe
Pour faire correspondre une classe sans champ d'enregistrement :
recherche :
classe :
sans :
enfant :
domaine :
nom : "logger"
Je vais ensuite réutiliser une partie de la correction rapide que nous avons vue plus tôt :
les correctifs disponibles :
- name : "Ajouter un enregistreur"
actions :
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "self"
Notez la différence de cible par rapport à la première correction rapide. Celle-ci utilise self parce que notre Search correspondait à la classe. La première correction rapide utilise parentClass parce que nous avons trouvé du code dans la classe elle-même.
Résumé
Il s'agit de l'un des principaux flux associés à l'utilisation de Sensei pour améliorer vos compétences personnelles en matière de programmation :
- créer une recette pour vous aider à mettre en œuvre votre "meilleure pratique" immédiate
- une fois que vous savez comment utiliser cette meilleure pratique, créez une recette pour accélérer votre flux de travail.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Preferences \ Plugins" (Mac) ou "Settings \ Plugins" (Windows) puis en recherchant simplement "sensei secure code".
Le code source et les recettes se trouvent dans le dépôt `sensei-blog-examples` sur le compte GitHub Secure Code Warrior , dans le module `pojoexamples`.

Migrer vers un enregistreur avec Sensei
Ce billet décrit la création d'une recette pour migrer de System.out.println à l'utilisation d'un logger Java.
Lorsque je bidouille du code, plutôt que d'utiliser le TDD, et que je fais des erreurs, j'ai la mauvaise habitude d'imprimer une ligne dans System.out, et j'ai voulu me débarrasser de cette habitude.
J'ai fait un certain nombre d'erreurs en écrivant le code ci-dessous :
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;
}
Initialement, j'ai écrit countdown++ et la boucle ne s'est pas terminée.
Et j'ai utilisé countdown > 1 donc je n'ai pas obtenu le résultat que je voulais.
Au final, j'ai truffé mon code de System.out.println pour m'aider à déboguer. Et cette expérience m'a conforté dans l'idée que je dois apprendre à utiliser un logger comme approche par défaut.
Recherche
Heureusement, j'ai lu la documentation deSensei et j'ai décidé d'utiliser le guide "Getting Started" pour m'aider à créer une recette pour convertir System.out.println et m'encourager à utiliser un logger :
- java.util.logging.Logger
Création d'une recette
La première chose que je fais est de cliquer sur println puis sur alt+enter pour créer une nouvelle recette.

Je le crée avec les détails suivants :
Nom : Logger : utilisez logger au lieu de println
Description : utiliser logger au lieu de println - n'oubliez pas d'arrêter d'utiliser System.out.println
Niveau : Erreur
Je commencerai par faire correspondre l'appel de méthode avec le nom println
recherche :
appel de méthode :
nom : "println"
Et l'aperçu me montre toutes les correspondances dans mon code.

Je peux voir que toutes les correspondances dans mon code sont pour System.out.println mais je ne suis pas sûr qu'à long terme ce sera la seule correspondance. Je veux faire correspondre une déclaration plus qualifiée que je veux modifier.
Je développe le matcheur pour rechercher un appel de méthode sur un champ nommé dans la classe System.
recherche :
appel de méthode :
nom : "println"
"on" :
domaine :
en :
classe :
nom : "Système"
nom : "out"
Je pourrais, si je le souhaitais, qualifier complètement le nom du système en java.lang.System

Modification du code pour l'enregistrement
Ensuite, je veux créer le QuickFix.
Tout d'abord, je souhaite modifier la ligne de code qui enregistre la sortie :
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(Level.INFO, {{{ arguments.0 }}})"
Je n'ai pas besoin de me souvenir du format du modèle de moustache. J'ai utilisé la fonction Show Variables de l'interface graphique pour afficher l'argument et j'ai double-cliqué dessus. L'interface graphique a ensuite rempli le modèle de moustache correspondant.

Lorsque je l'essaie, je constate que je dois toujours appuyer sur alt+enter pour importer l'énumération des niveaux. Mais si je modifie mon QuickFix pour avoir un élément pleinement qualifié, alors Sensei ajoutera l'importation pour moi, par exemple.
- Il remplacera System.out.println(output) ; par
logger.log(Level.INFO, output) ;
- Et ajoutez un import pour l'enum :
import java.util.logging.Level ;
- Si je réécris en :
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})
Et cela fonctionnera, mais je devrai toujours me souvenir de la syntaxe pour instancier le logger en premier lieu.

Modification du code pour ajouter le champ logger
Je peux modifier mon QuickFix pour créer le champ pour moi aussi.
Je vais d'abord coder le logger, puis l'ajouter à ma recette pour ne plus avoir à le coder.
Logger logger2 = Logger.getLogger(SysOutTest.class.getName()) ;
J'ai tendance à écrire le code d'exemple que je veux voir généré en premier, car je peux alors utiliser la complétion de code et la vérification syntaxique d'IntelliJ pour m'assurer qu'il est correct. Comme effet secondaire, il sera alors dans l'aperçu du code lorsque j'éditerai la recette pour ajouter les lignes QuickFix qui créeront ce code.
Et lorsque j'écris le code d'exemple, je veux utiliser un nom de champ différent (ici j'utilise logger2) parce que Sensei est assez intelligent pour ne pas ajouter un champ en double, donc je dois le tromper en utilisant un nom différent.
Je vais donc modifier la recette pour créer ce code en ajoutant un champ appelé logger.
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "parentClass"
Notez que j'ai modifié SysOutTest pour en faire une variable mustache afin qu'elle prenne le nom de n'importe quelle classe dans laquelle j'utilise cette recette. Et encore une fois, je ne me suis pas souvenu de la syntaxe mustache, j'ai utilisé l'interface graphique Show Variables pour trouver le remplacement dont j'avais besoin.
En qualifiant complètement le Logger de java.util.logging.Logger, Sensei ajoutera l'importation et écrira la ligne de code que je veux, c'est-à-dire
Logger logger = Logger.getLogger(SysOutTest.class.getName()) ;

Une chose utile à propos de cette recette est que, parce qu'elle n'ajoute le champ logger qu'une seule fois, je peux l'utiliser sur n'importe quel code existant où j'ai utilisé `System.out.println` et utiliser Sensei pour changer toutes les occurrences dans mon fichier de code en même temps.

Prochaines étapes
Une fois que je me serai habitué à cela, je finirai par m'entraîner à ne plus utiliser System.out.println.
Je peux utiliser Sensei pour m'aider à écrire du code de manière proactive en créant une deuxième recette qui m'aide à créer un logger.
Par exemple, je peux trouver une classe dans laquelle il n'y a pas de champ appelé logger, et en ajouter un.
Si je crée une recette de niveau Information
Nom : Logger : ajouter un logger
Description : Ajouter un logger à la classe
Pour faire correspondre une classe sans champ d'enregistrement :
recherche :
classe :
sans :
enfant :
domaine :
nom : "logger"
Je vais ensuite réutiliser une partie de la correction rapide que nous avons vue plus tôt :
les correctifs disponibles :
- name : "Ajouter un enregistreur"
actions :
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "self"
Notez la différence de cible par rapport à la première correction rapide. Celle-ci utilise self parce que notre Search correspondait à la classe. La première correction rapide utilise parentClass parce que nous avons trouvé du code dans la classe elle-même.
Résumé
Il s'agit de l'un des principaux flux associés à l'utilisation de Sensei pour améliorer vos compétences personnelles en matière de programmation :
- créer une recette pour vous aider à mettre en œuvre votre "meilleure pratique" immédiate
- une fois que vous savez comment utiliser cette meilleure pratique, créez une recette pour accélérer votre flux de travail.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Preferences \ Plugins" (Mac) ou "Settings \ Plugins" (Windows) puis en recherchant simplement "sensei secure code".
Le code source et les recettes se trouvent dans le dépôt `sensei-blog-examples` sur le compte GitHub Secure Code Warrior , dans le module `pojoexamples`.

Cliquez sur le lien ci-dessous et téléchargez le PDF de cette ressource.
Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Voir le rapportRéservez une démonstrationAlan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.
Migrer vers un enregistreur avec Sensei
Ce billet décrit la création d'une recette pour migrer de System.out.println à l'utilisation d'un logger Java.
Lorsque je bidouille du code, plutôt que d'utiliser le TDD, et que je fais des erreurs, j'ai la mauvaise habitude d'imprimer une ligne dans System.out, et j'ai voulu me débarrasser de cette habitude.
J'ai fait un certain nombre d'erreurs en écrivant le code ci-dessous :
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;
}
Initialement, j'ai écrit countdown++ et la boucle ne s'est pas terminée.
Et j'ai utilisé countdown > 1 donc je n'ai pas obtenu le résultat que je voulais.
Au final, j'ai truffé mon code de System.out.println pour m'aider à déboguer. Et cette expérience m'a conforté dans l'idée que je dois apprendre à utiliser un logger comme approche par défaut.
Recherche
Heureusement, j'ai lu la documentation deSensei et j'ai décidé d'utiliser le guide "Getting Started" pour m'aider à créer une recette pour convertir System.out.println et m'encourager à utiliser un logger :
- java.util.logging.Logger
Création d'une recette
La première chose que je fais est de cliquer sur println puis sur alt+enter pour créer une nouvelle recette.

Je le crée avec les détails suivants :
Nom : Logger : utilisez logger au lieu de println
Description : utiliser logger au lieu de println - n'oubliez pas d'arrêter d'utiliser System.out.println
Niveau : Erreur
Je commencerai par faire correspondre l'appel de méthode avec le nom println
recherche :
appel de méthode :
nom : "println"
Et l'aperçu me montre toutes les correspondances dans mon code.

Je peux voir que toutes les correspondances dans mon code sont pour System.out.println mais je ne suis pas sûr qu'à long terme ce sera la seule correspondance. Je veux faire correspondre une déclaration plus qualifiée que je veux modifier.
Je développe le matcheur pour rechercher un appel de méthode sur un champ nommé dans la classe System.
recherche :
appel de méthode :
nom : "println"
"on" :
domaine :
en :
classe :
nom : "Système"
nom : "out"
Je pourrais, si je le souhaitais, qualifier complètement le nom du système en java.lang.System

Modification du code pour l'enregistrement
Ensuite, je veux créer le QuickFix.
Tout d'abord, je souhaite modifier la ligne de code qui enregistre la sortie :
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(Level.INFO, {{{ arguments.0 }}})"
Je n'ai pas besoin de me souvenir du format du modèle de moustache. J'ai utilisé la fonction Show Variables de l'interface graphique pour afficher l'argument et j'ai double-cliqué dessus. L'interface graphique a ensuite rempli le modèle de moustache correspondant.

Lorsque je l'essaie, je constate que je dois toujours appuyer sur alt+enter pour importer l'énumération des niveaux. Mais si je modifie mon QuickFix pour avoir un élément pleinement qualifié, alors Sensei ajoutera l'importation pour moi, par exemple.
- Il remplacera System.out.println(output) ; par
logger.log(Level.INFO, output) ;
- Et ajoutez un import pour l'enum :
import java.util.logging.Level ;
- Si je réécris en :
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})
Et cela fonctionnera, mais je devrai toujours me souvenir de la syntaxe pour instancier le logger en premier lieu.

Modification du code pour ajouter le champ logger
Je peux modifier mon QuickFix pour créer le champ pour moi aussi.
Je vais d'abord coder le logger, puis l'ajouter à ma recette pour ne plus avoir à le coder.
Logger logger2 = Logger.getLogger(SysOutTest.class.getName()) ;
J'ai tendance à écrire le code d'exemple que je veux voir généré en premier, car je peux alors utiliser la complétion de code et la vérification syntaxique d'IntelliJ pour m'assurer qu'il est correct. Comme effet secondaire, il sera alors dans l'aperçu du code lorsque j'éditerai la recette pour ajouter les lignes QuickFix qui créeront ce code.
Et lorsque j'écris le code d'exemple, je veux utiliser un nom de champ différent (ici j'utilise logger2) parce que Sensei est assez intelligent pour ne pas ajouter un champ en double, donc je dois le tromper en utilisant un nom différent.
Je vais donc modifier la recette pour créer ce code en ajoutant un champ appelé logger.
les correctifs disponibles :
- name : "use Logger" (utiliser l'enregistreur)
actions :
- réécrire :
to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "parentClass"
Notez que j'ai modifié SysOutTest pour en faire une variable mustache afin qu'elle prenne le nom de n'importe quelle classe dans laquelle j'utilise cette recette. Et encore une fois, je ne me suis pas souvenu de la syntaxe mustache, j'ai utilisé l'interface graphique Show Variables pour trouver le remplacement dont j'avais besoin.
En qualifiant complètement le Logger de java.util.logging.Logger, Sensei ajoutera l'importation et écrira la ligne de code que je veux, c'est-à-dire
Logger logger = Logger.getLogger(SysOutTest.class.getName()) ;

Une chose utile à propos de cette recette est que, parce qu'elle n'ajoute le champ logger qu'une seule fois, je peux l'utiliser sur n'importe quel code existant où j'ai utilisé `System.out.println` et utiliser Sensei pour changer toutes les occurrences dans mon fichier de code en même temps.

Prochaines étapes
Une fois que je me serai habitué à cela, je finirai par m'entraîner à ne plus utiliser System.out.println.
Je peux utiliser Sensei pour m'aider à écrire du code de manière proactive en créant une deuxième recette qui m'aide à créer un logger.
Par exemple, je peux trouver une classe dans laquelle il n'y a pas de champ appelé logger, et en ajouter un.
Si je crée une recette de niveau Information
Nom : Logger : ajouter un logger
Description : Ajouter un logger à la classe
Pour faire correspondre une classe sans champ d'enregistrement :
recherche :
classe :
sans :
enfant :
domaine :
nom : "logger"
Je vais ensuite réutiliser une partie de la correction rapide que nous avons vue plus tôt :
les correctifs disponibles :
- name : "Ajouter un enregistreur"
actions :
- addField :
field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
\}}.class.getName())"
cible : "self"
Notez la différence de cible par rapport à la première correction rapide. Celle-ci utilise self parce que notre Search correspondait à la classe. La première correction rapide utilise parentClass parce que nous avons trouvé du code dans la classe elle-même.
Résumé
Il s'agit de l'un des principaux flux associés à l'utilisation de Sensei pour améliorer vos compétences personnelles en matière de programmation :
- créer une recette pour vous aider à mettre en œuvre votre "meilleure pratique" immédiate
- une fois que vous savez comment utiliser cette meilleure pratique, créez une recette pour accélérer votre flux de travail.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Preferences \ Plugins" (Mac) ou "Settings \ Plugins" (Windows) puis en recherchant simplement "sensei secure code".
Le code source et les recettes se trouvent dans le dépôt `sensei-blog-examples` sur le compte GitHub Secure Code Warrior , dans le module `pojoexamples`.
Table des matières
Alan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Réservez une démonstrationTéléchargerRessources pour vous aider à démarrer
Services professionnels - Accélérer grâce à l'expertise
L'équipe des services de stratégie de programme (PSS) de Secure Code Warriorvous aide à construire, améliorer et optimiser votre programme de codage sécurisé. Que vous partiez de zéro ou que vous affiniez votre approche, nos experts vous fournissent des conseils sur mesure.
Thèmes et contenu de la formation sur le code sécurisé
Notre contenu, à la pointe de l'industrie, évolue constamment pour s'adapter au paysage du développement logiciel en constante évolution, tout en gardant votre rôle à l'esprit. Les sujets abordés vont de l'IA à l'injection XQuery, et sont proposés pour une variété de rôles, des architectes et ingénieurs aux gestionnaires de produits et à l'assurance qualité. Découvrez en avant-première ce que notre catalogue de contenu a à offrir par sujet et par rôle.
Quêtes : Apprentissage de pointe pour permettre aux développeurs de garder une longueur d'avance et d'atténuer les risques.
Quests est une learning platform qui aide les développeurs à atténuer les risques liés à la sécurité des logiciels en améliorant leurs compétences en matière de codage sécurisé. Grâce à des parcours d'apprentissage, des défis pratiques et des activités interactives, elle permet aux développeurs d'identifier et de prévenir les vulnérabilités.
Ressources pour vous aider à démarrer
Vibe Coding va-t-il transformer votre base de code en une fête de fraternité ?
Le codage vibratoire est comme une fête de fraternité universitaire, et l'IA est la pièce maîtresse de toutes les festivités, le tonneau. C'est très amusant de se laisser aller, d'être créatif et de voir où votre imagination peut vous mener, mais après quelques barils, boire (ou utiliser l'IA) avec modération est sans aucun doute la solution la plus sûre à long terme.
La décennie des défenseurs : Secure Code Warrior Dixième anniversaire
Secure Code WarriorL'équipe fondatrice de SCW est restée soudée, dirigeant le navire à travers chaque leçon, chaque triomphe et chaque revers pendant une décennie entière. Nous nous développons et sommes prêts à affronter notre prochain chapitre, SCW 2.0, en tant que leaders de la gestion des risques pour les développeurs.