Comment prévenir les bogues

Arrêtez d'écrire des bogues : mécanismes et outils d'adaptation pour prévenir les bogues.
Vous dites que votre code a un bogue lorsqu'il fait quelque chose que vous (ou vos utilisateurs finaux) ne voulez pas. La vérité c'est quevotre code fait toujours exactement ce que vous lui avez dit de faire . Votre code agit comme il le fait parce que vous avez écrit le code pour le faire, et cela inclut tous les bogues que votre code présente.
Ce n'est ni nouveau ni surprenant. Mais, pour citer Dirty Harry Callaghan, "Un homme doit connaître ses limites", et la première étape pour résoudre tout problème consiste à reconnaître le problème.
Puisque nous n'écrivons pas de code pour faire ce que nousne fais pas voulez, la définition d'un bogue est un code que vous avez écrit en pensant qu'il faisait une chose mais qui, en fait, fait… autre chose. Pour le dire autrement : un bogue est un code que vous avez écrit mais que vous n'avez pas « parfaitement compris toutes ses implications » (pour le dire poliment).
Ainsi, après avoir identifié le problème, la deuxième étape consiste à résoudre le problème en créant les mécanismes d'adaptation nécessaires : comment écrire du code que nous comprenons mieux ?
Vous avez déjà construit ces mécanismes d'adaptation : vous comprenez votre code la plupart du temps et, avec le temps, vous vous êtes amélioré (vous aviez l'habitude d'écrire beaucoup plus de bogues dans des situations beaucoup plus simples). Le but de cet article n'est donc pas de fournir une nouvelle technique car vous les avez (probablement) toutes. L'objectif est de vous rendre plus conscient de la façon dont vos mécanismes d'adaptation actuels contribuent à prévenir les bogues afin que vous puissiez mieux les utiliser.
Le pouvoir d'obtenir les bonnes spécifications
Commençons par le début : il existe une catégorie spéciale de bogue où tout fonctionne du point de vue des développeurs… mais l'utilisateur final n'est pas satisfait du résultat : unbogue de spécification . Les bogues de spécification se produisent dans deux scénarios : lorsque les spécifications peuvent être comprises de différentes manières et lorsque les spécifications sont contradictoires. Dans les deux cas, le développeur a la possibilité d'implémenter le "mauvais" choix (Développeur : "J'ai construit ce que vous avez dit" ; Utilisateur final : "Ce n'est pas ce que je voulais dire").
La solution ici est de s'assurer que l'équipe de développement et les utilisateurs finaux partagent une compréhension commune de ce que signifient les spécifications – que vos spécifications sontvalide . Faire en sorte que le développeur et l'utilisateur final examinent ensemble les spécifications est le meilleur outil dont vous disposez pour y parvenir (surtout si l'examen implique l'utilisation de prototypes, qui sont le moyen le plus puissant d'exprimer les spécifications d'une manière significative pour les développeurs et les utilisateurs finaux ).
Le pouvoir de la simplification
En termes de techniques, vous avez probablement adopté une version duprincipe de responsabilité unique (PRS). En termes de réduction de bugs, SRP dit que moins votre code en fait, plus il est probable que vous le compreniez : plus court et plus simple, c'est mieux.
Soyons plus précis. Vous comprenez mieux une méthode qui s'adapte à l'écran qu'une méthode où vous devez faire défiler vers le haut ou vers le bas pour tout voir (et, pour mémoire, passer à un écran plus grand ou à une police plus petiten'est pasLa bonne réponse).
Bien sûr, "méthodes plus courtes" signifie plus de méthodes donc, si vous suivez SRP, votre application aura plus de pièces mobiles. "Plus de pièces mobiles" créent la possibilité d'un nouveau type de bogue :bogues d'intégration , où les composants ne fonctionnent pas ensemble comme prévu. Bien que vous ayez déplacé le problème, vous ne l'avez pas complètement résolu (c'est ce qu'on appelle des mécanismes « d'adaptation » et non des mécanismes « de résolution » pour une raison).
Le couplage lâche de vos composants aide à résoudre les bogues d'intégration : lorsque vous examinez un composant, vous ne devriez pas avoir besoin de savoir quoi que ce soit sur un autre composant pour bien comprendre le composant que vous examinez (en fait, la seule chose que deux composants faiblement couplés doivent partager est un format de message). La définition d'un microservice est probablement quelque chose comme "une application SRP faiblement couplée".
Le pouvoir des motifs
Très peu de code que nous écrivons est purement passe-partout, mais nous voyons les mêmes types de problèmes surgir encore et encore, et c'est là que les modèles de conception peuvent être utiles. L'application de modèles de conception bien compris à votre code a quelques effets secondaires utiles pour vous aider à comprendre votre code.
Tout d'abord, si vous choisissez le mauvais modèle de conception, vous découvrirez que vous devez écrire beaucoup plus de code que prévu pour que le modèle fonctionne (vous avez choisi le modèle d'état, par exemple, lorsque le modèle de rôle servirait mieux le problème). L'un des signes que vous comprenez votre code est que le modèle de conception que vous appliquez facilite réellement la résolution du problème.
L'application de modèles met également en évidence ce qui est « spécial » dans votre problème actuel, un domaine dans lequel vous êtes plus susceptible de mal comprendre votre code et d'introduire un bogue.
Et, bien sûr, les meilleures pratiques et les commentaires perspicaces se sont développés autour de tous ces modèles, qui vous aident tous à mieux comprendre votre application particulière du modèle.
Le pouvoir des noms
Vous pouvez réduire davantage l'impact d'avoir "plus de pièces mobiles" simplement en donnant à vos composants des noms qui décrivent ce que fait le composant. N'ayez pas peur ici d'attribuer des noms longs afin de décrire complètement un composant – tout bon IDE vous demandera le nom correct, donc vous ne taperez jamais le tout, de toute façon.
Suivre des modèles de conception bien connus et créer des composants qui remplissent des rôles dans ces modèles aident également à nommer : le rôle d'un composant dans un modèle doit déterminer le nom du composant. Si, par exemple, vous implémentez le modèle de méthode d'usine, appeler une méthode CustomerFactory peut être tout ce dont vous avez besoin pour comprendre cette méthode (en supposant que votre méthode CustomerFactory implémente SRP et ne fait que remplir son rôle, bien sûr).
Des noms plus longs et plus descriptifs contribuent également à rendre votre code lisible, ce qui facilite également la compréhension. La définition la plus simple du « code lisible » est qu'il s'agit d'un code qui « s'explique de lui-même ».
Le pouvoir de la lisibilité
Quand il s'agit d'expliquer les choses, vous pouvez apprendre des enseignants. Tout bon enseignant vous dira que vous ne comprenez pas vraiment quelque chose tant que vous ne pouvez pas l'expliquer avec succès à quelqu'un d'autre (même si ce « quelqu'un d'autre » n'est qu'uncanard en caoutchouc que vous conservez à cette fin). Plus important encore, l'inverse est également vrai : si votre professeur vous dit que quelque chose est difficile à comprendre, cela signifie probablement qu'il ne le comprend pas vraiment.
En d'autres termes, si vous ne pouvez pas expliquer votre code d'une manière que vous et les autres trouvez satisfaisante, alors vous ne le comprenez probablement pas.
Le signe avant-coureur de ce problème est que vous commencez à ajouter des commentaires pour expliquerQuelvotre code fait (bien que les commentaires qui expliquentPourquoi votre code existe valent toujours la peine). Des commentaires qui expliquentcommentde votre code sont une reconnaissance que, même si vous comprenez votre code en ce moment, vous êtes à peu près sûr que le prochain programmeur ne le comprendra pas… et, dans six mois, vous ne le comprendrez pas non plus.
Si les commentaires sont un signe que vous ne comprenez pas votre code, alors les avertissements du compilateur sont un signe que le compilateur ne le comprend pas non plus. Lorsque même le compilateur pense que votre code n'a pas de sens, il y a fort à parier que votre code n'aura de sens pour personne d'autre. Suivez ces avertissements, comprenez pourquoi le code que vous avez écrit déclenche l'avertissement et remplacez ce code par un meilleur code.
Le pouvoir des normes
L'écriture de code lisible vous fait probablement penser aux normes de codage. En termes de prévention des bogues, l'objectif ici est de choisir des normes et des conventions qui éviteront ou mettront en évidence les malentendus. L'indentation du code, par exemple, ne consiste pas à « rendre le code joli », mais à s'assurer que la disposition visuelle de votre code explique la structure de votre solution et rend votre code plus lisible.
En termes de conventions de codage (par exemple, nommage des variables), vous devez choisir des conventions qui mettent activement en évidence les erreurs qui ne seront signalées nulle part ailleurs. Les conventions de nommage qui signalent simplement les types de données (par exemple, intCounter) n'ajoutent aucune valeur car tout bon compilateur ou linter signalera déjà les problèmes de type de données pour vous (voir : note sur les avertissements du compilateur, ci-dessus).
Vous préférez plutôt une convention de codage qui nomme les variables en fonction des données qu'elles contiennent. Vous vous demanderiez automatiquement si vous saviez ce qui se passait dans une ligne de code qui charge une variable nommée currentCustomer à partir d'une variable appelée currentSalesOrder, quelles que soient les classes sous-jacentes.
L'adoption de ces pratiques a également pour effet secondaire de « standardiser le code » sur plusieurs applications. Cette standardisation a de la valeur car elle fait ressortir les variantes et les constructions inhabituelles. Puisque ce sont les endroits où vous êtes le plus susceptible de mal comprendre votre propre code, c'est une bonne chose.
Le pouvoir de l'examen
Comme vous pouvez apprendre des enseignants, vous pouvez apprendre des autres qui aident les gens à comprendre les choses. Tout bon rédacteur technique, par exemple, vous dira que le moyen le plus simple de repérer les problèmes dans quelque chose que vous avez écrit est de le mettre dans un tiroir pendant quelques jours, puis de le sortir et de le relire. Si, en relisant votre code, vous le trouvez illisible (c'est-à-dire qu'il ne s'explique pas tout seul), c'est bon signe que vous ne comprenez pas ce que fait votre code.
Encore mieux, comme tout rédacteur technique vous le dira, c'est de demander à quelqu'un d'autre de lire votre code. (C'est pourquoi les éditeurs existent. Salut, Mandy! Salut, Mihail!) Les rédacteurs techniques appellent ces critiques «yeux froids». Ces critiques contrecarrent une sorte de biais de confirmation lorsque vous lisez votre propre travail : vous ne voyez pas ce que dit le code, mais vous voyez plutôt ce que vouscensépour écrire.
La clé ici est lorsque vous rencontrez quelque chose qui n'a de sens ni pour vous ni pour un autre lecteur,ne fais pas essayez de comprendre ou de l'expliquer. Au lieu de cela, réécrivez votre code afin qu'il soit compréhensible dès que vous ou l'examinateur y arrivez.
Le pouvoir de ne pas écrire de code
Peut-être que votre outil le plus puissant pour éviter de créer des bogues est de ne pas écrire de code du tout. Au lieu de cela, utilisez des bibliothèques tierces populaires partout où vous le pouvez (comme les différentsPacks Telerik ). En réduisant la quantité de code que vous devez écrire, vous réduisez à la fois la quantité dont vous avez besoin pour comprendre et accéder àla compréhension des autres développeurs de ce code.
Le pouvoir des tests
Les tests sont votre dernière chance de prouver que vous comprenez parfaitement votre code, d'abord en testant votre codeen isolementpuis en l'intégrant à d'autres composants (à l'aide d'outils commeStudio d'essais).
Tester votre code isolément n'est possible qu'avec un bon outil de simulation (comme, par exemple,JustMock ). Et il sera plus facile de tester votre code si vous l'écrivez d'une manière qui prend en charge les tests (bien qu'un outil de simulation efficace puisse faire à peu près n'importe quoi "testable”).
Mais, d'une certaine manière, des pratiques de test efficaces sont une bonne idée même si vous n'exécutez jamais de test automatisé. Le code testable suit le principe de responsabilité unique et est faiblement associé à d'autres composants, qui sont tous deux des techniques qui permettent une meilleure compréhension de votre code. La participation des utilisateurs finaux à l'écriture des tests au niveau de l'intégration aide à éliminer les « erreurs » de compréhension dans les spécifications. Vous pourriez faire valoir que l'exécution des tests pour prouver que le code n'a pas de bogues n'est que la cerise sur le gâteau (mais vous devriez quand même exécuter les tests).
Un nombre de bogues nul (c'est-à-dire, où rien n'est trouvé dans les tests) indiquerait une parfaite compréhension de votre code. Ce n'est probablement pas réalisable – il y a une limite à la compréhension humaine, après tout. Mais c'est un objectif qui vaut la peine d'être poursuivi.
Source link