Il y a une discussion en cours sur comp.lang.c ++. Modérée sur la question de savoir si les assertions, qui en C ++ n'existent que dans les versions de débogage par défaut, doivent être conservées ou non dans le code de production.
Évidemment, chaque projet est unique, donc ma question ici n'est pas tant de savoir si les affirmations doivent être conservées, mais dans quels cas c'est recommandable / pas une bonne idée.
Par assertion, je veux dire:
- Un contrôle d'exécution qui teste une condition qui, lorsqu'elle est fausse, révèle un bogue dans le logiciel.
- Un mécanisme par lequel le programme est arrêté (peut-être après un travail de nettoyage vraiment minime).
Je ne parle pas nécessairement de C ou C ++.
Ma propre opinion est que si vous êtes le programmeur, mais que vous ne possédez pas les données (ce qui est le cas avec la plupart des applications de bureau commerciales), vous devriez les garder, car une asssertion défaillante montre un bogue, et vous ne devriez pas y aller avec un bug, avec le risque de corrompre les données de l'utilisateur. Cela vous oblige à tester fortement avant de livrer, et rend les bogues plus visibles, donc plus faciles à repérer et à corriger.
Quelle est votre opinion / expérience?
À votre santé,
Carl
Voir la question associée ici
Réponses et mises à jour
Salut Graham,
Une assertion est une erreur pure et simple et doit donc être traitée comme telle. Puisqu'une erreur doit être gérée en mode version, vous n'avez pas vraiment besoin d'assertions.
C'est pourquoi je préfère le mot «bug» quand je parle d'assertions. Cela rend les choses beaucoup plus claires. Pour moi, le mot «erreur» est trop vague. Un fichier manquant est une erreur, pas un bogue, et le programme doit y remédier. Essayer de déréférencer un pointeur nul est un bogue, et le programme devrait reconnaître que quelque chose sent le mauvais fromage.
Par conséquent, vous devez tester le pointeur avec une assertion, mais la présence du fichier avec un code normal de gestion des erreurs.
Légèrement hors sujet, mais un point important dans la discussion.
En guise d'avertissement, si vos assertions pénètrent dans le débogueur lorsqu'elles échouent, pourquoi pas. Mais il y a de nombreuses raisons pour lesquelles un fichier ne pourrait pas exister qui sont complètement hors du contrôle de votre code: droits de lecture / écriture, disque plein, périphérique USB débranché, etc. Comme vous n'en avez pas le contrôle, je pense que les affirmations sont ce n'est pas la bonne façon de traiter cela.
Carl
Thomas,
Oui, j'ai Code Complete et je dois dire que je ne suis pas du tout d'accord avec ce conseil particulier.
Supposons que votre allocateur de mémoire personnalisé se trompe et remette à zéro un morceau de mémoire qui est encore utilisé par un autre objet. Il m'arrive de mettre à zéro un pointeur que cet objet déréférence régulièrement, et l'un des invariants est que ce pointeur n'est jamais nul, et vous avez quelques assertions pour vous assurer qu'il reste ainsi. Que faire si le pointeur est soudainement nul. Vous juste si () autour de lui, en espérant que cela fonctionne?
N'oubliez pas que nous parlons de code produit ici, il n'y a donc pas de rupture dans le débogueur et d'inspection de l'état local. C'est un vrai bug sur la machine de l'utilisateur.
Carl
Réponses:
Les assertions sont des commentaires qui ne deviennent pas obsolètes. Ils documentent quels états théoriques sont prévus et quels états ne devraient pas se produire. Si le code est modifié afin que les états soient autorisés à changer, le développeur est rapidement informé et doit mettre à jour l'assertion.
la source
Permettez-moi de citer le code complet de Steve McConnell. La section sur les assertions est 8.2.
Cependant, plus loin dans la même section, ce conseil est donné:
Je pense que tant que les performances ne sont pas un problème, laissez l'assertion, mais plutôt que d'afficher un message, faites-la écrire dans un fichier journal. Je pense que ce conseil est également dans Code Complete, mais je ne le trouve pas pour le moment.
la source
Laissez les assertions activées dans le code de production, sauf si vous avez mesuré que le programme s'exécute beaucoup plus rapidement avec elles désactivées.
http://c2.com/cgi/wiki?ShipWithAssertionsOn
la source
assert ref != null;
est différent deif (ref == null) throw new IllegalArgumentException();
Vous ne devriez pas utiliser le premier pour des conditions préalables qui pourraient être fausses. Vous devez utiliserassert
pour des choses qui ne peuvent pas être fausses. Exemple,int i = -1 * someNumber; i = i * i;
puis plus tard pour rappeler aux gens quei
c'est positif,assert i > 0;
Si vous envisagez même de laisser des affirmations en production, vous y pensez probablement mal. L'intérêt des affirmations est que vous pouvez les désactiver en production, car ils ne font pas partie de votre solution. Il s'agit d'un outil de développement, utilisé pour vérifier que vos hypothèses sont correctes. Mais au moment où vous entrez en production, vous devriez déjà avoir confiance en vos hypothèses.
Cela dit, il y a un cas où je vais activer les assertions en production: si nous rencontrons un bogue reproductible en production que nous avons du mal à reproduire dans un environnement de test, il peut être utile de reproduire le bogue avec les assertions activées en production, pour voir si elles fournissent des informations utiles.
Une question plus intéressante est la suivante: dans votre phase de test, quand désactivez-vous les assertions?
la source
Les assertions ne doivent jamais rester dans le code de production. Si une assertion particulière semble utile dans le code de production, elle ne doit pas être une assertion; il devrait être un contrôle d'erreur de temps d'exécution, à savoir quelque chose à code comme ceci:
if( condition != expected ) throw exception
.Le terme «assertion» en est venu à signifier «une vérification uniquement au moment du développement qui ne sera pas effectuée sur le terrain».
Si vous commencez à penser que des affirmations pourraient arriver sur le terrain, vous commencerez inévitablement à faire d'autres pensées dangereuses, comme vous demander si une affirmation donnée vaut vraiment la peine d'être faite. Il n'y a aucune affirmation qui ne vaille la peine d'être faite. Vous ne devriez jamais vous demander "devrais-je affirmer cela ou non?" Vous devriez seulement vous demander "Y a-t-il quelque chose que j'ai oublié d'affirmer?"
la source
À moins que le profilage montre que les assertions causent des problèmes de performances, je dis qu'elles devraient également rester dans la version de production.
Cependant, je pense que cela nécessite également que vous gériez les échecs d'assertion avec une certaine élégance. Par exemple, ils devraient aboutir à un type général de dialogue avec l'option de signaler (automatiquement) le problème aux développeurs, et pas seulement de quitter ou de planter le programme. En outre, vous devez faire attention à ne pas utiliser d'assertions pour des conditions que vous autorisez réellement, mais que vous n'aimez peut-être pas ou ne considérez pas comme indésirables. Ces conditions doivent être gérées par d'autres parties du code.
la source
Dans mon C ++, je définis REQUIRE (x) qui est comme assert (x) sauf qu'il lève une exception si l'assertion échoue dans une version de version.
Puisqu'une assertion échouée indique un bogue, elle doit être traitée sérieusement même dans une version Release. Lorsque les performances de mon code sont importantes, j'utiliserai souvent REQUIRE () pour le code de niveau supérieur et assert () pour le code de niveau inférieur qui doit s'exécuter rapidement. J'utilise également REQUIRE au lieu d'affirmer si la condition d'échec peut être causée par des données transmises à partir d'un code écrit par un tiers, ou par une corruption de fichier (de manière optimale, je concevoirais le code spécifiquement pour qu'il se comporte bien en cas de corruption de fichier, mais nous n’a pas toujours le temps de faire ça.)
Ils disent que vous ne devriez pas montrer ces messages d'affirmation aux utilisateurs finaux parce qu'ils ne les comprendront pas. Alors? Les utilisateurs finaux peuvent vous envoyer un e-mail avec une capture d'écran ou du texte du message d'erreur, ce qui vous aide à déboguer. Si l'utilisateur dit simplement "il s'est écrasé", vous avez moins de capacité à le réparer. Il serait préférable de vous envoyer automatiquement les messages d'échec d'assertion sur Internet, mais cela ne fonctionne que si l'utilisateur a accès à Internet et que vous pouvez obtenir sa permission.
la source
Si vous souhaitez les conserver, remplacez-les par une gestion des erreurs. Rien de pire qu'un programme en train de disparaître. Je ne vois rien de mal à traiter certaines erreurs comme des bogues graves, mais elles devraient être dirigées vers une section de votre programme qui est équipée pour les traiter en collectant des données, en les enregistrant et en informant l'utilisateur que votre application a eu une condition indésirable et sort.
la source
À condition qu'ils soient traités comme toute autre erreur, je ne vois pas de problème avec cela. Gardez à l'esprit que les assertions ratées en C, comme avec d'autres langages, vont simplement quitter le programme, et ce n'est généralement pas suffisant pour les systèmes de production.
Il y a quelques exceptions - PHP, par exemple, vous permet de créer un gestionnaire personnalisé pour les échecs d'assertion afin que vous puissiez afficher les erreurs personnalisées, effectuer une journalisation détaillée, etc. au lieu de simplement quitter.
la source
Notre logiciel de serveur de base de données contient à la fois des assertions de production et de débogage. Les assertions de débogage ne sont que cela - elles sont supprimées dans le code de production. Les assertions de production ne se produisent que si (a) une condition existe qui devrait ne jamais exister et (b) il n'est pas possible de récupérer de manière fiable de cette condition. Une assertion de production indique qu'un bogue dans le logiciel a été rencontré ou qu'une sorte de corruption de données s'est produite.
Puisqu'il s'agit d'un système de base de données et que nous stockons des données potentiellement critiques pour l'entreprise, nous faisons tout notre possible pour éviter les données corrompues. Si une condition existe peut nous amener à stocker des données incorrectes, nous affirmons immédiatement, annulons toutes les transactions et arrêtons le serveur.
Cela dit, nous essayons également d'éviter les assertions de production dans les routines critiques pour les performances.
la source
Je vois les assertions comme des tests unitaires en ligne. Utile pour un test rapide lors du développement, mais finalement ces assertions doivent être refactorisées pour être testées en externe dans des tests unitaires.
la source
Je trouve qu'il est préférable de gérer toutes les erreurs qui sont dans la portée et d'utiliser des assertions pour les hypothèses que nous affirmons sont vraies.
c'est-à-dire que si votre programme ouvre / lit / ferme un fichier, alors ne pas pouvoir ouvrir le fichier est dans la portée - c'est une possibilité réelle, qu'il serait négligent d'ignorer, en d'autres termes. Donc, cela devrait avoir un code de vérification des erreurs associé.
Cependant, disons que votre fopen () est documentée comme renvoyant toujours un handle de fichier valide et ouvert. Vous ouvrez le fichier et le transmettez à votre fonction readfile ().
Cette fonction readfile, dans ce contexte, et probablement selon ses spécifications de conception, peut à peu près supposer qu'elle va obtenir un fichier valide ptr. Il serait donc inutile d'ajouter du code de gestion des erreurs pour le cas négatif, dans un programme aussi simple. Cependant, il devrait au moins documenter l'hypothèse, d'une manière ou d'une autre - assurer d'une manière ou d'une autre - que c'est effectivement le cas, avant de continuer son exécution. Il ne doit pas VRAIMENT supposer que ce sera toujours valide, au cas où il est appelé de manière incorrecte, ou s'il est copié / collé dans un autre programme, par exemple.
Donc, readfile () {assert (fptr! = NULL); ..} est approprié dans ce cas, alors que la gestion complète des erreurs ne l'est pas (en ignorant le fait que la lecture réelle du fichier nécessiterait de toute façon un système de gestion des erreurs).
Et oui, ces affirmations devraient rester dans le code de production, à moins qu'il ne soit absolument nécessaire de les désactiver. Même dans ce cas, vous ne devriez probablement les désactiver que dans les sections critiques pour les performances.
la source
Supposons qu'un morceau de code soit en production et qu'il atteigne une assertion qui serait normalement déclenchée. L'assertion a trouvé un bug! Sauf que ce n'est pas le cas, car l'assertion est désactivée.
Qu'est-ce-qu'on fait maintenant? Soit le programme (1) plantera de manière non informative à un point plus éloigné de la source du problème, soit (2) fonctionnera joyeusement jusqu'à la fin, donnant probablement un résultat erroné.
Aucun des deux scénarios n'est invitant. Laisser les assertions actives même en production.
la source
J'utilise rarement des assertions pour autre chose que la vérification de type à la compilation. J'utiliserais une exception au lieu d'une assertion simplement parce que la plupart des langages sont conçus pour les gérer.
Je donne un exemple
contre
Comment l'application traiterait-elle l'assertion? Je préfère l'ancienne
try catch
méthode pour traiter les erreurs fatales.la source
La plupart du temps, lorsque j'utilise l'assertion en java (le mot-clé assert), j'ajoute automatiquement des codes de production après. Selon le cas, cela peut être un message de journalisation, une exception ... ou rien.
Selon moi, toutes vos affirmations sont essentielles dans la version de développement, pas dans la version de production. Certains d'entre eux doivent être conservés, d'autres doivent être jetés.
la source
Les ASSERTIONS ne sont pas des erreurs et ne doivent pas être traitées comme des erreurs. Lorsqu'une assertion est lancée, cela signifie qu'il y a un bogue dans votre code ou alternativement dans le code appelant votre code.
Il y a quelques points pour éviter d'activer les assertions dans le code de production: 1. Vous ne voulez pas que votre utilisateur final voie un message comme "ASSERTION failed MyPrivateClass.cpp line 147. L'utilisateur final n'est PAS votre ingénieur QA. 2. ASSERTION pourrait influencer la performance
Cependant, il y a une bonne raison de laisser des affirmations: ASSERTION peut influencer les performances et le timing, et malheureusement cela a parfois de l'importance (en particulier dans les systèmes embarqués).
J'ai tendance à voter pour laisser l'assertion activée dans le code de production, mais en m'assurant que ces impressions ne sont pas exposées à l'utilisateur final.
~ Yitzik
la source
Une assertion est une erreur pure et simple et doit donc être traitée comme telle.
Puisqu'une erreur doit être gérée en mode version, vous n'avez pas vraiment besoin d'assertions.
Le principal avantage que je vois pour les assertions est une rupture conditionnelle - elles sont beaucoup plus faciles à configurer que de parcourir les fenêtres de VC pour configurer quelque chose qui prend 1 ligne de code.
la source