IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Afficher des messages utilisateurs en levant des exceptions, bonne pratique?


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut Afficher des messages utilisateurs en levant des exceptions, bonne pratique?
    Bonjour à toute la communauté,

    Je suis tombé sur un code que je n'ai pas apprécié qui, pour afficher un message à l'utilisateur, levait des exceptions.
    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
                If Chose > 0 Then
                    If machin = 0 Then
                        If truc > -1 And bazar <> 1684 Then
                            ' ...
     
                        ElseIf machin > -1 Then
                            ' ...
                            If truc > 0 Then
                                '...
                            Else
                                Throw New ApplicationException("Il y a un problème pour le chargement de tous les calculs - comparaisonGRH ligne 198") ' Bon c'est la ligne 502 mais c'est pas grave...
                            End If
                        Else
                            Throw New ApplicationException("Vous n'appartenez à aucun groupe autorisé à accéder à ce programme.")
                        End If
                    Else
                        Throw New ApplicationException("Il y a un problème dans cAutoritésDeValidation.DetecterInfosLdap() - comparaisonGRH 204")
                    End If
                Else
                    Throw New ApplicationException("Vous ne disposez pas des autorités requises, veuillez vous adresser à votre administrateur.")
                End If
            Catch ex As Exception
                MessageBox.Show(ex.ToString, "MU0127VB - Comparaison GRH fichier Sepa et fichier log", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Application.Exit()
            End Try
    J'en ai parlé à un autre dev qui me dit faire pareil.
    Il s'en suit une recherche sur la bonne gestion des exceptions, je tombe sur un tas d'articles qui me laissent penser que ce n'est pas propre.
    Notamment celui-ci : http://kerrubin.wordpress.com/2014/0...es-exceptions/
    Les exceptions sont coûteuses en terme de performance.
    Donc les utiliser avec parcimonie peut être une bonne idée.
    Un processus de validation des arguments (Code Contracts ?) est une meilleure idée.
    et celui-ci : http://codebuild.blogspot.fr/2012/01...exception.html
    Don't manage business logic with exceptions. Use conditional statements instead. If a control can be done with if-else statement clearly, don't use exceptions because it reduces readability and performance (e.g. null control, divide by zero control).
    (il y en a plein d'autre...)

    Vous en pensez quoi?

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 199
    Par défaut
    c'est sûr que c'est aberrant, c'est pas propre, pas logique et couteux en performance

    mais c'est vrai aussi que c'est plus simple à coder, entre autre parce que le throw sort du bloc directement
    à la décharge de ceux qui travaillent comme ca, dans un petit projet ca ne coute rien en performance (lever une exception ca ne se voit pas, c'est plusieurs (dizaines ?) par seconde qui commence à ralentir l'appli)
    et ca n'empeche pas le programme de fonctionner

    sur un gros projet c'est donc fortement déconseillé


    après chacun choisit sa manière de coder (ou chaque entreprise) par exemple chez nous, on a pas le droit d'imbriquer plus de 2 if ^^
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre Expert Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Par défaut Hello
    Salut,

    Ayant fait pas mal de recherches ces derniers temps sur les exceptions, en vue d'établir une stratégie de la gestion des exceptions, je vais te donner quelques infos.

    Sur les performances j'ai également lu partout plein de choses qui stigmatisent les exceptions. La réalité n'est pas aussi noir que le dépeignent la plupart des tutoriels. En fait il y a surtout une erreur d'interprétation de la méthodologie "officiel" qui dit que c'est coûteux.

    Deux choses peuvent être coûteuses :

    1) Si il y a une vrai erreur, alors l'application va générer une first chance exception pour tenter de résoudre lui même le problème. Si il n'y arrive pas, alors il plante et créer l'exception. Ce n'est donc pas ton cas, puisque l'exception est générer par le code, il n'y a pas d'erreur d’exécution à l'origine. Quelque part, les tests qui sont faits dans ton code, suivent les recommandations : Les tests sont faits à la main avec des if... en opposition à une méthode ou tu ne tests rien, et tu attends que ça plante.

    2) Il n'y a qu'une chose qui consomme des ressources dans la génération des exceptions: c'est en réalité la création de son StackTrace. Je ne retrouve pas le lien, mais j'ai trouvé un article où quelqu'un test la création des exceptions avec ou sans StackTrace (car on peut se créer des exception sans StackTrace), et effectivement.... Sur la création de 1 000 000 d'exceptions d'affilées, on voit la différence entre les deux.

    -> Légende urbaine n°1: Mettre un Try Catch ne ralentie (pratiquement) en rien ton programme tant qu'il n'y a pas d'exception.
    -> Légende urbaine n°2 : Ce n'est pas tant la création de l'exception qui est coûteuse, mais par contre laisser le code planter sans test puis générer une exception, ça, ça fait perdre du temps pour rien, le temps du plantage.

    Maintenant, sur une exception que tu génère toi même (donc sans erreur d’exécution)... Le temps de la création d'une exception est ridicule (de mon point de vue). J'applique moi même une gestion des exceptions : J'encadre la plupart de mes procédures par un try Catch (je sens que je vais m'attirer des foudres), si une exception est levée, je l'enregistre en base (avec les infos qui s'accordent avec la situation), puis je remonte l'exception jusqu'à l'UI pour informer l'utilisateur du problème. J'applique cela sur un programme 5-tiers, client serveur avec couche WCF.... Je n'ai vue Aucune différence de temps d’exécution. Testé sur plein de postes clients.

    Dans ton cas, bien sûr, plutôt que de mettre des Throw, tu pourrais mettre tout le code dans une fonction qui retourne False dès qu'il y a un problème. Mais pour connaitre l'erreur il faudrait aussi renvoyer le texte correspondant (donc retourner le texte d'erreur ou passer le texte de l'erreur par référence). Mais franchement, tu n'y verrais aucune différence si ce n'est un peu de complication juste pour éviter les exceptions.

    En conclusion, je répondrai que moi ça me choque pas du tout d’utiliser les exceptions ainsi.

  4. #4
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Merci pour votre retour d'expérience.

    Mettre des MessageBox.Show à la place des Throw new ApplicationException je ne trouve pas ça beaucoup plus compliqué, surtout que la sortie des conditions ne donne sur rien donc le comportement est le même.
    Cela n’empêche effectivement pas l'application de fonctionner mais je parle plutôt de propreté du code et de bonne pratique.
    Si j'avais du faire un retour de fonction, cela serait différent, encore qu'en cas de retour, on peut facilement faire une enum que je trouve beaucoup plus propre et lisible pour tous les cas qui peuvent se produire normalement dans l'application.

    Effectivement pour les ralentissements, je suis tombé sur plein d'articles montrant la perte de performance avec des boucles sur 1.000.000 d'éléments, donc ce n'est pas un argument pour ce genre de cas.

    Pour ma part c'est principalement que je ne m'attends pas qu'un Catch affiche un message qui n'est pas une vrais exception, genre :
    Vous n'appartenez à aucun groupe autorisé à accéder à ce programme.
    Vous ne disposez pas des autorités requises, veuillez vous adresser à votre administrateur.
    Je pense qu'une exception doit rester quelque chose d'exceptionnel et que s'il y a moyen de ne pas en déclencher en ne compliquant pas le code, autant le faire.

    De plus dans le cas cité ci-dessus, cela empêche une bonne gestion des MessageBox, j'aurais mi MessageBoxIcon.Information au lieu de MessageBoxIcon.Error, bon ça c'est un premier point pas fort important mais qui compte quand même.
    Ensuite ça empêche un log des vrais exceptions, on va se retrouver très vite avec un log encrassé par des messages de fonctionnement normal de l'application.

    EDIT :
    Citation Envoyé par Pol63 Voir le message
    après chacun choisit sa manière de coder (ou chaque entreprise) par exemple chez nous, on a pas le droit d'imbriquer plus de 2 if ^^
    Nous nous n'avons pas de règle, c'est d'autant plus dur de reprendre le code d'un collègue

  5. #5
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 199
    Par défaut
    dans ton cas les exceptions sont juste utilisée pour gagner en facilité de codage

    normalement lever un exception sert à avertir l'appelant et qu'il s'arrête dans ce qu'il était en train de faire
    dans certains cas je m'en sers aussi pour aller directement dans le catch (qui fait un msgbox, mais générique) mais c'est quand je considère que ce n'est pas normal qu'une chose se produise, donc au moins quand on log les ex ca fait une trace d'un comportement anormal (enfin surtout non prévu ^^)
    et le fameux select case sur une liste prévue qui se termine toujours par un case else throw

    Citation Envoyé par Sankasssss Voir le message
    Nous nous n'avons pas de règle, c'est d'autant plus dur de reprendre le code d'un collègue
    ca doit être pour ca qu'on est règles communes de codage, pour pouvoir passer après un autre ^^



    @mactwist69, il me semblais que les exceptions de 1ère chancesétaient des juste des throw dans le framework interceptés par des catch dans le framework, donc des exceptions tout à fait standard mais dans une couche de bas niveau interceptées par des couches de plus haut niveau
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Hello,

    Je viens apporter mes 2 centimes à l'histoire. (pour info, je suis l'autre dev dont sankass parle dans son intro)

    Personnellement, voici ma manière de procéder :

    J'utilise l'évènement d'application UnhandeldException pour gérer "en bout de course" les exceptions qui ne le sont pas par l'application. Je récupère leur message, stacktrace et inner exception et je fourre tout dans une DB prévue à cette effet et j'affiche un message générique à l'utilisateur.

    Du coup, qu'importe si je lève des exceptions dans l'application qui ne sont pas de vrais cas de plantage et qui ne servent qu'à donner une info à l'utilisateur puissent qu'elles sont de toute façon pas logguée.
    A côté de ça, il y a les "vraies" erreurs qui, la plupart du temps dans mon cas, proviennent de sql server lorsque des infos qu'un utilisateur veut persister en DB provoque une violation de clef secondaire. Dans des cas comme ça, je connais le message qui sera renvoyé par sql server. Du moins le début ! Je peux ainsi afficher un message convenable à l'utilisateur pour lui indiquer le problème et continuer l'exécution sans problème. Pas besoin donc de logguer ces erreurs.

    Personnellement, je trouve l'utilisation des exceptions dans le code (du moins de la manière dont je procède) beaucoup plus clair que l'affichage d'un message suivi d'un Exit Sub/Function. J'ai réellement horreur de ce Exit (peut-être à tord).

    De plus dans le cas cité ci-dessus, cela empêche une bonne gestion des MessageBox, j'aurais mi MessageBoxIcon.Information au lieu de MessageBoxIcon.Error, bon ça c'est un premier point pas fort important mais qui compte quand même.
    Rien n'interdit de créer un type custom d'exception (ou d'utiliser des types existants en définissant qui sert à quoi) pour différencier les messages à afficher dans un message d'erreur de ceux à afficher dans un message d'avertissement. Mais ce que je fais personnellement, c'est que j'utilise la classe de base (ie. Exception) pour tout et, dans le bloc Catch, je fais un Select Case sur le message. Cela me permet d'afficher le type de message adéquat et dans le Else, c'est qu'il s'agit d'une exception que je n'ai pas créée moi-même et je la rejette donc. Elle finira par être gérée par l'évènement d'application et loggué dans la DB pour résolution ultérieure.
    @Sankass : c'est vrai que dans l'exemple que je t'ai donné, il n'y avait pas le Select Case... C'est car c'est juste un dirty project pour tester wcf ^^.

    Niveau performance, je n'ai jamais constaté de problème. Mais faut dire aussi que j'ai pas 2000 users derrière qui bosse avec l'application (le max en simultané pour une appli doit être aux alentour de 20 je pense).

    Sinon, d'un point de vue sémantique, pour moi, une exception ne doit pas forcément exceptionnel. Pour moi, une exception est une erreur survenue dans l'application. Si l'utilisateur doit encoder des champs nom, prénom et date de naissance pour la création d'un client et qu'il n'indique qu'un nom et prénom, il y a bien erreur et une exception mérite d'être levée selon moi. Juste que je le fais moi-même. Je pourrais laisser le framework se débrouiller l'exception serait probablement générée dans le constructeur du client mais il me semble qu'alors il y aurait dégradation de perf.

    Voilà, c'était mon point de vue.

  7. #7
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 199
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    Dans des cas comme ça, je connais le message qui sera renvoyé par sql server. Du moins le début ! Je peux ainsi afficher un message convenable à l'utilisateur pour lui indiquer le problème et continuer l'exécution sans problème. Pas besoin donc de logguer ces erreurs.
    aïe
    tester le message d'erreur retourné par sql server c'est un peu moche
    si tu passes sur un sql anglais ou qu'un jour le message change sur une nouvelle version d'sql server ton appli marche plus.
    il y a un numéro d'erreur qui lui par contre est fait pour être testé sur sqlexception

    Citation Envoyé par Kropernic Voir le message
    Personnellement, je trouve l'utilisation des exceptions dans le code (du moins de la manière dont je procède) beaucoup plus clair que l'affichage d'un message suivi d'un Exit Sub/Function. J'ai réellement horreur de ce Exit (peut-être à tord).
    Moi je suis fan du exit sub, j'expliciterais peut etre plus tard pourquoi si j'ai le temps, mais chacun ses gouts en effet
    après il y a aussi la méthode de la fonction qui retourne un message d'erreur ou une enum, ca reste simple à coder


    Citation Envoyé par Kropernic Voir le message
    Sinon, d'un point de vue sémantique, pour moi, une exception ne doit pas forcément exceptionnel. Pour moi, une exception est une erreur survenue dans l'application. Si l'utilisateur doit encoder des champs nom, prénom et date de naissance pour la création d'un client et qu'il n'indique qu'un nom et prénom, il y a bien erreur et une exception mérite d'être levée selon moi. Juste que je le fais moi-même. Je pourrais laisser le framework se débrouiller l'exception serait probablement générée dans le constructeur du client mais il me semble qu'alors il y aurait dégradation de perf.
    en développement on appelle ça de la validation, qui donne rarement lieu à des exceptions vu que c'est une boucle qui vérifie si les controles sont bien remplis et que les règles de remplissage sont respectées, en vue de prévenir l'utilisateur avant qu'il fasse quoi que ce soit (changement de couleur d'une zone ou autre)

    après il y a toujours la réponse "ça marche" ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre Expert Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Par défaut
    @Pol63 : De ce que j'ai compris, lorsqu'il y a une First Chance Exception, certes cela se passe à bas niveau, mais "The point" c'est que le debugger va décider de quoi faire avec : L'ignorer et continuer, essayer de réparer tout seul ou lever une exception (ce qui est la pire des solutions. Quoiqu'il en soit ça prends du temps, c'est pour ça que par exemple il est plus rapide de tester une variable pour savoir si on divise par 0 plutôt que de laisser faire une division par zero encadrer par un try-Catch.


    Cela n’empêche effectivement pas l'application de fonctionner mais je parle plutôt de propreté du code et de bonne pratique.
    -> C'est pas faux. La méthode ne freine pas tant que ça le programme... Après question propreté, tout est une question de méthodologie. Si partout dans le programme on utilise les Throw pour stopper les procédures quand il y a une erreur, alors se serait plus propre de continuer ainsi qui serait propre. De mon point de vue, il y a d'autres manières de faire cela.
    ->L'avantage tout de même, c'est que dans n'importe quel procédure, il n'y a pas à prévoir des retours d'erreurs à chaque fois... avec des enums, des paramètres ou autre. Ce système permet à la fois de couper l’exécution et de remonter une info. 2 en 1.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Je pense qu'une exception doit rester quelque chose d'exceptionnel
    -> Oui ! Mais là encore je pense que tu confonds les exceptions de types exceptionnels et prévu. Le fait de faire des try Catch partout et de rien tester, c'est le cas ou les erreurs ne sont pas prévu et enlève le caractère exceptionnel des exceptions en banalisant leurs interceptions. Mais dans ton cas, faire des tests et générer une exception, c'est une erreur prévu ET exceptionnel en théorie.


    j'aurais mi MessageBoxIcon.Information au lieu de MessageBoxIcon.Error
    -> Qu'est ce qui t'empêche de le faire ?


    ca doit être pour ca qu'on est règles communes de codage, pour pouvoir passer après un autre ^^
    -> Carrément !!! ^^

  9. #9
    Membre Expert Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Par défaut @Tous
    Bon je suis chaud (il faut dire, j'ai travaillé mon sujet). Les exceptions, il y a plein de manière de voir les choses... et il ne semble pas y avoir unanimité dans la manière de les utiliser. Au début je me fiais à l'avis générale qui veut qu'on les évites. Mais depuis que je les utilise correctement, ça a grandement améliorer la qualité de certains logiciels (notamment des erreurs qui jusque là restaient inconnu).

    Pour cela il faut distinguer deux choses :

    -> Utiliser la génération d'une exception lorsqu'une erreur logique survient
    -> La politique d'encadrement des exceptions avec les try-catch.

    Le sujet de départs étaient la pertinence d'utiliser un Throw NEw Exception pour une erreur détecter. Moi je trouve ça logique, je l'utilise, ça me permet de ne pas créer et gérer un système qui remonte une info décrivant une erreur.

    Par exemple une procédure de l'UI appelle n procédures qui appellent le WCF qui appel une procédure de la businness layer. Dans la BL, une erreur survient, une erreur testée donc. Sans le Throw new exception, il faut que chacune de ces procédures prévois un paramètres en référence, un string, pour remonter à l'UI l'info du problème... Pour TOUTES les procédures. (ou alors, tu mets un Message box "sur place"... Rien de mieux pour faire un programme sans dessus dessous).

    Bien sur ce système va de paire avec un système comme Kropernic. J'ai créer une exception personnalisée, genre PersoException. Son constructeur enregistre l'exception en base.
    Quand il y a une erreur prévu, j'envoi une PersoException avec le texte (elle est donc enregistrée en base directement à sa création). Dans mes try Catch, je fais deux catch :
    1) un catch PersoException qui fait juste Throw pour remonter à l'UI (on ne retraite pas)
    2) un catch Exception (donc erreur non prévu), alors je stocke le contenu dans une PersoException (donc s'enregistre en base) que je Throw, ainsi l'erreur est remontée jusqu'à l'UI sans être retraité.

    C'est une manière de faire. C'est mieux qui ce qu'il y avait avant... Parfois des try catch vide, des messages box dans toutes les couches, ou des procédures qui continue malgré une erreur... Là, tous les message box sont dans l'UI ET chaque exception est enregistrée "sur place" où l'erreur survient puis remonté ce qui stoppe le traitement.

Discussions similaires

  1. Réponses: 0
    Dernier message: 15/07/2014, 21h31
  2. Réponses: 8
    Dernier message: 12/07/2012, 15h22
  3. Réponses: 2
    Dernier message: 21/08/2009, 13h41
  4. Modification des YES en Oui et des messages dans dlg
    Par netchip dans le forum Langage
    Réponses: 11
    Dernier message: 15/04/2006, 14h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo