L'impression sur console / sortie standard est-elle une bonne stratégie de débogage?

11

Disons que nous avons une fonction comme celle-ci:

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Maintenant, pour une raison quelconque, notre code ne fonctionne pas. Peut-être que cela génère une erreur, peut-être qu'il renvoie la mauvaise valeur, peut-être qu'il est coincé dans une boucle infinie.

La première chose que tout programmeur de première année est d'imprimer sur console / sortie standard (après avoir appris à imprimer Hello World avant d'apprendre à utiliser un débogueur).

Par exemple, pour déboguer ce code, ils peuvent effectuer les opérations suivantes:

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Maintenant, ils exécutent le code, ils obtiennent une grande impression de la console, qu'ils peuvent parcourir pour localiser les problèmes.

Une alternative est bien sûr de définir des points d'arrêt et de parcourir le code à chaque point.

Un avantage majeur de l'impression sur console est que le développeur peut voir le flux des valeurs en une seule fois, sans avoir à cliquer sur les étapes, etc.

Mais l'inconvénient est que votre code est ensuite criblé de toutes ces instructions d'impression qui doivent ensuite être supprimées.

(Est-il possible de dire au débogueur d'imprimer uniquement certaines valeurs dans un journal?, Les points d'arrêt peuvent ensuite être facilement ajoutés ou supprimés sans réellement modifier le code.)

J'utilise toujours l'impression sur console comme méthode de débogage principale, je me demande à quel point c'est courant / efficace par rapport à autre chose.

dwjohnston
la source
1
Vous devez apprendre à utiliser un débogueur et à utiliser une infrastructure de journalisation appropriée. Cela vous rendra beaucoup plus heureux que d'imprimer sur la console (qui n'existe pas toujours).
7
Il est important d'apprendre à utiliser les débogueurs, cependant, il existe de nombreuses situations où le débogage printf est la seule méthode de débogage disponible.
whatsisname

Réponses:

26

Les instructions d'impression et le débogueur ne s'excluent pas mutuellement. Ce ne sont que différents outils à votre disposition pour localiser / identifier les bugs. Il y a ceux qui prétendent qu'ils ne touchent jamais à un débogueur et il y a ceux qui n'ont aucune instruction logging / print n'importe où dans le code qu'ils écrivent. Mon conseil est que vous ne voulez faire partie d'aucun de ces groupes.

Au lieu de cela, apprenez à utiliser la journalisation et apprenez à utiliser un débogueur. Avec l'expérience, vous choisirez (presque sans y avoir pensé) le bon outil et accomplirez le travail avec précision et efficacité. Sans expérience, vous choisirez parfois l'un au-dessus de l'autre, et cela vous prendra peut-être un peu plus de temps à fouiller les variables ou à parcourir les fichiers journaux, mais cela fait partie du processus d'apprentissage.

Donc, pour répondre à votre question spécifique. Oui. L'utilisation d'impressions pour tracer l'exécution est une bonne stratégie de débogage largement utilisée. Toutefois...

Au lieu d'utiliser des instructions d'impression, envisagez d'utiliser un cadre de journalisation. Les cadres de journalisation ont un concept de niveaux de journalisation afin que vous puissiez ajouter un tas de messages de journal mais choisir un niveau pour chacun. Lorsque votre application s'exécute dans des conditions normales, votre niveau serait ERREUR ou AVERTISSEMENT afin que seuls les éléments importants soient signalés. Cependant, lorsque vous parcourez le code et avez besoin de comprendre le flux d'exécution, vous pouvez remplacer l'enregistreur par INFO ou DEBUG et maintenant toutes les instructions "print" que vous avez déjà dans le code rapporteront des informations supplémentaires.

Utilisation d'un cadre de journalisation ...

  1. vous n'aurez pas besoin de supprimer toutes les impressions une fois que vous aurez terminé.
  2. les impressions que vous laissez dans le code peuvent vous aider, vous ou tout autre développeur, à déboguer ce même code à l'avenir
  3. vous pourrez déboguer ce code sur le terrain sans avoir à le reconstruire à chaque fois juste pour ajouter les impressions que vous avez supprimées.
  4. vous pourrez rediriger les messages de journalisation où vous le souhaitez, pas seulement une console. Ils pourraient aller dans un fichier, syslog, DB, socket ... etc

