Comme mes projets Java actuels deviennent de plus en plus gros, je ressens un besoin croissant d'insérer une sortie de débogage dans plusieurs points de mon code.
Pour activer ou désactiver cette fonctionnalité de manière appropriée, en fonction de l'ouverture ou de la fermeture des sessions de test, je place généralement un private static final boolean DEBUG = false
au début des classes que mes tests inspectent, et je l'utilise de cette manière (par exemple):
public MyClass {
private static final boolean DEBUG = false;
... some code ...
public void myMethod(String s) {
if (DEBUG) {
System.out.println(s);
}
}
}
etc.
Mais cela ne me dérange pas, car cela fonctionne bien sûr, mais il pourrait y avoir trop de classes pour définir DEBUG sur true, si vous n'en fixez pas quelques-unes.
Inversement, je (comme - je pense - beaucoup d'autres) n'aimerais pas mettre toute l'application en mode débogage, car la quantité de texte produite pourrait être écrasante.
Alors, existe-t-il une manière correcte de gérer cette situation sur le plan architectural ou la manière la plus correcte est d'utiliser le membre de classe DEBUG?
Réponses:
Vous voulez regarder un cadre de journalisation, et peut-être un cadre de façade de journalisation.
Il existe plusieurs cadres de journalisation, souvent avec des fonctionnalités qui se chevauchent, à tel point qu'au fil du temps, beaucoup ont évolué pour s'appuyer sur une API commune, ou ont fini par être utilisés à travers un cadre de façade pour abstraire leur utilisation et leur permettre d'être échangés sur place si besoin.
Cadres
Quelques cadres de journalisation
Quelques façades forestières
Usage
Exemple de base
La plupart de ces frameworks vous permettraient d'écrire quelque chose du formulaire (ici en utilisant
slf4j-api
etlogback-core
):Notez l'utilisation d'une classe actuelle pour créer un enregistreur dédié, ce qui permettrait à SLF4J / LogBack de formater la sortie et d'indiquer la provenance du message de journalisation.
Comme indiqué dans le manuel SLF4J , un modèle d'utilisation typique dans une classe est généralement:
Mais en fait, il est encore plus courant de déclarer l'enregistreur avec le formulaire:
Cela permet également à l'enregistreur d'être utilisé à partir de méthodes statiques, et il est partagé entre toutes les instances de la classe. Il s'agit très probablement de votre forme préférée. Cependant, comme l'a noté Brendan Long dans les commentaires, vous voulez être sûr de comprendre les implications et de décider en conséquence (cela s'applique à tous les cadres de journalisation suivant ces idiomes).
Il existe d'autres façons d'instancier des enregistreurs, par exemple en utilisant un paramètre de chaîne pour créer un enregistreur nommé:
Niveaux de débogage
Les niveaux de débogage varient d'un framework à l'autre, mais les plus courants sont (par ordre de criticité, de bénin à mauvais, et de probablement très commun à, espérons-le, très rare):
TRACE
Information très détaillée. Doit être écrit dans les journaux uniquement. Utilisé uniquement pour suivre le flux du programme aux points de contrôle.DEBUG
Des informations détaillées. Doit être écrit dans les journaux uniquement.INFO
Événements d'exécution notables. Doit être immédiatement visible sur une console, donc utilisez-le avec parcimonie.WARNING
Curiosités d'exécution et erreurs récupérables.ERROR
Autres erreurs d'exécution ou conditions inattendues.FATAL
Erreurs graves entraînant une résiliation prématurée.Blocs et gardes
Supposons maintenant que vous ayez une section de code où vous êtes sur le point d'écrire un certain nombre d'instructions de débogage. Cela pourrait rapidement affecter vos performances, à la fois en raison de l'impact de la journalisation elle-même et de la génération de tous les paramètres que vous pourriez transmettre à la méthode de journalisation.
Pour éviter ce genre de problème, vous voulez souvent écrire quelque chose de la forme:
Si vous n'aviez pas utilisé ce garde avant votre bloc d'instructions de débogage, même si les messages peuvent ne pas être émis (si, par exemple, votre enregistreur est actuellement configuré pour imprimer uniquement les choses au-dessus du
INFO
niveau), laheavyComputation()
méthode aurait quand même été exécutée .Configuration
La configuration dépend assez de votre infrastructure de journalisation, mais ils offrent principalement les mêmes techniques pour cela:
Ils offrent également principalement les mêmes capacités:
Voici un exemple courant de configuration déclarative, à l'aide d'un
logback.xml
fichier.Comme mentionné, cela dépend de votre framework et il peut y avoir d'autres alternatives (par exemple, LogBack permet également d'utiliser un script Groovy). Le format de configuration XML peut également varier d'une implémentation à l'autre.
Pour plus d'exemples de configuration, veuillez vous référer (entre autres) à:
Du plaisir historique
S'il vous plaît noter que Log4J est de voir une mise à jour majeure pour le moment, la transition de la version 1.x à 2.x . Vous voudrez peut-être jeter un œil à la fois pour plus de plaisir historique ou de confusion, et si vous choisissez Log4J, vous préférerez probablement la version 2.x.
Il convient de noter, comme Mike Partridge l'a mentionné dans les commentaires, que LogBack a été créé par un ancien membre de l'équipe Log4J. Qui a été créé pour combler les lacunes du cadre de journalisation Java. Et que la prochaine version majeure de Log4J 2.x intègre elle-même maintenant quelques fonctionnalités tirées de LogBack.
Recommandation
En bout de ligne, restez découplé autant que vous le pouvez, jouez avec quelques-uns et voyez ce qui vous convient le mieux. En fin de compte, ce n'est qu'un cadre de journalisation . Sauf si vous avez une raison très spécifique, en dehors de la facilité d'utilisation et des préférences personnelles, l'une d'entre elles serait plutôt OK, il n'y a donc pas de raison de s'y accrocher. La plupart d'entre eux peuvent également être étendus à vos besoins.
Pourtant, si je devais choisir une combinaison aujourd'hui, j'irais avec LogBack + SLF4J. Mais si vous me l'aviez demandé quelques années plus tard, j'aurais recommandé Log4J avec Apache Commons Logging, alors gardez un œil sur vos dépendances et évoluez avec elles.
la source
static
, car cela économise une petite quantité de mémoire, mais provoque des problèmes dans certains cas: slf4j.org/faq.html#declared_staticutiliser un cadre de journalisation
la plupart du temps, il y a une méthode d'usine statique
alors vous pouvez sortir votre code de journalisation avec différents niveaux:
alors il y aura un seul fichier où vous pouvez définir quels messages pour chaque classe doivent être écrits dans la sortie du journal (fichier ou stderr)
la source
C'est exactement à cela que servent les frameworks de journalisation comme log4j ou slf4j plus récent. Ils vous permettent de contrôler la journalisation dans les moindres détails et de la configurer même lorsque l'application est en cours d'exécution.
la source
Un cadre de journalisation est certainement la voie à suivre. Cependant, vous devez également disposer d'une bonne suite de tests. Une bonne couverture des tests peut souvent éliminer la nécessité d'une sortie de débogage tous ensemble.
la source