web-dev-qa-db-fra.com

Comment éviter de provoquer des bogues dans le logiciel lorsque je corrige des bogues non liés?

Je suis stagiaire en logiciel et je reçois des bogues à corriger ainsi que des fonctionnalités à ajouter au logiciel. Lorsque j'ajoute des fonctionnalités, tout fonctionne bien. Mon problème est plus avec la correction des bugs. Je travaille sur une base de code extrêmement grande (étendue de millions de lignes) avec une mauvaise documentation (Il n'y a pas de commentaires, des tonnes de nombres magiques, un couplage étroit entre différentes classes, etc.). La seule documentation fournie est un document Word de 8 pages environ. Mais je sens toujours que je peux faire un meilleur travail avec la correction de bugs.

Je vais donner un exemple d'une situation que j'ai rencontrée et qui me semble avoir pu faire mieux dans:

  • On m'a attribué un bug à corriger concernant les calculs d'étendue pour un type d'objet spécifique (infographie)
  • J'ai trouvé le problème avec le bogue et pourquoi il a été causé. Parce que le programme a rempli une structure de données (tableau contigu) avec de la mémoire représentant un point cartésien 3D, il ne devrait apparemment pas avoir (Par conséquent, ce point serait utilisé dans les calculs d'étendue).
  • Le bug a en effet été causé par cela. TOUTEFOIS, un autre morceau de code (dans une classe différente) a utilisé l'arithmétique du pointeur pour obtenir ce point et l'utiliser pour une autre fonctionnalité, pour faire en sorte que la souris se rapproche de ce point lorsqu'une certaine fonctionnalité du logiciel était activée. Cependant, depuis que j'ai supprimé le point, j'ai corrigé le bogue qui m'avait été attribué et qui a causé un autre bogue dans le logiciel.

Que puis-je faire pour éviter que de telles choses se produisent? Comment puis-je m'améliorer? Y a-t-il un processus qui me manque?

49
Jason

Vous ne pouvez pas être seul responsable de ces types de défauts. Vous êtes humain et il est impossible de penser aux grands systèmes dans leur ensemble.

Pour éviter les "bogues de régression" - bogues créés involontairement lors de la modification du système, vous pouvez procéder comme suit:

  • Développer une suite complète de tests de régression automatisés. Espérons que votre système dispose d'une large suite de tests. Chaque fois qu'un bogue est découvert dans votre système, vous devez écrire un test automatisé qui reproduit le bogue. Corrigez ensuite le bogue. Si le système régresse un jour, votre "test de régression" se cassera et avertira le développeur.
  • Inspectez le code. Chaque fois que vous corrigez un bogue, il est judicieux d'inspecter les utilisations de la fonction que vous avez modifiée pour essayer d'identifier les changements de rupture que vous avez introduits
  • Écrivez plus de tests. Si, lors de l'inspection du code, vous identifiez du code qui n'est couvert par aucun test automatisé, c'est une bonne occasion d'en ajouter.
  • Familiarisez-vous avec le système et travaillez longtemps avec des logiciels. C'est en forgeant qu'on devient forgeron. Personne ne s'attend à ce qu'un développeur n'introduise pas de bogues dans un tout nouveau système ou lorsqu'il est stagiaire. Nous l'avons tous fait.
73
Samuel

Vous ne pouvez pas l'éliminer dans tout son sens. Voici quelques étapes pour réduire l'impact et réduire la probabilité:

  1. Ajoutez un test unitaire et un test de régression pour la fonctionnalité ou le bogue que vous modifiez ou corrigez. Si vous n'avez pas de cadre de test ou de faisceau configuré pour votre projet, configurez-le de manière à ce qu'il fasse partie de votre processus. Cela améliorera les choses au fil du temps.
  2. Améliorez la conception de votre code pour que le code soit couplé de manière plus lâche. Cela signifie suivre le SRP même si cela signifie sacrifier du SEC. En particulier, dans les systèmes OOP, votre code et vos données doivent être dans la même classe et les données doivent toujours être privées. Si cela n'a pas de sens, il y a un décalage d'impédance entre le domaine problématique et Il ne devrait pas être possible qu'un changement dans la structure des données dans une classe affecte le comportement d'une autre classe.
  3. Parlez à vos collègues de votre solution proposée. Cela pourrait prendre la forme de révisions de code, mais parfois cela n'attrapera pas les régressions. Les révisions de code ne sont généralement pas destinées à détecter les bogues. En corollaire, assurez-vous que le reste de l'équipe est au courant des changements que vous apportez et donnez-leur le temps de vous donner des informations sur les autres parties du système qui pourraient s'appuyer sur le code. Faites-le même si vous êtes la personne la plus âgée de l'équipe.

