Je revoyais juste du code que j'avais écrit il y a quelque temps, et je peux voir que j'ai quelques méthodes privées qui lancent des exceptions de argument et / ou des exceptions d'argument s'il y a des problèmes avec les paramètres des méthodes.
Je suppose que ma justification est que cela aide à pérenniser l'application si quelqu'un essaie de "mal" utiliser la méthode à l'avenir. Cependant, étant donné qu'il s'agit d'une méthode privée et que les personnes susceptibles d'appeler cette méthode peuvent voir les commentaires et le code associés, il est tout simplement inutile de lancer cela. Cela ne fait certainement pas de mal de les avoir, bien que cela ajoute de l'encombrement.
Mon sentiment est que ces exceptions sont généralement plus utiles sur quelque chose comme une API qui va être exposée publiquement.
la source
Comme tout le reste, cela dépend ....
Si les méthodes publiques sont de simples wrappers qui appellent la méthode privée (dans le sens d'une méthode privée surchargée), il peut être judicieux de lever une exception dans la méthode privée au lieu d'enregistrer chaque méthode publique.
Généralement, s'il ne répond pas à la définition ci-dessus, je ne vérifierais généralement pas les arguments / levons une exception sur une méthode privée. Bien qu'il existe d'autres cas, je le fais généralement dans une méthode privée avant d'effectuer une opération coûteuse qui pourrait échouer à mi-chemin si les arguments n'étaient pas valides.
la source
Je me rends compte que même si la question n'a pas de balise de langue, il s'agit probablement implicitement de «langues du café». Mais juste pour être complet, je voudrais mentionner le consensus apparent quelque peu divergent dans le monde C ++.
Les programmeurs C ++ sont généralement intéressés par trois choses:
noexcept
?Dans le passé, j'ai abordé le premier problème en écrivant du code comme celui-ci
où
CHECK_ARGS
est#define
d à une constante de temps de compilation afin que le compilateur puisse éliminer complètement tout le code de vérification des arguments dans les builds optimisées. (Je ne dis pas que la compilation des vérifications est une bonne chose en général, mais je crois qu'un utilisateur devrait avoir la possibilité de les compiler.)J'aime toujours dans cette solution que l'argument vérifiant le code soit clairement visible, regroupé dans le
if
. Cependant, les deuxième et troisième problèmes ne sont pas résolus par cela. Par conséquent, je penche maintenant davantage vers l'utilisation d'uneassert
macro pour la vérification des arguments.Les normes de codage Boost sont d'accord avec ceci:
Il y a eu une conférence très intéressante donnée par John Lakos à CppCon'14 intitulée Programmation défensive bien faite ( partie 1 , partie 2 ). Dans la première partie de son intervention, il aborde la théorie des contrats et des comportements indéfinis. Dans la deuxième partie, il présente ce que je considère comme une très bonne proposition de vérification systématique des arguments. En substance, il propose des macros d'assertion qui permettent à l'utilisateur de sélectionner la part du budget (en termes d'utilisation du processeur) qu'il est prêt à donner à la bibliothèque pour la vérification des arguments et à la bibliothèque d'utiliser judicieusement ce budget. En outre, l'utilisateur peut également installer une fonction globale de gestion des erreurs qui sera appelée en cas de détection d'un contrat rompu.
En ce qui concerne l'aspect qu'une fonction est privée, je ne pense pas que cela signifie que nous ne devrions jamais la faire vérifier ses arguments. Nous pouvons faire davantage confiance à notre propre code pour ne pas violer le contrat d'une fonction interne, mais nous savons également que nous ne sommes pas parfaits non plus. La vérification des arguments dans les fonctions internes est tout aussi utile pour détecter nos propres bogues que pour les fonctions publiques pour détecter les bogues dans le code client.
la source
Considérez la structure suivante:
Logique interne: cette fonction suppose d'être appelée avec des paramètres corrects et utilise donc des assertions pour vérifier les préconditions, les postconditions et les invariants pour vérifier votre logique interne.
Wrapper Interface utilisateur: Cette fonction enveloppe la fonction interne et utilise InvalidArgumentExceptions pour gérer de mauvaises valeurs et de dire à l'utilisateur de corriger ses entrées:
Assert(x).hasLength(4);
,Assume(y).isAlphanumeric();
,Assert(z).isZipCode();
,Assume(mailAdress).matchesRegex(regex_MailAdress);
,Reject(x).ifEmpty();
, etc.Encapsuleur d'interface par lots: cette fonction encapsule la fonction interne et utilise la journalisation, les marquages de validité et les statistiques pour gérer les valeurs incorrectes sans interrompre une tâche de longue durée. Les marquages pourraient être utilisés ultérieurement par une personne vérifiant et nettoyant la base de données de résultats.
Encapsuleur d'interface de ligne de commande: cette fonction enveloppe la fonction interne et demande à nouveau la dernière entrée.
Vous devez utiliser les deux - assertions et exceptions - dans différentes méthodes pour différentes tâches. Vous devez séparer la logique interne de la vérification des paramètres. Comparez-le à la séparation du modèle, de la vue et du contrôleur.
la source
Il existe de meilleures façons d'éviter la vérification des références nulles: utilisez un contrat de code ou un cadre AOP pour effectuer la vérification pour vous. Google "contrat de code c #" ou "postsharp".
la source