Mise à jour: je viens de remarquer à la fin que vous demandiez: "Est-il possible de dire au débogueur d'imprimer uniquement certaines valeurs dans un journal". Selon le débogueur que vous utilisez. De nombreux débogueurs modernes vous permettent de définir une action à invoquer lorsqu'un point d'arrêt est atteint. Dans certains (je l'ai fait dans VS et WinDbg), il est possible de spécifier "imprimer ceci et reprendre". Visual Studio les appelle des "points de trace" au lieu de "points d'arrêt"

DXM
la source
+1 pour le premier paragraphe. Les débogueurs et les journaux résolvent deux problèmes très différents.
Blrfl
1
Mais n'êtes-vous pas d'accord pour dire que laisser les instructions de journal dans le code la laid?
dwjohnston
1
dépend du type d'instructions de journal que vous laissez en place. Je viens de trouver et de supprimer celui-ci: "logger.error (" WHAT ")". Sinon, je traite le code de journalisation comme le reste de mon code. Formatez-le, rendez-le joli et informatif. Ouais, saupoudrer une déclaration d'impression toutes les deux lignes est un peu trop et il y a eu des moments où j'ai dû y recourir. Mais généralement, avoir 10 à 20 instructions de journal dans tout le fichier (les fichiers / classes étant de taille raisonnable et non gigantesques) n'est pas mauvais du tout.
DXM
Je reçois que laisser quelques déclarations de journaux dans pourrait être utile, par exemple si vous avez un système de production , vous voudrez peut - être vous connecter diverses variables importantes car ils sont utilisés si une erreur ne surgissent que vous pouvez voir immédiatement ce qui est arrivé dans votre production environnement. Cependant, pour le contexte du développement, cela semble désordonné. Par exemple, vous écrivez votre fonction d'analyse, et vous n'avez pas tout à fait raison votre expression rationnelle - vous avez donc mis une série d'instructions de journal juste pour vérifier ce qui se passe, et finalement le trier. Je ne pense pas que cela ajoute de la valeur à l'avenir pour les laisser entrer.
dwjohnston
1
@Izkata: tout dépendrait des spécificités de votre bug spécifique et de la quantité de journalisation de votre code. Ce que j'essaie de faire comprendre, c'est qu'il est toujours utile d'avoir des instructions de journalisation et de les avoir à différents niveaux: ERR -> WARN ... -> DEBUG. Si vous avez besoin de plus pour quelque chose de très spécifique, commencez par ajouter des instructions d'impression. Mais ma réponse à quelqu'un qui utilise "print" comme déclaration de journalisation, sera toujours de passer à un framework et de commencer à l'utiliser.
DXM
3

La journalisation / impression et les débogueurs sont des techniques complémentaires qui ont des forces et des faiblesses différentes - il est préférable d'utiliser les deux. Mais dans l'ensemble, je dirais que les débogueurs sont l'outil supérieur dans la plupart des cas et doivent être utilisés en premier, la journalisation / impression n'étant utilisée que pour les choses pour lesquelles il est réellement meilleur.

Avantages des débogueurs:

  • Vous pouvez inspecter tout l'état du programme, pas seulement les valeurs que vous pensiez imprimer à l'avance. Cela peut massivement accélérer le processus de débogage en réduisant le cycle de rétroaction à moins d'une seconde. Particulièrement important lorsqu'il faut du temps pour atteindre le bogue.
  • Vous pouvez voir d'où proviennent les appels et même inspecter les valeurs de la trace de la pile.
  • Vous pouvez (dans une certaine mesure, cela dépend de la langue / platfrom) du code de débogage que vous ne pouvez pas facilement modifier car vous n'avez que le code binaire ou octet compilé.

Avantages de l'enregistrement / de l'impression:

  • Il ne nécessite pas de construction ou de configuration de débogage spéciale. Ça marche toujours.
  • Peut être utilisé pour analyser des erreurs difficiles à reproduire et qui se produisent rarement
  • Peut être utilisé pour analyser les erreurs dépendant du timing où la pause causée par un débogueur peut facilement faire disparaître le bogue.
  • Vous donne des informations permanentes que vous pouvez analyser à votre guise. Vous pouvez faire des allers-retours entre les sorties à différents points du déroulement du programme.
Michael Borgwardt
la source
Un autre avantage de la journalisation est que vous ne rencontrez le problème qu'au énième passage dans votre code et que vous pouvez vraiment utiliser une trace de la façon dont vous y êtes arrivé. La plupart des débogueurs n'ont pas de bouton inversé, mais l'enregistrement des valeurs avec lesquelles une fonction de niveau supérieur a été appelée fonctionnera, et vous rapprochera souvent au moins d'un petit boîtier reproductible.
Christopher Creutzig
1

L'impression sur une sortie standard d'une manière peut être une bonne stratégie pour déboguer votre code, par exemple

  • j'utilise beaucoup d'instructions d'impression pour voir ce qui se passe à différents niveaux de mon code, surtout si je ne comprends pas complètement l'erreur

  • ou peut-être que l'erreur ne contient aucune information détaillée qui pourrait me diriger vers la partie du code à l'origine du problème.

Cependant, vous devez vous habituer aux outils de débogage, il y en a beaucoup selon la langue ou la plate-forme que vous utilisez.

Une autre méthode est également la journalisation, je journalise les erreurs tout le temps lorsque je travaille sur des applications Android, également avec la gestion des exceptions, on peut facilement consigner une trace de pile ou un message d'erreur de l'exception levée.

Plaix
la source
3
ce post est assez difficile à lire (mur de texte). Pourriez-vous le modifier sous une meilleure forme?
moucher
Je l'ai rendu un peu lisible. Désolé pour le précédent!
Plaix