Pourquoi l'utilisation de System.out.println () est-elle si mauvaise? [fermé]
18
Bien sûr, il est très utile d'utiliser un cadre de journalisation pour les messages d'erreur ou les avertissements. Mais parfois j'utilise System.out.println () si je veux essayer quelque chose de nouveau en peu de temps.
Est-ce vraiment si mauvais d'utiliser System.out.println () pour un test rapide?
Qui a dit que c'était mauvais? Quelle est l'alternative?
James
1
Les outils de révision de code statique @Kayser sont inappropriés pour des tests rapides - ils sont plutôt pour le code que vous avez l'intention de développer avec d'autres (ou que d'autres devront comprendre). La leçon que je semble apprendre cette année est qu'il existe des espaces de problèmes très différents, même tout au long de la journée de travail, qui nécessitent des outils et des pratiques très différents. Donc, pour votre test rapide, jetez tout et utilisez Groovy :)
Bill K
1
Essayez d'utiliser System.err.println()et voyez ce qui se passe. Je suppose que l'outil pense que vous utilisez System.outdans le mauvais but.
Izkata
2
Le principal problème concerne l'évolutivité et le contrôle. Si vous avez des millions de ces déclarations, comment pouvez-vous voir ce que vous devez voir. Si vous devez réagir à l'un de ces éléments, comment pouvez-vous le faire par programme? Les cadres de journalisation sont généralement ces deux pensées appliquées à System.out.
Réponses:
18
Comme indiqué dans les commentaires, la vraie question posée est la suivante: pourquoi les outils d'analyse de code statique signalent-ils les utilisations de System.out.println?
La raison en est que l'envoi de messages à stdout est généralement inapproprié dans un environnement de production. Si vous codez une bibliothèque, la bibliothèque doit renvoyer des informations à son appelant, pas imprimer sur stdout. Si vous codez une application GUI, les informations doivent être présentées à l'utilisateur, pas à l'endroit où stdout pointe (ce qui pourrait être nulle part). Si vous codez un serveur (ou quelque chose qui s'exécute dans un conteneur côté serveur), vous devez utiliser la fonction de journalisation fournie par le framework. Et ainsi de suite.
Mais si vous utilisez println pour le débogage ou le développement, ou si vous écrivez un programme et lit stdin et écrit sur stdout, println est parfaitement correct. Il n'y a rien de mal à ce genre de cas.
Bonne réponse. Merci .. +1 pour "Si vous codez une application GUI, les informations doivent être présentées à l'utilisateur, pas à l'endroit où stdout pointe (ce qui pourrait être nulle part)"
Kayser
10
Tout stdoutest mis en mémoire tampon, et il est donc possible que votre programme se bloque après votre appel println(), mais avant qu'il n'atteigne l'écran.
Cela étant dit, ce scénario est vraiment peu probable. Allez-y et utilisez-le, mais gardez juste cette limitation mineure à l'esprit.
Au moins deux principaux interprètes Python essaient très fort de vider tous les fichiers ouverts avant de quitter, même si la sortie est due à une exception non gérée. Les JVM ne font-elles pas quelque chose de similaire?
1
@delnan, peut-être, mais tout peut arriver. (Le code qui vide stdout pourrait être là où le problème fait surface. Le thread que vous exécutez pourrait être forcé. Le processus actuel pourrait être forcé de mémoire de l'OS.) Ne vivez pas votre vie autour de ma déclaration, mais soyez juste au courant.
riwalk
1
Le code qui vide stdout se trouve dans la machine virtuelle elle-même et n'est donc pas affecté par les erreurs dans la langue que la machine virtuelle implémente. Bon point sur la fin du processus forcé. Mais notez que par exemple le SIGTERM d'Unix et la plupart des autres signaux peuvent être capturés pour faire un nettoyage comme celui-ci - ne fonctionne pas avec le SIGKILL plus extrême.
2
Je ne pense pas avoir jamais vu cela ou entendu parler de cela, même si j'ai vu d'autres problèmes. Il est également peu probable que ce problème s'améliore avec des outils tels que les enregistreurs car ils sont susceptibles d'utiliser System.out comme outil sous-jacent.
System.outest juste un enveloppé BufferedOutputStream. Ceci est probablement similaire à n'importe quel cadre de journalisation que vous utiliserez, les cadres fournissent simplement plus de fonctionnalités sous la forme de configuration et de destination de votre sortie de journal
La plupart des IDE doivent avoir des raccourcis clavier pour la saisie automatique de System.out.println, commenter / décommenter une ligne et supprimer une ligne. Vous avez raison en principe d'essayer d'éviter une utilisation excessive de celui-ci, mais vous pouvez au moins gagner du temps de cette façon.
Steven
7
Il y a quelques mises en garde sur l'utilisation System.out, même dans le code jetable.
Un problème majeur est qu'il est généralement lent . Par exemple, si vous essayez d'avoir une idée approximative de la vitesse d'un code (notez que les microbenchmarks sont difficiles ), alors ajouter un seul System.out.println()n'importe où peut vraiment gâcher votre timing (car il se synchronise et attend souvent la sortie réelle pour être visible par l'utilisateur avant de revenir).
En dehors de cela, je ne m'en inquiéterais pas trop dans le code jetable. Si vous avez l'intention de le valider (que ce soit en tant que code de production ou code de test), vous devez vous en débarrasser et le remplacer par un appel de journalisation propper (oui, même en code de test).
Comme c'est souvent le cas, la réponse est «cela dépend». Si votre application dispose déjà d'un cadre de journalisation, vous pouvez également l'utiliser. Il ne peut pas être moins performant que vous println(), et vous pouvez bénéficier d'autres fonctionnalités qu'il fournit: traces de pile, contexte supplémentaire, meilleur formatage, etc. Il existe également la possibilité distincte que les cadres de journalisation offrent une meilleure récupération des erreurs, garantissant que vos journaux sont correctement écrits, même en cas de défaillance catastrophique.
La question devient donc quand ajouter un système de journalisation en premier lieu. C'est un appel au jugement: vous ne voulez pas l'ajouter trop tôt, seulement pour découvrir que vous n'en avez vraiment pas besoin. Vous ne voulez pas non plus l'ajouter trop tard et effectuer un travail excessif de conversion à partir de votre solution ad-hoc.
Si vous découvrez que vous vous connectez beaucoup println(), votre base de code essaie de vous dire qu'elle éprouve des douleurs croissantes. À ce stade, il vaut la peine d'investir dans une journalisation appropriée.
J'ai souvent le problème que System.out.print utilise la page de code "par défaut du système", qui est souvent UTF-8 sous Linux, mais quelques trucs MS misérable sous Windows.
Cela peut conduire à des caractères Unicode qui sont ou ne sont pas correctement imprimés à l'écran, selon l'endroit où le programme s'exécute.
Je préfère donc un PrintWriter personnalisé à System.out
Par des trucs MS chiés. Vous voulez dire CP1352 ou UTF16?
Cole Johnson
@ColeJohnson: La fenêtre de la console Windows est malheureusement toujours bloquée à une époque pré-UTF16. L'utilisation d'un IDE sain avec une console intégrée peut cependant réduire ce problème.
Joachim Sauer
@Cole Johnson - Je pourrais vivre avec le CP 65001 (c'est-à-dire utf8), mais il semble qu'il n'y ait aucun moyen d'obtenir cela comme page de code "par défaut du système", lorsque, par exemple, vous avez un clavier allemand, vous obtenez le CP 850 ou quelque chose du genre.
Ingo
1
Ce n'est pas mal du tout. La notion peut provenir du fait que c'est très simple et pas aussi sophistiqué que d'utiliser un cadre de journalisation dédié dans votre application.
Cependant, cela ne veut pas dire que c'est une approche invalide. Je l'ai utilisé à plusieurs reprises pour vérifier le flux d'application après quelques détournements de programmation de magie noire vaudou .
Le plus gros problème avec le System.out.println occasionnel, comme je le vois, est que c'est une "mauvaise odeur d'habitude (tm)". Si vous vous trouvez en train de faire cela, alors vous pourriez probablement améliorer votre efficacité en vous sentant plus à l'aise avec votre débogueur préféré.
De plus, avec un débogueur, vous savez avec certitude qu'un point d'arrêt ne glissera pas dans votre code de production, contrairement à System.out.println.
Soit dit en passant, si vous effectuez simplement un test rapide et persiste à ne pas utiliser de débogueur, je pense que System.out.println est mieux que d'utiliser un cadre de journalisation, car si vous laissez accidentellement une instruction log.debug lorsque vous c'est fait, c'est plus difficile à extirper.
Construire une stratégie de test entière autour de l'écho du contenu de l'état interne n'est pas le plus intelligent, mais pour des tests de code rapides et sales en cours de développement, l'impression étrange ici et là ne fera pas de mal tant que vous vous souvenez de les supprimer!
Le danger d'oublier de les retirer est probablement pourquoi il est déconseillé.
System.err.println()
et voyez ce qui se passe. Je suppose que l'outil pense que vous utilisezSystem.out
dans le mauvais but.Réponses:
Comme indiqué dans les commentaires, la vraie question posée est la suivante: pourquoi les outils d'analyse de code statique signalent-ils les utilisations de System.out.println?
La raison en est que l'envoi de messages à stdout est généralement inapproprié dans un environnement de production. Si vous codez une bibliothèque, la bibliothèque doit renvoyer des informations à son appelant, pas imprimer sur stdout. Si vous codez une application GUI, les informations doivent être présentées à l'utilisateur, pas à l'endroit où stdout pointe (ce qui pourrait être nulle part). Si vous codez un serveur (ou quelque chose qui s'exécute dans un conteneur côté serveur), vous devez utiliser la fonction de journalisation fournie par le framework. Et ainsi de suite.
Mais si vous utilisez println pour le débogage ou le développement, ou si vous écrivez un programme et lit stdin et écrit sur stdout, println est parfaitement correct. Il n'y a rien de mal à ce genre de cas.
la source
Tout
stdout
est mis en mémoire tampon, et il est donc possible que votre programme se bloque après votre appelprintln()
, mais avant qu'il n'atteigne l'écran.Cela étant dit, ce scénario est vraiment peu probable. Allez-y et utilisez-le, mais gardez juste cette limitation mineure à l'esprit.
la source
System.out
est juste un enveloppéBufferedOutputStream
. Ceci est probablement similaire à n'importe quel cadre de journalisation que vous utiliserez, les cadres fournissent simplement plus de fonctionnalités sous la forme de configuration et de destination de votre sortie de journalla source
C'est mauvais si vous travaillez sur un programme non trivial et que vous
la source
Il y a quelques mises en garde sur l'utilisation
System.out
, même dans le code jetable.Un problème majeur est qu'il est généralement lent . Par exemple, si vous essayez d'avoir une idée approximative de la vitesse d'un code (notez que les microbenchmarks sont difficiles ), alors ajouter un seul
System.out.println()
n'importe où peut vraiment gâcher votre timing (car il se synchronise et attend souvent la sortie réelle pour être visible par l'utilisateur avant de revenir).En dehors de cela, je ne m'en inquiéterais pas trop dans le code jetable. Si vous avez l'intention de le valider (que ce soit en tant que code de production ou code de test), vous devez vous en débarrasser et le remplacer par un appel de journalisation propper (oui, même en code de test).
la source
Comme c'est souvent le cas, la réponse est «cela dépend». Si votre application dispose déjà d'un cadre de journalisation, vous pouvez également l'utiliser. Il ne peut pas être moins performant que vous
println()
, et vous pouvez bénéficier d'autres fonctionnalités qu'il fournit: traces de pile, contexte supplémentaire, meilleur formatage, etc. Il existe également la possibilité distincte que les cadres de journalisation offrent une meilleure récupération des erreurs, garantissant que vos journaux sont correctement écrits, même en cas de défaillance catastrophique.La question devient donc quand ajouter un système de journalisation en premier lieu. C'est un appel au jugement: vous ne voulez pas l'ajouter trop tôt, seulement pour découvrir que vous n'en avez vraiment pas besoin. Vous ne voulez pas non plus l'ajouter trop tard et effectuer un travail excessif de conversion à partir de votre solution ad-hoc.
Si vous découvrez que vous vous connectez beaucoup
println()
, votre base de code essaie de vous dire qu'elle éprouve des douleurs croissantes. À ce stade, il vaut la peine d'investir dans une journalisation appropriée.la source
J'ai souvent le problème que System.out.print utilise la page de code "par défaut du système", qui est souvent UTF-8 sous Linux, mais quelques trucs MS misérable sous Windows.
Cela peut conduire à des caractères Unicode qui sont ou ne sont pas correctement imprimés à l'écran, selon l'endroit où le programme s'exécute.
Je préfère donc un PrintWriter personnalisé à System.out
la source
Ce n'est pas mal du tout. La notion peut provenir du fait que c'est très simple et pas aussi sophistiqué que d'utiliser un cadre de journalisation dédié dans votre application.
Cependant, cela ne veut pas dire que c'est une approche invalide. Je l'ai utilisé à plusieurs reprises pour vérifier le flux d'application après quelques détournements de programmation de magie noire vaudou .
la source
Il n'y a rien de mal à l'utiliser, cela vous aide à comprendre «ce qui se passe».
Mais si vos pairs / autres développeurs / outils vous ridiculisent, vous pouvez toujours utiliser Logger ou lancer les tests Junit !
la source
Le plus gros problème avec le System.out.println occasionnel, comme je le vois, est que c'est une "mauvaise odeur d'habitude (tm)". Si vous vous trouvez en train de faire cela, alors vous pourriez probablement améliorer votre efficacité en vous sentant plus à l'aise avec votre débogueur préféré.
De plus, avec un débogueur, vous savez avec certitude qu'un point d'arrêt ne glissera pas dans votre code de production, contrairement à System.out.println.
Soit dit en passant, si vous effectuez simplement un test rapide et persiste à ne pas utiliser de débogueur, je pense que System.out.println est mieux que d'utiliser un cadre de journalisation, car si vous laissez accidentellement une instruction log.debug lorsque vous c'est fait, c'est plus difficile à extirper.
la source
Construire une stratégie de test entière autour de l'écho du contenu de l'état interne n'est pas le plus intelligent, mais pour des tests de code rapides et sales en cours de développement, l'impression étrange ici et là ne fera pas de mal tant que vous vous souvenez de les supprimer!
Le danger d'oublier de les retirer est probablement pourquoi il est déconseillé.
la source