Passer trop de temps à déboguer


24

Hier, j'ai déployé une version v1.0 d'un projet Web sur lequel j'ai passé environ 6 semaines à travailler (on et off, c'est-à-dire). Je n'ai pas enregistré de manière exacte mon temps, mais d'après mes expériences, j'estimerais que sur tout le temps que j'ai passé à programmer, la moitié a été consacrée au débogage. J'estime que cela représente environ 15 à 20 heures de débogage, ce qui pour moi est un temps précieux qui aurait mieux valu être consacré à l'écriture de nouveau code ou à la fin du projet plus tôt. Cela n'aide surtout pas que je sois un étudiant de première année à l'université dans 5 semaines.

Le truc, c'est que je me sens mal d'avoir passé tout ce temps à déboguer. Tout ce temps passé à déboguer me fait réaliser que j'ai fait des erreurs assez stupides pendant que je développais mon projet, des erreurs qui m'ont coûté beaucoup de temps à réparer.

Comment puis-je empêcher que cela se produise à l'avenir? Je ne veux pas passer 50% de mon temps à déboguer, je préfère passer 10% à déboguer et le reste à écrire du nouveau code. Quelles techniques puis-je essayer pour m'aider à atteindre cet objectif?


22
Quand j'étais étudiant de première année, j'étais aussi un codeur lent. Donnez-lui juste 20 ans.
Job

27
euh oui, bonne chance avec ça. "Si le débogage est le processus de suppression des bogues. La programmation doit alors être le processus de leur insertion." -Edsger Dijkstra
Matt

7
Avez-vous appris quelque chose de ces erreurs? Si vous l'avez fait, vous ne les ferez pas la prochaine fois et cela réduira votre temps de débogage.
Craig T

5
Cela s'appelle "expérience" et vous aidera dans votre prochain projet.

4
Parlant de la fin des années 40, Maurice Wilkes a écrit: "Dès que nous avons commencé la programmation, nous avons été surpris de constater qu'il n'était pas aussi facile de bien programmer les programmes que nous le pensions. Le débogage devait être découvert. mes voyages entre la salle EDSAC et l'équipement de poinçonnage qui «hésitait aux angles des escaliers», la prise de conscience m'a pris de plein fouet qu'une bonne partie du reste de ma vie allait être consacrée à trouver des erreurs dans mes propres programmes. "
Trevor Powell,

Réponses:


35

Vous demandez le Saint Graal du génie logiciel, et personne n'a encore "la" réponse à cette question.

L'essentiel est de suivre les types d'erreurs que vous commettez, puis d'analyser ces erreurs pour déterminer s'il existe une tendance commune. L'analyse des causes profondes est le nom officiel de ce type d'introspection, et il existe de nombreuses informations sur le Web à ce sujet.

Les professionnels utilisent un système de suivi des bogues pour pouvoir (1) savoir ce qui doit être corrigé, mais aussi (2) analyser ce qui devait être corrigé après coup. Vous n'avez pas besoin d'être aussi formel - il suffit de garder un décompte dans un cahier.

Défauts de conception

Si vous trouvez que la plupart de vos erreurs proviennent d'une mauvaise compréhension de l'énoncé du problème, ou si vous continuez à trouver que vous avez choisi le mauvais algorithme ou la mauvaise voie à suivre pour résoudre vos problèmes, vous avez des problèmes au stade de la conception.

Il vous incomberait de prendre plus de temps au début du projet et d'écrire exactement ce qui doit être fait et comment il doit le faire. Examinez attentivement ce travail et revoyez le problème d'origine et déterminez si vous le résolvez vraiment de la bonne manière. Une ou trois heures supplémentaires au départ peuvent vous faire économiser de nombreuses heures sur la route.

Erreurs de codage

Si votre conception est solide, mais que vous combattez constamment le langage avec lequel vous codez, procurez-vous des outils qui analyseront votre code pour vous et vous avertiront tôt et souvent que vous faites des erreurs.

Si vous programmez en C, activez tous les avertissements du compilateur, utilisez un vérificateur sémantique comme lintet utilisez un outil comme valgrindpour détecter les problèmes courants liés à la mémoire dynamique.

Si vous programmez Perl, allumez strictet warningset garde à ce qu'il dit.

