Je travaille sur une bibliothèque conçue pour communiquer (sur la communication série RS232) avec des périphériques externes. Je pensais que la stratégie de traitement des erreurs et des exceptions semblait être une méthode standard appropriée de l'industrie de signaler des erreurs. P>
J'ai donc lu peu de directives sur les exceptions. Un stipule assez clairement que je devrais N'utilisez pas de codes d'erreur en raison de préoccupations que des exceptions pourraient affecter les performances négativement. P>
blockQuote>
Autre m'a dit de ne pas jeter Exception dans les cas normaux: P>
n'utilisez pas d'exceptions pour des erreurs normales ou attendues, ou pour un flux de contrôle normal. P>
blockQuote>
Je ne suis pas capable de dessiner une ligne claire entre les cas normaux / attendus et autres. Par exemple, dans ma bibliothèque, une opération peut échouer car: P>
Je peux penser à tout ce qui précède comme des problèmes attendus, car ils peuvent se produire très souvent dans la pratique (en infactuellement, de nombreux meurtres marketing m'appellent pour résoudre le problème ^ dans mon logiciel uniquement pour ne pas connaître le câble à leur ordinateur portable). Donc, peut-être que des exceptions ne devraient pas être jetées car sinon un programmeur d'application devra les attraper à de nombreux endroits (beaucoup de blocs de capture ne sont pas aussi agréables que je pense). P>
D'autre part, j'ai aussi tendance à penser que ce sont toutes des erreurs que je dois faire une manière en quelque sorte faire rapport au programmeur d'application, et une exception semble être la meilleure façon de le faire. Si je n'utilise pas d'exceptions, je devrai signaler ces problèmes en utilisant un code d'erreur ou une erreur enums. (Ugly, je sais). P>
Quelle approche pensez-vous que je devrais prendre? p>
9 Réponses :
Avec RS232, sauf si vous avez activé la main de main du matériel (et la plupart du temps, les gens ne le voient pas. Il n'y a aucun moyen pour vous de dire si un appareil est même connecté, autre que le fait que rien n'est envoyé au PC. P>
Je classerais 1 et 3 ensemble en tant que RS232TimeTorRor et 2 en tant que RS232AuthentiollingError, probablement. p>
En règle générale, un TimeOtorRor indique que le périphérique distant est enfermé ou n'est tout simplement pas connecté. Une erreur d'authentification est une sorte de ProtocolError, mais subtilement différente de la communication, mais le périphérique distant "vient de dire non" de créer une connexion avec le PC. P>
Je pense que les paramètres d'exception sont bien justifiés: vous ne vous attendriez jamais à une erreur de délai d'attente pendant les opérations normales, ni d'une erreur d'authentification. P>
La bibliothèque est destinée à être utilisée pour la communication avec de nombreux appareils (32 appareils à la fois) et il doit être aussi rapide que possible car il sera utilisé dans l'environnement de production. Pensez-vous que soulever l'exception trop souvent affectera la performance?
Si cela doit être aussi rapide au point où jeter des exceptions est un problème, vous devez écrire la bibliothèque en C. Si vous soulevez une exception de délai d'attente, vous ne revenez plus immédiatement au matériel et voyez une autre exception - Vous ignorez cet appareil jusqu'à ce que vous soyez explicitement dit de y retourner.
@Hemant: retournez la question. Si les erreurs se produisent tout le temps, pensez-vous que cela affectera la performance? Vous attendez-vous souvent des erreurs? La performance sera-t-elle touchée par l'utilisation d'une exception étant-elle comparée à celle de la performance impliquée dans la récupération de l'erreur au niveau suivant d'abstraction?
Vous développez une bibliothèque em>, un composant qui sera utilisé par d'autres applications. p>
Par conséquent, dans les cas prévus que vous mentionnez, j'utiliserais certainement des exceptions pour communiquer à l'application appelante que quelque chose ne va pas. Vous devez définir une exception personnalisée pour chacun de ces scénarios, puis documenter clairement quand ils peuvent se produire. P>
Ceci permet ensuite au code du client de l'application de prendre la décision de la meilleure façon de procéder. Seule la demande du client peut effectuer cette décision et des exceptions clairement documentées l'aident considérablement. P>
La meilleure chose à propos d'une exception personnalisée est que vous pouvez fournir plusieurs données de données significatives / utiles relatives au problème / exception. Ces données sont également bien encapsulées dans un seul objet. Comparez ceci aux codes d'erreur et retournez des valeurs. P>
La performance peut être un problème, mais uniquement lorsque l'exception est lancée dans une boucle serrée ou une autre situation d'activité élevée. Pour éviter cela, vous pouvez également appliquer un motif utilisé par le .NET Framework, nommément fournir des méthodes .... () (p. Ex. de toute façon, j'irais avec des exceptions personnalisées initialement, puis effectuez des tests de performance pour voir en réalité que certaines parties de la bibliothèque peuvent nécessiter une optimisation. P> Tryparse () code>) qui retourne booléen indiquant si une action a réussi ou échoué. p>
En ce qui concerne la performance, je n'ai vu qu'une seule fois lorsque la performance est entrée en place et qu'il y avait littéralement des centaines d'exceptions étant jetées et restonnées à l'arrière. Nous avions une opération qui pourrait être faite de deux manières, une fois parfois travaillée mais jeté une exception quand elle ne l'a pas fait, et l'inverse de la manière dont la voie est requise. Nous avons décidé que la voie de réflexion devrait être une baisse si nous ne pouvons pas le faire sans réflexion. Les exceptions ont été levées de manière aussi souvent que c'était beaucoup plus rapide d'utiliser toujours la méthode de réflexion (la différence était l'utilisateur qui attend 10 secondes contre des fractions de seconde).
si vous lancez ou non une exception est une conséquence du type de la fonction. p>
Je suppose que je dis que vous devriez pousser le problème de "Dois-je jeter une exception?" à "Quelles méthodes les gens appelleront ma bibliothèque?" Avec la mise en garde que les exceptions que vous lancez devraient être
J'utiliserais des exceptions, dans l'approche suivante (inspirée par le design-by-contrat) p>
De cette manière, si l'utilisateur de l'API peut coder sa logique clé à l'aide de Structures IF-else. P>
Si des situations inattendues surviennent (en raison de problèmes de synchronisation subtils, par exemple, une exception sera lancée: le développeur peut attraper cette exception et y faire face. MAIS NOTE: Cela ne doit pas nécessairement être à l'endroit où la méthode a été invoquée: elle peut être plus haute / plus tôt dans la pile d'appels, à un endroit central où toutes les exceptions étranges sont gérées p>
J'ai fait des travaux sur l'analyse automatisée du code de manutention des erreurs dans des programmes C multimobiliers de C. Celles-ci étaient basées sur des normes de codage nécessitant une inspection manuelle et une propagation des codes d'erreur. Il s'avère que les développeurs n'aiment pas écrire ce code, ils l'oublient et ils en font facilement des erreurs. En fait, nous avons trouvé 2 écarts des normes de codage (2 défauts, on pourrait dire) pour 1000 lignes de code C. P>
Résumé: (1) J'utiliserais des inspecteurs booléens (2) des exceptions peuvent être attrapées à des endroits plus élevés dans la pile d'appels; (3) s'appuyer sur des codes d'erreur est dangereux dans la pratique. P>
Conception par contrat pour la victoire!
Ne pas utiliser des exceptions pour la normale ou erreurs attendues, ou pour un flux normal de Contrôle. P>
Dans vos implémentations de méthode, évitez de provoquer une exception à dessein afin de modifier le flux d'exécution, de gérer une logique spéciale, des cas spéciaux ou des erreurs normales ou attendues. Par exemple, la manipulation des exceptions doit être supprimée dans la fonction suivante. (Il gère des erreurs normales ou attendues, mais comme la note dit que Convert.Tostring ne va pas vraiment échouer.) Il y a une performance mineure touchée en raison du temps nécessaire pour «configurer» la manipulation des exceptions dans la méthode. Ce n'est pas un coup important, mais si vous appelez cette fonction dans une boucle, cela peut devenir important. Si cette méthode est dans une bibliothèque, laissez toute exception à la bulle à l'utilisateur de la bibliothèque. (Les exceptions personnalisées sont différentes, voir la réponse de Ash.) P>
xxx pré> Voici une mise en œuvre "meilleure" de la méthode: p>
xxx pré> < / blockquote>
Ne pas utiliser les codes d'erreur à cause de préoccupations que les exceptions peuvent affecter performance négativement. p> blockQuote>
Évitez de concevoir tout comme une fonction qui retourne véritable / faux avec les paramètres "Out" pour éviter les préoccupations de performance "imaginées" avec l'utilisation d'exceptions. P>
Le choix ne doit pas être compris entre lancer une exception ou renvoyer un code d'erreur. Essayez de retourner un objet d'exception dans une condition exceptionnelle. Le succès de la performance ne consiste pas à créer une exception, mais à la jeter. L'appelant peut ensuite vérifier une valeur de retour «null». L'exception renvoyée pourrait être une fonction de fonction, ou l'un des paramètres "Out". P>
Des exceptions ont été conçues pour exactement cela - des circonstances exceptionnelles. J'essaie d'y penser comme ça - si vous supposez que tout ce que vous dépendez de fonctionne comme normal pour la majorité du temps, et la méthode x échoue, c'est une circonstance exceptionnelle, car elle ne se produit normalement pas et vous devriez définir des exceptions attraper la situation. p>
Donc, dans votre situation, vous supposez que l'appareil soit opérationnel. Par conséquent, les circonstances exceptionnelles dans ce cas sont l'appareil n'acceptant pas une connexion, il rejetant une connexion, il n'accepte pas de données que vous l'envoyez ou que vous ne recevez pas de données, il devrait être envoyé, etc. Si vos périphériques sont systématiquement éteints plusieurs fois par jour, puis Vous vous attendez à ce qu'ils soient désactivés, utilisez donc des codes de retour ou un "Bool Isdeviceon ();" méthode pour vérifier avant de vous connecter. P>
Si c'est quelque chose que vous STRUT> attendez-vous à ce que strong> se produise dans des circonstances normales, telles que l'interrogation d'un périphérique pour ses capacités, mais celui que vous souhaitez n'est pas disponible, puis utilisez les codes de retour ou une méthode de retour - par exemple "Bool Dudevicehavethiscapabilité ();" Ne pas attraper une exception quand ce n'est pas le cas. P>
Un autre exemple (pour les applications GUI) est la saisie de l'utilisateur. N'utilisez pas d'exceptions pour cela, car vous vous attendez à ce que un utilisateur entrait quelque chose de mal, nous ne sommes pas parfaits. P>
J'ai connu des problèmes de performances massives dues à utiliser des exceptions quand ils n'étaient pas des circonstances vraiment exceptionnelles. Un exemple était lorsque je traiterais un fichier de données 2 Go 2-3 fois par jour. Certaines lignes avaient des prix valides dans le format 0.00. Certains n'ont pas. J'ai utilisé une formatException pour attraper ceux qui ne l'ont pas. P>
Deux ans plus tard, lorsque j'ai eu la chance d'obtenir un analyseur de performance, cette ligne qui a attrapé l'exception était responsable de 80% du temps utilisé pour analyser le fichier. J'ai changé cela pour utiliser la méthode Tryparse () de l'INT et obtenu une augmentation de vitesse massive. P>
Pour vos exemples, j'utiliserais probablement: p>
J'ai fini par faire à peu près exactement comme vous l'avez suggéré. Merci.
Si une méthode ne parvient pas à effectuer sa fonction première de manière à ce qu'un appelant soit prêt à traiter, la fonction doit généralement indiquer une telle défaillance via une valeur de retour (ou, rarement, par écrit à une variable qui est adoptée par référence) . Si une fonction échoue de manière à ce qu'un appelant ne soit probablement pas prêt à traiter, il vaut mieux organiser une exception. Si certains appelants seraient prêts à faire face à une défaillance et que d'autres appelants ne veulent pas, il est préférable d'utiliser le motif Essayer / faire. Essentiellement, on fournit deux méthodes: dialogue et trydosomething. Dosomething se promet de réussir ou de lancer une exception. Trydosomething promet de ne pas jeter une exception à moins que quelque chose de vraiment inattendu se passe; Il indiquera les défaillances «attendues» par la valeur de retour. p>