J'essaie actuellement d'améliorer mon utilisation des exceptions et j'ai trouvé la distinction importante entre les exceptions qui signifient des erreurs de programmation (par exemple, quelqu'un a passé null comme argument ou appelé une méthode sur un objet après sa suppression) et celles qui signifient un échec dans le opération qui n'est pas la faute de l'appelant (par exemple une exception d'E / S).
Comment ces deux types d'exceptions devraient-ils être traités différemment? Pensez-vous que les exceptions aux erreurs doivent être explicitement documentées, ou est-ce suffisant pour documenter les conditions préalables pertinentes? Et pouvez-vous laisser de côté la documentation d'une condition préalable ou d'une exception d'erreur si elle doit être évidente (par exemple, ObjectDisposedException
lors de l'appel d'une méthode sur un objet supprimé)
la source
Réponses:
Je pense que vous êtes sur la bonne voie. Ni lancer, attraper ni documenter toutes les exceptions potentiellement jetables n'a beaucoup de sens. Il y a des moments où la rigueur du produit nécessite un degré plus élevé d'emploi exceptionnel et de documentation (par exemple, certains aspects critiques de la sécurité d'un système).
La stratégie consistant à être plus défensif, à l'aide de concepts contractuels pour identifier les conditions préalables (et postconditions) sur les appelants en aval en particulier (par exemple, tout ce qui ressemble à un membre public ou protégé) sera souvent plus efficace et plus flexible. Cela s'applique non seulement à la mise en œuvre, mais à la documentation. Si les développeurs savent ce qui est attendu, ils sont plus susceptibles de suivre les règles et moins susceptibles d'être confus ou d'utiliser à mauvais escient le code que vous avez écrit.
Certaines des choses courantes qui devraient être documentées incluent le cas des paramètres nuls. Souvent, il y a une conséquence pour leur utilisation qui conduit le résultat à quelque chose qui ne serait normalement pas prévu, mais qui est autorisé et utilisé pour diverses raisons, parfois pour plus de flexibilité. En tant que consommateur d'un membre dont les paramètres autorisent des valeurs nulles ou autres valeurs non rationnelles spéciales (comme un temps négatif ou des quantités négatives), je m'attends à les voir identifiés et expliqués.
Pour les paramètres non nuls, en tant que consommateur d'un membre public ou protégé, je veux savoir que null n'est pas autorisé. Je veux savoir quelle est la plage de valeurs valide dans le contexte donné. Je veux connaître les conséquences de l'utilisation de valeurs qui sont en dehors de la plage normale, mais qui sont par ailleurs valides dans un contexte d'appel différent (par exemple, la valeur du type est généralement valide pour toute opération, mais pas ici - comme un paramètre booléen qui ne fonctionne pas ne vous attendez pas à false comme valeur valide.
En ce qui concerne la plate-forme ou les interfaces bien connues, je ne pense pas que vous deviez aller à l'extrême pour le documenter. Cependant, parce que vous avez la possibilité, en tant que développeur, de varier l'implémentation de n'importe quel guide de plateforme, notez comment il s'ensuit que ce guide peut être utile.
Spécifiques à IDisposable, les implémentations de cette interface offrent souvent une méthode alternative préférée au processus d'élimination explicite. Dans ces cas, mettez en surbrillance la méthode préférée et notez que l'élimination explicite n'est pas préférée.
la source
performReadCommand(ICommand cmd, int replySizeBytes)
- vous attendriez-vous à ce que null soit acceptable pour cmd, ou une valeur négative pour replySizeBytes? La documentation de l'OMI ne serait nécessaire que si ces valeurs étaient réellement autorisées, et vous devriez probablement déterminer si 0 est valide pour replySizeBytes.Voici mes propres pensées. Notez que je ne suis pas trop certain que c'est la meilleure façon de procéder, c'est pourquoi j'ai créé cette question en premier lieu.
Pour autant que je sache, il est peu logique qu'un appelant immédiat gère réellement les exceptions d'erreur de programmation, il devrait plutôt s'assurer que les conditions préalables sont remplies. Seuls les gestionnaires d'exceptions «externes» aux limites des tâches doivent les intercepter, afin qu'ils puissent continuer à faire fonctionner le système en cas d'échec d'une tâche.
Afin de garantir que le code client peut intercepter proprement les exceptions "échec" sans intercepter les exceptions d'erreur par erreur, je crée maintenant mes propres classes d'exception pour toutes les exceptions d'échec et je les documente dans les méthodes qui les déclenchent. Je leur ferais vérifier les exceptions en Java.
Jusqu'à récemment, j'essayais de documenter toutes les exceptions qu'une méthode pouvait générer, mais cela crée parfois une liste involontaire qui doit être documentée dans chaque méthode de la chaîne d'appels jusqu'à ce que vous puissiez montrer que l'erreur ne se produira pas. Au lieu de cela, je documente maintenant les conditions préalables dans les descriptions de résumé / paramètre et ne mentionne même pas ce qui se passe si elles ne sont pas remplies. L'idée est que les gens ne devraient pas essayer de capturer ces exceptions de toute façon, il n'est donc pas nécessaire de documenter leurs types.
Pour documenter les conditions préalables, énoncer l'évidence ne fait qu'encombrer inutilement - si passer null à une méthode n'a aucun sens évident, l'appelant doit s'attendre à une exception s'il passe null de toute façon, même si cela n'est pas documenté. Il en va de même pour le cas d'ObjectDisposedException - cette interface est si largement utilisée que quelqu'un appelant Dispose serait conscient de la responsabilité de s'assurer que personne ne continuera à utiliser l'objet.
la source
Une règle d'or raisonnable:
Vous voudrez peut-être avoir un gestionnaire d'exceptions non fatal de niveau supérieur pour intercepter tout ce qui ne peut pas être géré ci-dessous pour empêcher votre application de tomber, mais cela dépendra fortement de votre application particulière. Par exemple, les applications iOS préfèrent intercepter autant que possible; une application en ligne de commande peut être parfaitement OK si elle n'intercepte pratiquement aucune exception.
la source
Même Java ne "documente" pas toutes les exceptions. Malgré l'exigence que chaque
throw
n exception soit mentionnée dans unethrows
clause, n'importe quelle ligne de code peut lancer unRuntimeException
sans avoir besoin de le déclarer dans la signature de la méthode.la source
La façon standard de le faire est avec l'approche java. Les erreurs de programmation doivent être des exceptions non vérifiées et ne doivent pas être interceptées pour garantir une panne rapide. Les erreurs de contrat sont des exceptions vérifiées et doivent être traitées de manière appropriée par le client.
la source