Peu importe la langue que vous utilisez, il existe probablement de nombreux outils pour détecter les erreurs courantes bien avant d'atteindre le stade de débogage.

Défauts de l'étape d'intégration

Au fur et à mesure que vous développez votre code en suivant les bonnes pratiques de modularité, vous devez commencer à coller les pièces séparées ensemble. Par exemple, différentes sections de votre code peuvent avoir à voir avec l'entrée utilisateur, l'interaction avec la base de données, l'affichage des données, les algorithmes / la logique, et chacun d'eux est construit relativement indépendamment les uns des autres (c'est-à-dire que vous avez tendance à vous concentrer sur la section à portée de main plutôt que de se soucier de l'intégration avec tout le reste).

C'est là que le développement piloté par les tests (TDD) est très pratique. Chaque module de votre code peut avoir des tests qui vérifient qu'ils fonctionnent selon la façon dont ils ont été conçus. Ces tests doivent être écrits en premier ou très tôt dans le processus afin que vous puissiez avoir un ensemble d '"aides" pour vous garder honnête. Lorsque vous commencez à tout faire fonctionner ensemble et que vous constatez que vous devez changer la façon dont ceci ou cela est implémenté ou interagit avec un autre sous-système, vous pouvez vous rabattre sur vos tests pour vous assurer que ce que vous avez fait pour faire tout cela fonctionne ensemble ne rompt pas l'exactitude du code.

Etc...

Prenez quelques livres sur le génie logiciel et les techniques de codage pratiques, et vous apprendrez de nombreuses façons de rendre le développement moins chaotique et plus fiable. Vous constaterez également qu'une simple expérience ancienne - obtenir un diplôme de l'école des coups durs - vous mettra également en forme.

Ce que presque tout se résume à cela, c'est qu'un peu de temps et de travail d'avance porte ses fruits dans d'énormes dividendes plus tard dans le processus de développement / sortie.

Le fait que vous ayez remarqué ces problèmes si tôt dans votre carrière en dit long sur votre avenir et je vous souhaite bonne chance.


1
Ceci est une excellente réponse, mais à mon humble avis à une question légèrement différente. L'OP dit que j'ai passé 6 semaines à écrire quelque chose et que j'ai dû passer beaucoup de temps à déboguer. Nous ne savons encore rien de la qualité, la maintenabilité, l'évolutivité de son produit. Si nous supposons TDD, une bonne conception, un suivi des bogues, il reste la question de savoir comment écrire du code (y compris du code de test qui doit également être débogué) avec moins de défauts. Activer les avertissements, utiliser de la charpie, etc. sont de bonnes suggestions. Plus de ceux de l'école des coups durs? :-)
Guy Sirton

1
@Guy - Ouais ... la question du PO était un peu vague, c'est pourquoi je suis allé en mettant l'accent sur l'analyse des causes profondes. Vous ne savez pas ce qui ne va pas tant que vous ne savez pas ce qui ne va pas. La raison pour laquelle j'ai donné l'enquête sur les zones à problèmes est parce que je voulais qu'il soit conscient de nombreux pièges potentiels et que chaque étape du processus mérite son propre examen. Pour autant que je sache, il est peut-être le prochain Tony Hoare, mais avec les compétences de frappe d'un éléphant aveugle - différentes corrections pour différentes causes.
unpythonic

37

Écrire des tests unitaires

L'écriture de tests unitaires pour votre code vous obligera à penser à votre architecture et vous encouragera à écrire votre code en petits morceaux soigneusement contrôlés et testables. Cela réduira considérablement vos efforts de débogage, et la petite quantité de débogage que vous effectuez sera limitée à de petits morceaux de code étroitement ciblés.

De plus, les tests que vous écrivez "couvriront" votre code; vous pourrez savoir quand une modification apportée au code casse quelque chose, car un ou plusieurs de vos tests existants échoueront. Cela réduit la complexité globale de votre effort de débogage et augmente votre confiance dans le fonctionnement du code.

Le hic, bien sûr, est que votre temps de débogage est désormais consacré à la rédaction de tests. Mais vous ne devez les écrire qu'une seule fois, et elles peuvent être exécutées autant de fois que nécessaire après les avoir écrites.