J'espère que cela t'aides.

10
RibaldEddie

Il y a beaucoup de bonnes suggestions dans d'autres réponses. J'ajouterais à cela: votre organisation a probablement un problème au niveau de la gestion.

  • La direction peut accorder la priorité au travail sur les nouvelles fonctionnalités plutôt qu'au règlement de la dette. Le bogue que vous avez mentionné prouve que les mauvaises pratiques passées rendent plus coûteux le développement de logiciels sans bogue aujourd'hui. Collectez des points de données comme ceux-ci pour informer la direction qu'il y a un problème permanent causé par la dette non traitée et qu'il serait sage de planifier un "jalon de qualité" où aucune nouvelle fonctionnalité n'est ajoutée, mais la dette existante est réduite.

  • La direction ignore probablement l'ampleur du problème. Les outils d'analyse statique qui trouvent de vrais bogues sont chers, mais ils sont beaucoup moins chers que les échecs sur le marché, car vous avez livré un logiciel qui perd des données utilisateur. Un bon analyseur statique vous dira que vous avez des dizaines de milliers de bogues non adressés, où ils se trouvent et comment les corriger. Cela vous permet de comprendre la taille du problème et la vitesse à laquelle vous l'atténuez.

9
Eric Lippert

En matière de réforme des choses, par opposition à leur déformation, il y a un principe clair et simple; un principe que l'on appellera probablement un paradoxe. Il existe dans un tel cas une certaine institution ou loi; disons, par souci de simplicité, une clôture ou un portail érigé en travers d'une route. Le type de réformateur le plus moderne s’adresse à lui gaiement et dit: "Je ne vois pas l’utilisation de cela; effaçons-le. "A quoi le réformateur le plus intelligent ferait bien de répondre:" Si vous ne voyez pas son utilisation, je ne vous laisserai certainement pas vous en débarrasser. Va-t'en et réfléchis. Ensuite, quand vous pourrez revenir et me dire que vous en voyez l'usage, je pourrai vous permettre de le détruire. "

- G.K. Chesterson

En plus de toutes les autres idées soulevées ici, une autre chose précieuse à faire est de découvrir comment et pourquoi un bug a été introduit. En supposant que votre équipe utilise Git ou un système de contrôle de source similaire, des outils tels que git blame ou le bouton Blame de GitHub peut vous aider. Une fois que vous avez identifié la ou les mauvaises lignes de code à l'origine du bogue, utilisez vos outils de contrôle de code source pour savoir quand il a été ajouté, par qui et dans le cadre de ce changement plus large.

Chaque fois que je corrige un bogue, j'essaie d'écrire sur le traqueur de bogues de l'organisation un narrative de la façon dont je pense que le bogue a commencé à exister. Parfois, c'est une histoire stupide et légèrement embarrassante comme "Il semble que Bob ait commenté la ligne 96 à des fins de test, l'ait accidentellement commise dans le commit 5ab314c, et il a été fusionné parce que nous nous précipitions pour obtenir le Frobnicator déployé et que revoir les trucs correctement cette semaine. " Pourtant, apprendre que c'est bon, au moment où vous résolvez le bogue, car cela vous rassure qu'il n'y a probablement aucune bonne raison pour le code cassé de être tel qu'il est et vous permet de le réparer avec plus de confiance. Mais parfois, vous plongez dans le git blame, et vous constatez que la ligne de code "manifestement cassée" que vous étiez sur le point de modifier a été introduite dans un commit qui prétend corriger n autre bogue auquel vous n'aviez pas pensé, et soudain vous vous rendez compte que votre "correction" va faire des dégâts et que vous devez faire quelque chose de plus intelligent.

