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
Évaluation comparative des compétences en matière de sécurité : Rationalisation de la conception sécurisée dans l'entreprise
Le mouvement "Secure-by-Design" (conception sécurisée) est l'avenir du développement de logiciels sécurisés. Découvrez les éléments clés que les entreprises doivent garder à l'esprit lorsqu'elles envisagent une initiative de conception sécurisée.
DigitalOcean réduit sa dette de sécurité avec Secure Code Warrior
L'utilisation par DigitalOcean de la formation Secure Code Warrior a considérablement réduit la dette de sécurité, permettant aux équipes de se concentrer davantage sur l'innovation et la productivité. L'amélioration de la sécurité a renforcé la qualité des produits et l'avantage concurrentiel de l'entreprise. À l'avenir, le score de confiance SCW les aidera à améliorer leurs pratiques de sécurité et à continuer à stimuler l'innovation.
Ressources pour vous aider à démarrer
Sécurité réactive contre sécurité préventive : La prévention est un meilleur remède
L'idée d'apporter une sécurité préventive aux codes et systèmes existants en même temps qu'aux applications plus récentes peut sembler décourageante, mais une approche "Secure-by-Design", mise en œuvre en améliorant les compétences des développeurs, permet d'appliquer les meilleures pratiques de sécurité à ces systèmes. C'est la meilleure chance qu'ont de nombreuses organisations d'améliorer leur sécurité.
Les avantages de l'évaluation des compétences des développeurs en matière de sécurité
L'importance croissante accordée au code sécurisé et aux principes de conception sécurisée exige que les développeurs soient formés à la cybersécurité dès le début du cycle de développement durable, et que des outils tels que le Trust Score de Secure Code Warriorles aident à mesurer et à améliorer leurs progrès.
Assurer le succès des initiatives de conception sécurisée de l'entreprise
Notre dernier document de recherche, Benchmarking Security Skills : Streamlining Secure-by-Design in the Enterprise est le résultat d'une analyse approfondie d'initiatives réelles de conception sécurisée au niveau de l'entreprise, et de l'élaboration d'approches de meilleures pratiques basées sur des conclusions fondées sur des données.
Plongée en profondeur : Naviguer dans la vulnérabilité critique de CUPS dans les systèmes GNU-Linux
Découvrez les derniers défis de sécurité auxquels sont confrontés les utilisateurs de Linux en explorant les récentes vulnérabilités de haute sévérité dans le système d'impression commun d'UNIX (CUPS). Apprenez comment ces problèmes peuvent conduire à une potentielle exécution de code à distance (RCE) et ce que vous pouvez faire pour protéger vos systèmes.