+1 pour les tests unitaires - plus tôt dans le processus de développement, les bogues sont détectés, moins ils sont faciles et faciles à corriger.
Paul R

26

50% pour le débogage (au sens large) n'est pas si mal. Les gens passent généralement beaucoup plus de temps à concevoir, tester, corriger des bogues, refactoriser et écrire des tests unitaires que vous n'écrivez le code réel. Cela fait partie du travail.

Et pour être honnête, c'est bien pire dans la programmation de la maintenance - très souvent, je passais une heure à comprendre ce qui ne va pas, puis cinq minutes à écrire le code pour le réparer, puis une demi-heure à tester le tout. C'est un peu plus de 5% de codage contre près de 95% de non-codage.

Il y a quelques choses que vous pouvez faire pour réduire le temps de débogage:

  • Écrivez du code débogable . Cela signifie: une gestion correcte des erreurs (avec une certaine réflexion), structurer votre code pour le rendre facile à suivre, en utilisant des assertions, des traces et tout ce qui peut faciliter la vie du débogueur. Évitez les lignes compliquées; une ligne qui fait plus d'une chose doit être divisée pour que vous puissiez les parcourir individuellement.
  • Écrivez du code testable . Divisez votre code en fonctions simples (ou tout ce que votre langue de choix prend en charge); éviter les effets secondaires, car ils sont difficiles à saisir dans les tests unitaires. Concevez vos fonctions afin qu'elles puissent être exécutées isolément. Évitez les fonctions polyvalentes. Évitez les cas de bord. Documentez ce que vos fonctions sont censées faire.
  • Écrivez des tests . Avoir des tests unitaires signifie que vous savez que vos fonctions fonctionnent pour au moins un sous-ensemble de leurs entrées; cela signifie également que vous avez un contrôle de santé mentale pour confirmer que vos modifications ne cassent rien. Assurez-vous de bien comprendre les concepts de couverture de code et de couverture d'entrée, ainsi que les limites des tests unitaires.
  • Mettre en place un «établi» . La façon exacte de procéder dépend de la langue en question. Certaines langues, comme Python ou Haskell, sont fournies avec un interpréteur interactif, et vous pouvez y charger votre code existant pour jouer avec. C'est parfait, car vous pouvez appeler vos fonctions dans le contexte de votre choix, avec un minimum d'effort - un outil précieux pour trouver et isoler les bogues. Les autres langues n'ont pas ce luxe, et vous devrez recourir à l'écriture de petits programmes de test interactifs.
  • Écrivez du code lisible . Prenez l'habitude d'écrire votre code pour exprimer vos intentions aussi clairement que possible. Documentez tout ce qui n'est pas parfaitement évident.
  • Écrivez un code simple . Si votre propre cerveau a du mal à comprendre l'intégralité de la base de code, alors ce n'est pas simple, et il est très peu probable que quelqu'un d'autre puisse le comprendre pleinement. Vous ne pouvez pas déboguer le code efficacement à moins de comprendre ce qu'il est censé faire.
  • Soyez facile sur le bouton «Supprimer» . Tout code dont vous n'avez pas besoin à l'heure actuelle appartient à la poubelle. Si vous en avez besoin plus tard, faites-le revivre à partir du contrôle de source (l'expérience montre que c'est extrêmement rare). Plus vous disposez de code, plus votre surface de débogage est petite.
  • Refactorisez tôt et souvent. Sans refactoring, vous ne pouvez pas conserver votre code dans un état débogable lors de l'ajout de nouvelles fonctionnalités.

1
De plus, le monde peut se comporter différemment de ce que vous attendez en cas de problème. Cela peut provoquer des bugs très subtils.

2
+1. Je dirais que seulement 50% des dépenses de débogage sont assez faibles, surtout mais pas seulement dans une base de code établie. Si je reçois un bogue, à moins qu'il ne nécessite à peu près une réécriture complète des parties pertinentes du code (peu probable), je pourrais passer beaucoup plus que cette fraction du temps total à trouver ce qui ne va pas, puis à tester le correctif. Le correctif lui-même est souvent rapide, ne représentant souvent qu'une ou quelques lignes de code modifié.
un CVn

