En termes très généraux, ce que je fais est:
Essayez d'isoler le problème. Pensez à ce qui a changé lorsque le bogue est apparu pour la première fois. Sur quoi travaillez-vous? Quelle partie du code modifiez-vous? 99% de mes bugs sont résolus de cette façon. C'est généralement quelque chose de stupide.
Si je devine où est le problème, jetez un œil au code qui semble être la cause. Lis le. Lisez-le à haute voix même. Demandez-vous: "Qu'est-ce que j'essaie de réaliser?". Pour certains types de problèmes: pourrait-il avoir des effets secondaires ou pourrait-il être affecté par du code à un autre endroit d'une manière à laquelle je n'avais pas pensé?
Essayez de différentes manières d'analyser ce qui ne va pas, où et quand (voir ci-dessous).
Si je n'ai toujours aucun indice, je vérifie si une ancienne version de ma source a le même problème, essayez de trouver quand dans ma chronologie de développement le problème est apparu pour la première fois. Pour ce faire, vous devez travailler avec un bon système de contrôle de version, tel que git (git a une fonctionnalité appelée bissect exactement pour ce type de débogage).
Si vous n'avez toujours aucun indice, faites une pause ... cela aide souvent.
Revenez à la planche à dessin - examinez comment votre programme est censé fonctionner et si cela a du sens.
Cela dépend vraiment du type de problème, mais en supposant que j'ai une idée générale de l'endroit où le problème pourrait être, alors:
Si je soupçonne que le problème est dans une partie du code / modification récente, j'essaie d'abord de supprimer / commenter / modifier ou quoi que ce soit pour faire disparaître le bogue en simplifiant le code, puis ramener le code problématique et prendre un bon coup d'oeil.
Exécutez un débogueur avec des points d'arrêt (si possible) et regardez comment mes données semblent essayer de trouver quand elles commencent à mal fonctionner, pour avoir une meilleure idée de l'endroit où les choses tournent mal.
bzr qdiff
commande.J'essaie d'utiliser le développement piloté par les tests ( TDD ). J'écris un test qui reproduit le bogue, puis j'essaie de réussir le test. Parfois, le fait d'écrire le test aide à trouver le bogue.
Cela me tient hors du débogueur la plupart du temps et fournit des tests de régression pour éviter de réintroduire le bogue.
Quelques liens:
la source
Il existe un certain nombre de définitions du mot science, mais il semble que vous vous référiez peut-être à ce que l'on pourrait appeler plus précisément la " méthode scientifique ". La méthode scientifique peut être résumée comme l'observation de certains phénomènes (vraisemblablement un bug ou un comportement de programme inattendu), la formulation d'une ou de plusieurs hypothèses pour expliquer le comportement, et l'expérimentation la plus probable pour le prouver (écrire un test qui reproduit le problème de manière fiable).
Les types de bugs (phénomènes) qui peuvent survenir sont pratiquement infinis et certains ne nécessitent pas nécessairement un processus bien défini. Par exemple, parfois vous observez un bogue et vous savez instantanément ce qui l'a causé simplement parce que vous êtes très familier avec le code. D'autres fois, vous savez qu'à partir d'une certaine entrée (action, série d'étapes, etc.), un résultat incorrect se produit (plantage, mauvaise sortie, etc.). Pour ces cas, cela ne nécessite souvent pas beaucoup de réflexion "scientifique". Une réflexion peut aider à réduire l'espace de recherche, mais une méthode courante consiste simplement à parcourir le code dans un débogueur et à voir où les choses ont mal tourné.
Cependant, les situations que je trouve les plus intéressantes et peut-être dignes d'un processus scientifique sont celles où l'on vous remet un résultat final et qu'on vous demande d'expliquer comment cela s'est produit. Un exemple évident de ceux-ci est un vidage sur incident. Vous pouvez charger le vidage sur incident et observer l'état du système et votre travail consiste à expliquer comment il est arrivé dans cet état. Le vidage sur incident (ou principal) peut afficher une exception, un blocage, une erreur interne ou un état "indésirable" tel que défini par l'utilisateur (par exemple, lenteur). Pour ces situations, je suis généralement suivre les étapes suivantes:
Observation étroite : Étudiez les informations entourant directement le problème spécifique, le cas échéant. Les choses évidentes ici sont la pile d'appels, les variables locales si vous pouvez les voir, les lignes de code entourant le problème. Ce type d'étude de localisation spécifique n'est pas toujours applicable. Par exemple, l'étude d'un système "lent" peut ne pas avoir un emplacement de départ évident comme celui-ci, mais une situation de crash ou d'erreur interne aura probablement un point d'intérêt immédiat et évident. Une étape spécifique ici pourrait être d'utiliser des outils tels que windbg (exécutez! Analyse -v sur un vidage sur incident chargé et regardez ce qu'il vous dit).
Large observation : étudiez d'autres parties du système. Examinez l'état de tous les threads du système, examinez toutes les informations globales (nombre d'utilisateurs / opérations / éléments, transactions / processus / widgets actifs, etc.), les informations du système (OS), etc. Si l'utilisateur a fourni des détails externes , pensez à ceux-ci en conjonction avec ce que vous avez observé. Par exemple, s'ils vous ont dit que le problème se produit tous les mardis après-midi, demandez-vous ce que cela pourrait signifier.
Hypothétiser: C'est la partie vraiment amusante (et je ne suis pas gênant que ce soit amusant). Cela nécessite souvent beaucoup de réflexion logique à l'envers. Il peut être très agréable de penser à la façon dont le système est entré dans son état actuel. Je soupçonne que c'est la partie que beaucoup de gens considèrent comme un art. Et je suppose que cela pourrait être si le programmeur commence simplement à lancer des choses au hasard pour voir ce qui colle. Mais avec l'expérience, cela peut être un processus assez bien défini. Si vous pensez très logiquement à ce stade, il est souvent possible de définir des ensembles possibles de chemins qui ont conduit à l'état donné. Je sais que nous sommes dans l'état S5. Pour que cela se produise, S4a ou S4b devait se produire et peut-être S3 avant S4a, etc. Le plus souvent, il peut y avoir plusieurs éléments qui pourraient conduire à un état donné. Parfois, il peut être utile d'écrire sur un bloc-notes un simple diagramme de flux ou d'état ou une série d'étapes liées au temps. Les processus réels ici varieront considérablement en fonction de la situation, mais une réflexion sérieuse (et un réexamen dans les étapes précédentes) à ce stade fournira souvent une ou plusieurs réponses plausibles. Notez également qu'une partie extrêmement importante de cette étape consiste à éliminer les choses impossibles. Supprimer l'impossible peut aider à réduire l'espace de la solution (rappelez-vous ce que Sherlock Holmes a dit sur ce qui reste après avoir éliminé l'impossible). Notez également qu'une partie extrêmement importante de cette étape consiste à éliminer les choses impossibles. Supprimer l'impossible peut aider à réduire l'espace de la solution (rappelez-vous ce que Sherlock Holmes a dit sur ce qui reste après avoir éliminé l'impossible). Notez également qu'une partie extrêmement importante de cette étape consiste à éliminer les choses impossibles. Supprimer l'impossible peut aider à réduire l'espace de la solution (rappelez-vous ce que Sherlock Holmes a dit sur ce qui reste après avoir éliminé l'impossible).
Expérience : Dans cette étape, essayez de reproduire le problème sur la base des hypothèses dérivées à l'étape précédente. Si vous avez réfléchi sérieusement à l'étape précédente, cela devrait être très simple. Parfois, je "triche" et modifie la base de code pour aider un test donné. Par exemple, j'ai récemment enquêté sur un accident dont j'ai conclu qu'il s'agissait d'une condition de course. Afin de le vérifier, j'ai simplement mis un Sleep (500) entre quelques lignes de code pour permettre à un autre thread de faire ses mauvaises choses au "bon" moment. Je ne sais pas si cela est autorisé dans la "vraie" science, mais c'est parfaitement raisonnable dans le code que vous possédez.
Si vous réussissez à le reproduire, il est probable que vous ayez presque terminé (il ne vous reste plus qu'à la réparer ... mais c'est pour un autre jour). Assurez-vous de vérifier le nouveau test dans le système de test de régression. Et je dois souligner que je voulais que cette déclaration précédente sur le fait qu'il soit simple d'être ironique. La recherche d'une solution et sa mise en œuvre peuvent nécessiter un travail important. Je pense que la correction d'un bogue ne fait pas partie du processus de débogage mais est plutôt du développement. Et si le correctif est impliqué, cela devrait nécessiter une certaine conception et une révision.
la source
Essayez de réduire le cas de test. Lorsqu'il est suffisamment petit, il est généralement plus facile de localiser le code correspondant à l'origine du problème.
Il est probable qu'un nouvel enregistrement soit à l'origine du problème et la version quotidienne précédente était correcte. Dans ce cas, votre journal des modifications du contrôle de code source devrait vous aider à décider qui intercepter.
De plus, si vous êtes en C / C ++, envisagez d'exécuter valgrind ou purifier pour isoler les problèmes liés à la mémoire.
la source
La partie la plus difficile du débogage consiste à isoler le problème, en particulier lorsque le problème est enfoui sous plusieurs couches. Au collège, j'ai étudié l'enregistrement de musique et, curieusement, il y avait un cours Studio Electronics qui s'applique directement ici. Je vais utiliser le débogage d'un environnement de studio comme illustration du processus de débogage systématique.
Le débogage du code n'est vraiment pas si différent. Le débogage est beaucoup plus facile lorsque le code lève une exception. Vous pouvez remonter à partir de la trace de pile de cette exception et définir des points d'arrêt à des positions clés. Habituellement, juste après avoir défini une variable, ou sur la ligne qui appelle la méthode qui lève l'exception. Vous pouvez constater qu'une ou plusieurs des valeurs ne sont pas correctes. Si ce n'est pas correct (une valeur nulle alors qu'il ne devrait pas y en avoir, ou la valeur est hors de portée), alors c'est un processus pour découvrir pourquoi ce n'est pas correct. Les points de rupture dans un IDE sont équivalents aux points de test électroniques (conçus pour une sonde de compteur pour vérifier le circuit).
Maintenant, une fois que j'ai traversé cette partie difficile de la découverte de mon vrai problème, je vais écrire des tests unitaires pour vérifier cela à l'avenir.
la source
Avec les bugs désagréables que j'ai du mal à retrouver en fin d'après-midi, ma stratégie la plus efficace est de me lever et de partir pendant quelques minutes. Habituellement, de nouvelles idées sur les sources d'erreur possibles commencent à apparaître après seulement 30 secondes.
la source
Pour une approche plus pratique:
Si le bogue est lié à une exception non gérée - regardez la trace de la pile. Les références nulles, index hors limites, etc. et vos propres exceptions définies sont les plus courantes, vous pouvez attribuer ce bug à un développeur junior, c'est probablement facile et une bonne expérience d'apprentissage.
Si cela ne se produit pas sur chaque machine, c'est probablement une forme de problème de concurrence / problème de thread. Ce sont super amusants à retrouver, mettez votre programmeur senior ennuyé dessus. Beaucoup de journalisation, de bonnes connaissances et de bons outils y parviennent.
Une autre grande classe de bogues est lorsque l'équipe de test ou le (s) client (s) n'aiment pas un comportement particulier. Par exemple, ils n'aiment pas que vous décidiez d'afficher les ID utilisateur ou que, lors de la recherche, vous n'obteniez pas de saisie semi-automatique. Ce sont de vrais bugs, pensez à avoir une meilleure gestion des produits et des développeurs avec une vue plus large. Cela devrait prendre un temps relativement court à un développeur pour "corriger" cela s'il construit le système en pensant à l'expansion.
80% de tous les autres bogues sont résolus en ayant un bon système de journalisation et en collectant suffisamment d'informations pour les résoudre. Utilisez le traçage intégré avec plusieurs niveaux de systèmes de journalisation complexes comme Log4Net / Log4J
les bogues de performance sont une catégorie à part, la règle la plus audacieuse ici est «mesurer d'abord, corriger plus tard! plus tard, une simple diminution de 3 à 4% du temps de réponse.
la source
J'ai deux approches:
Divide and Conquer
Paradigm.Ces approches m'ont aidé la plupart du temps.
la source