Bien sûr, comme de nombreuses autres réponses le notent ici, ce serait bien si le développeur précédent avait laissé un test qui échouerait si vous réintroduisiez naïvement un vieux bogue - une sorte d'avertissement automatisé indiquant que la clôture que vous êtes sur le point de démolir a un but que vous ne pouvez pas voir. Mais vous ne pouvez pas contrôler le nombre de tests écrits par les développeurs précédents de votre base de code, car c'est le passé; plonger dans l'historique du code est l'une des rares techniques à votre disposition au moment de corriger un bogue existant pour réduire votre risque de casser des choses.

5
Mark Amery

Je travaille également sur une application héritée fragile. Mon objectif numéro un pour tout changement est de "ne rien casser qui fonctionnait auparavant". (L'objectif numéro deux est que l'utilisateur doit être en mesure de terminer son travail, même si cela devient un peu maladroit ou si vous devez invoquer une solution de contournement, il ne peut à aucun moment être absolument bloqué.)

  1. Il y a un livre, Working Effectively with Legacy Code, de Michael Feathers. C'est assez utile, mais je vais vous avertir qu'il s'agit à 100% d'ajouter des tests automatisés. C'est techniquement toujours possible (et il explique comment le faire pour beaucoup de situations délicates) mais ce n'est pas toujours réalisable du point de vue commercial. Le livre est également utile car il contient de petites barres latérales amusantes sur la gravité des choses.
  2. Inspection manuelle fastidieuse de tout ce qui touche au point de changement. Si vous avez modifié deux fonctions, foo et bar, effectuez une recherche en texte intégral sur l'ensemble de votre base de code (vous avez tout vérifié, non?) Pour les mots foo et bar. (Remarque, vous voudrez devenir un utilisateur avancé d'un outil de recherche tel que grep.) Il est important de ne pas essayer de simplifier cette recherche ... ne vous contentez pas de rechercher dans les fichiers Java , car votre fonction peut être appelée en utilisant la réflexion de quelque chose qui a démarré dans un JavaScript frontal ... juste un exemple. Gardez un suivi arrière jusqu'à ce que vous ayez entièrement testé tout ce qui appelle votre changement.
  3. Inversez votre technique de recherche et essayez de trouver des points dans votre application en faisant la même chose sans appeler votre point de changement. Recherchez le code copié-collé ou la même chose-faite-à double sens et assurez-vous que vous avez changé tous les points qui devaient être modifiés. (Répétez ensuite l'étape précédente.)

Cela peut sembler horrible, mais ces applications héritées difficiles à maintenir ne sont généralement toujours disponibles et mises à jour que parce qu'elles font quelque chose d'important et que quelqu'un a vraiment besoin qu'elles fonctionnent. Essayez d'en tirer une satisfaction.

1
user3067860

"un autre morceau de code (dans une classe différente) a utilisé l'arithmétique du pointeur pour obtenir ce point et l'utiliser pour une autre fonctionnalité, pour faire en sorte que la souris se rapproche de ce point lorsqu'une certaine fonctionnalité du logiciel était activée."

Oui, vous avez reçu une base de code à maintenance élevée. Il semble que dans ce cas, plutôt qu'un couplage régulier entre des objets avec des interfaces évidentes, il y ait eu de la "magie", qui a bien sûr cessé de fonctionner dès qu'elle a été modifiée.

Il n'y a aucun tour de magie à cela. De nombreuses techniques de développement logiciel se concentrent sur la gestion de la complexité afin de permettre de repérer l'impact d'un changement - mais celles-ci n'ont pas été suivies ici. C'est la faute des développeurs précédents et des seniors qui ont supervisé le projet.

1
pjc50

Vous pouvez refactoriser le code pour masquer l'accès direct à ce membre spécifique et ajouter un accesseur. Cela cassera tout code qui repose sur un accès direct au membre, donc vous saurez chaque endroit qui l'utilise.

En prime, déplacez le membre et remplissez sa place précédente avec des ordures - cela cassera le code qui y accède via l'arithmétique du pointeur.

En tant que développeur, vous voulez que votre code se casse tôt, souvent. "Fonctionne à 99,99% ou le temps" est bien pire pour la correction de bugs que "ne fonctionne pas du tout". (bien sûr, pour le code de production, vous ne voulez pas de "casser tôt, casser souvent")

0
Calin Ceteras