@ ThorbjørnRavnAndersen Hell oui, en particulier avec des projets Web comme le mentionne OP. Nous passons un bon moment avec les encodages de caractères cette semaine au travail ...
Izkata

5

Plus de planification

Il est inévitable que vous passiez une bonne partie du temps à déboguer, 10% est un objectif assez ambitieux. Bien que l'un des meilleurs moyens de réduire le temps consacré au débogage et au développement soit de passer plus de temps dans la phase de planification.

Cela peut aller des diagrammes au pseudo-code sur un bloc de planification. Quoi qu'il en soit, vous aurez plus de temps pour réfléchir à ce que vous prévoyez de faire plutôt que de faire ces erreurs pendant le développement.


1
+1 parce que c'est ce que je fais pour réduire mon temps de débogage. Lorsque je démarre un nouveau projet, j'écris tout ce que je vais faire dans les commentaires, puis je reviens et je remplace les commentaires par du code
CamelBlues

Je fais de même avec les commentaires, surtout pour ne pas oublier où je me suis arrêté. Mais j'aime dessiner des diagrammes de classe sur papier et leurs dépendances. Cela me donne un bon aperçu de ce que je pense à l'époque.
Bryan Harrington

5

Travaillez plus soigneusement

C'est l'équivalent logiciel de "mesurer deux fois une fois":

  • Ne codez pas si vous vous sentez distrait ou fatigué.
  • Passez suffisamment de temps à réfléchir au problème pour avoir une solution propre et élégante. Les solutions simples sont moins susceptibles d'avoir des problèmes.
  • Accordez toute votre attention à la tâche. Concentrer.
  • Lisez votre code rapidement après le codage pour essayer de rechercher les erreurs. Examen de l'auto-code.
  • N'attendez pas trop longtemps entre le codage et les tests. Une rétroaction immédiate est importante pour l'amélioration.
  • Évitez de faire des choses qui mènent généralement à des erreurs. Lisez les odeurs de code .
  • Choisissez les bons outils pour le travail.

Cela dit, rien ne va éliminer complètement les défauts. Vous devez accepter cela comme une réalité de la vie. Compte tenu de ce fait, prévoyez des défauts, par exemple test unitaire. Ne prenez pas non plus cela pour signifier "prendre pour toujours" (aka analyse-paralysie). Il s'agit de trouver l'équilibre.


4

D'autres réponses ont déjà couvert la plupart de ce que je veux dire, mais je veux quand même vous donner mon avis (brutalement honnête):

Fondamentalement, pour les logiciels non triviaux, attendez - vous à passer la grande majorité de votre temps à la maintenance et au débogage. Si vous travaillez sur un système logiciel de production mature et que vous passez moins de 80 à 90% de votre temps à la maintenance et au débogage, vous vous en sortez bien!

Maintenant, évidemment, la distinction entre «maintenance» et «débogage» est un peu subjective. Considérez-vous seulement que les "bogues" sont des problèmes avec le code qui sont trouvés après sa sortie et les utilisateurs se sont plaints d'eux? Ou est-ce que chaque petite chose va mal avec votre code une fois que vous avez ajouté quelque chose (trouvé dans vos propres phases de test de pré-version)? Dans un système logiciel non trivial (selon les modèles d'utilisation), l'un peut être beaucoup plus gros que l'autre. Mais en tout cas, c'est ce que nécessite la programmation de quelque chose de plus grand qu'un programme "Hello world" jouet - beaucoup de maintenance et de débogage. Certaines personnes disent même quelque chose comme " tout ce qui suit la première ligne de code devrait être le" mode de maintenance ",

TL; DR: Il me semble simplement que vous pourriez avoir une image légèrement irréaliste de la programmation de systèmes logiciels non triviaux. La grande majorité de l'effort porte sur le réglage fin, la maintenance, la refactorisation, la correction de bogues et, en général, sur des tâches qui relèveraient du "débogage" (maintenance) - au moins dans un sens très général - par opposition à la réalisation de nouveaux travaux totalement nouveaux, écrire un nouveau code.


2

Il est difficile de donner des techniques spécifiques sans détails spécifiques sur ce que vous faites et les technologies que vous utilisez. Mais même de très bons codeurs passent beaucoup de temps à tester et à déboguer.

Beaucoup d'écrire du bon code sans beaucoup de bugs est une expérience. Vous faites des erreurs, puis vous les corrigez, puis vous vous souvenez quelles étaient les erreurs et ce que vous aviez à faire à la place pour les faire correctement, et vous ne faites pas la même erreur la prochaine fois. Et si vous n'êtes pas encore au collège et que vous commencez déjà à réfléchir sérieusement aux moyens de faire moins d'erreurs, je dirais que vous êtes définitivement en avance sur le match.


1
Cela m'étonne les gens que je vois qui n'apprennent pas de leurs erreurs (ou qui se donnent la peine d'essayer de se souvenir de ce qu'ils ont appris). Et juste après que quelque chose leur ait explosé au visage, ils se retournent et font exactement la même chose dans le prochain projet.
HLGEM

2

L'INTÉGRATION CONTINUE (IC) est la réponse.

Intégration continue = Système de gestion de la configuration (à savoir, Git, Mercurial, SVN, etc.) + Outil CI + Tests unitaires + Tests de fumée

Cette formule devrait vous inciter à en savoir plus sur l'intégration continue (CI). Voici quelques ressources dans ce domaine:


1

Vraiment, pour réduire le débogage, vous pouvez le charger en amont en planifiant plus en profondeur. Vous n'êtes pas encore allé à l'université? Je pense que vous verrez dans vos cours de niveau intermédiaire à tardif que vous couvrirez les détails du cycle de vie du développement logiciel qui pourraient très bien éclairer vos folies.

Comme j'essaie de l'expliquer à mes employeurs, la meilleure façon de réduire la maintenance du code et le support technique est de passer du temps à planifier votre code à l'avance.


1

Le développement piloté par les tests peut aider à réduire le temps de débogage en:

  • avoir beaucoup de petits tests ciblés signifie qu'en cas d'échec, il n'y a qu'une petite quantité de code qui pourrait avoir causé le problème.
  • travailler par petites étapes (en écrivant un test qui échoue et en le faisant réussir) signifie que vous pouvez vous concentrer sur une tâche à la fois. Autrement dit, faire passer le test actuel.
  • la refactorisation après avoir réussi le test vous encourage à garder votre code clair et compréhensible - le rendant plus facile à suivre en cas de problème.

Même si vous utilisez TDD, vous aurez toujours des moments où vous devrez utiliser le débogueur. Lorsque cela se produit, vous devez essayer d'écrire un test unitaire pour reproduire le scénario qui a provoqué la session de débogage. Cela garantira que si ce problème se reproduit, il sera rapidement détecté en cas d'échec du test, et le test servira de marqueur pour la zone de code à l'origine du problème, réduisant ainsi le besoin de débogage.


1

Le débogage est inévitable en programmation, mais la clé ici est, votre code est-il facile à déboguer ou non? Si vous avez besoin de passer des heures juste pour déboguer quelque chose de simple, alors il doit y avoir quelque chose de vraiment mauvais avec votre architecture de code.

Vous devez vous habituer à écrire du code propre et à supprimer les mauvaises habitudes comme copier-coller du code et écrire de longues méthodes, etc.

À côté, vous devez de temps en temps refactoriser votre code. Je vous suggère de lire le livre de Martin Fowler: Refactoring: Improving the Design of Existing Code


1

D'autres ont mentionné les tests et la révision du code. Celles-ci sont toutes deux extrêmement utiles mais ont une différence clé - quand est-il préférable de les exécuter. Il est préférable d'effectuer les tests très près de l'écriture initiale du code, de sorte que vous pouvez plus facilement vous rappeler pourquoi vous avez fait les choses d'une certaine manière et localiser plus rapidement le problème lorsqu'il échoue au test. La révision du code, en revanche, est mieux effectuée un peu plus tard. Vous voulez avoir à regarder le code sans un souvenir parfait afin de ne pas masquer les détails auxquels vous vous souvenez avoir pensé mais que vous n'avez pas insérés. Vous voulez réaliser des endroits où votre code n'est pas clair. Vous voulez le petit effort supplémentaire d'avoir à comprendre ce que fait le code. Vous voulez être en mesure d'appliquer toutes les nouvelles connaissances que vous avez acquises sur le problème ou les interactions avec d'autres codes ou de nouvelles techniques. Fondamentalement,

Cependant, tout cela est encore tangent à votre question. Afin de passer moins de temps à déboguer, vous devez comprendre pourquoi vous avez dû déboguer en premier lieu. Une mauvaise compréhension du problème, une connaissance imparfaite de vos outils et technologies et le simple fait de rencontrer "les données réelles ne correspondent pas aux données d'exemple" les types de problèmes vont tous se manifester de différentes manières et nécessiteront différentes techniques et types de pratique pour éviter A l'avenir.

Le dernier point que je ferai est l'expérience. Il n'y a pas de moyen facile d'obtenir cela, il suffit de mettre du temps. Au fur et à mesure que vous acquérez de l'expérience, vous passerez moins de temps à déboguer parce que vous écrirez un meilleur code pour commencer, noterez les problèmes plus tôt et développerez une meilleure intuition pour ce qui pourrait être la source d'un problème. Continuez et vous progresserez régulièrement au cours de votre carrière.


0

Excellentes réponses ci-dessus mais personne directement mentionné (bien que la plupart y aient fait allusion):

LIRE LIRE LIRE LIRE LIRE et à nauseam ...

Plus vous en savez, moins vous ne savez pas. Un peu cliché, mais toujours la vérité de base.

Une fois que vous avez suivi les conseils ci-dessus et documenté analytiquement les bogues, essayez de les classer, puis lisez la documentation pertinente.

Était-ce un problème de décision de conception? Renseignez-vous sur les modèles de conception.

S'agit-il d'un manque de connaissance du cadre ou du langage? Bone up on that!

etc

Un développeur (en direct) ne peut jamais échapper à deux choses: le changement (la seule constante en informatique) et RTFMing ...


0

Tests unitaires et assertions

Dans la mesure du possible, divisez votre code en petits morceaux qui peuvent être testés isolément. Ce n'est pas toujours pratique, cependant. Certains éléments de fonctionnalité dépendent d'entrées extrêmement compliquées. Certains font quelque chose qui ne peut pas être facilement vérifié de manière automatisée, comme dessiner des choses à l'écran. Parfois, le non-déterminisme est impliqué, etc.

Lorsque vous ne pouvez pas écrire de bons tests unitaires, la meilleure chose à faire est d'affirmer. Alors que les tests unitaires vérifient si vous obtenez la bonne réponse sur une entrée prédéterminée, les affirmations vérifient la validité des étapes intermédiaires sur les entrées du monde réel. Si votre code contient des bogues, il échouera rapidement, près de la racine du problème et avec un message d'erreur clair, plutôt que loin du problème avec un message d'erreur ambigu. En outre, affirme les hypothèses du document et rend votre code plus lisible.


0

Lorsque vous démarrez un projet, combien d'approches alternatives identifiez-vous?

Avez-vous de deux à quatre approches différentes, avec des avantages et des inconvénients pour chacune? Faites-vous ensuite une sélection raisonnée parmi eux?

Alors, le plus important, pensez-vous que la simplicité est très importante?

La raison pour laquelle je pose la question est, selon mon expérience, le volume de code, et donc le nombre de bugs (sans parler des performances), peut varier de plus d'un ordre de grandeur entre une approche de conception et une autre. Ce que je vois des gens très expérimentés, c'est faire des travaux avec pas plus de code que nécessaire.

Ils sont pleinement compétents et conscients de tous les algorithmes de structure de données, des fonctionnalités des langages orientés objet, etc., mais leur code semble ne pas l'être , car ils utilisent ces choses avec parcimonie , ou pas du tout, si le problème persiste. pas besoin d'eux.


0

Chaque fois que vous corrigez un bogue, vous voulez éviter de refaire la même erreur. Pour ce faire, vous pouvez effectuer les opérations suivantes:

  • Notez-le dans un journal d'enregistrement des défauts , qui comprend:

    • type de défaut
    • phase dans laquelle le défaut a été injecté
    • phase dans laquelle il a été retiré
    • temps fixe
    • une description du problème et une solution
  • Adoptez un guide de style pour normaliser le style de code que vous écrivez

  • Intégrez des règles de codage sécurisées à votre processus de révision de code

  • Visualisez le flux de contrôle et les données

Les références

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.