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

  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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Points : 4 232
    Points
    4 232
    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 sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    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 émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    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.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Points : 4 232
    Points
    4 232
    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 sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    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
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    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.
    Kropernic

  7. #7
    Membre émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    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 !!! ^^
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    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

  9. #9
    Membre émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    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.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  10. #10
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    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
    J'avoue que ce serait probablement plus propre. Juste que j'ai pas encore vu où se trouvait ce numéro (mais j'ai pas bcp cherché non plus)
    Citation Envoyé par Pol63 Voir le message

    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
    Je veux des arguments en faveur du exit sub. Cela me fera p-e changé d'avis.
    Citation Envoyé par Pol63 Voir le message
    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)
    En théorie, 100% d'accord avec toi. Sauf que en pratique, avec des users ayant la capacité de réflexion d'une éponge, ça marche moins bien.
    True story : Dans une application, ils devaient encoder une durée en heures et minutes et, pour pas qu'ils se fachent chier avec le ":" et utiliser juste le numpad, ils pouvaient encoder par exemple "0800" pour mettre 08:00 dans la cellule du datagridview. Je testais la valeur encodée dans l'event cellvalidating et mettait la ligne en error en cas de problème (backcolor en rouge + boule rouge avec "!" au début de la ligne avec une hint qui indique le problème). Avec bien sûr, le tout décrit dans la manuel. Bin pas moyen hein... Il a fallu que j'affiche un message signalant ce qui n'allait pas...
    Citation Envoyé par Pol63 Voir le message
    après il y a toujours la réponse "ça marche" ...
    Dans ces cas-là, je ne leur dis rien pour ne pas les perturber. C'est sensible une éponge !
    Kropernic

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    J'avoue que ce serait probablement plus propre. Juste que j'ai pas encore vu où se trouvait ce numéro (mais j'ai pas bcp chercher non plus)
    il y a plein de classes d'exceptions qui héritent de la classe exception
    chaque classe rajoute donc ses propriétés
    la classe sqlexception a errornumber, errorline et quelques autres trucs
    après 2 méthodes pour la lire
    dans les exemples msdn on voit souvent un catch multiple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    catch ex as sqlexception
     ...
    catch ex as exception
     ...
    end catch
    c'est l'équivalent d'un select case typeof
    si c'est une sqlexception ca rentre dans le 1er catch, sinon ca teste le suivant etc...

    sinon faire un seul catch et tester le type
    comme dans ton cas par exemple ca serait un if typeof à faire dans ta méthode globale

    sur ioexception il y a le numéro d'erreur de windows (genre 5 = erreur de droits)

    et sinon moi dans l'enregistrement du log d'erreur, j'enregistre aussi toutes les propriétés de l'exception, il y a des choses intéressantes parfois
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  12. #12
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    des choses intéressantes sur les SqlException
    Sorry pour le petit hors sujet mais bon, tant qu'à faire...

    Si la procédure stockée utilisée doit faire des insertions dans plusieurs tables, j'imagine qu'avec le code d'erreur, on saura le type de contrainte qui n'est pas validé mais pas la table de la contrainte en cause... Du coup, pour informer l'utilisateur, ça devient plus difficile...

    Je vais creuser le sujet et ouvrir une discussion si nécessaire.
    Kropernic

  13. #13
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Mes deux sous à ce sujet :

    L'exception est parfaite pour gérer les cas de figure exceptionnels. Cela masque certes le flux de contrôle pour ces cas exceptionnels mais en contrepartie la lisibilité du flux de contrôle ordinaire en est grandement simplifiée. N'importe qui ayant eu à faire remonter des codes d'erreurs sur douze niveaux pourra témoigner du bénéfice obtenu.

    C'est une bonne pratique et ça n'a absolument rien de sale ou de bâclé ! Quant au coût sur les performances, il est de quelques microsecondes ce qui est rarement problématique dans les cas véritablement exceptionnels (ce qui est le cas de toute erreur nécessitant une action utilisateur).


    En revanche j'ai beaucoup plus de mal avec l'idée de gérer l'UI via des exceptions. Ça me semble complètement tordu, ne serait-ce que parce que la bonne réponse est souvent plus complexe qu'une boîte de dialogue. Par ailleurs soit on est dans le code UI et alors c'est à lui d'afficher directement l'erreur comme il convient, soit on est dans une couche métier et alors un message d'erreur utilisateur n'y a pas sa place.

    La bonne solution dans ce dernier cas est soit de passer au code métier une interface (disons "IErrorHandler") avec les méthodes adaptées (quitte à lever après une exception non-utilisateur pour remonter dans le code), soit de lever une exception générale sans message particulier et ce sera au code UI de la traiter et de décider quoi en faire et quel message éventuellement afficher.

  14. #14
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    En revanche j'ai beaucoup plus de mal avec l'idée de gérer l'UI via des exceptions. Ça me semble complètement tordu, ne serait-ce que parce que la bonne réponse est souvent plus complexe qu'une boîte de dialogue. Par ailleurs soit on est dans le code UI et alors c'est à lui d'afficher directement l'erreur comme il convient, soit on est dans une couche métier et alors un message d'erreur utilisateur n'y a pas sa place.

    La bonne solution dans ce dernier cas est soit de passer au code métier une interface (disons "IErrorHandler") avec les méthodes adaptées (quitte à lever après une exception non-utilisateur pour remonter dans le code), soit de lever une exception générale sans message particulier et ce sera au code UI de la traiter et de décider quoi en faire et quel message éventuellement afficher.
    Je reprends mon exemple de création de client. Pour créer un client, les informations obligatoires sont le nom, le prénom et la date de naissance.

    Si un utilisateur n'indique de le nom et la date de naissance, que ferais-tu exactement ?

    Personnellement, je fais directement le test dans la couche GUI pour vérifier que ces 3 données sont encodées (il y a bien sûr également toute la panoplie de tests réglementaire dans la couche métier qui va créé l'objet). S'il en manque une, je lève une exception pour afficher son message dans le bloc Catch. Cela présent l'avantage d'arrêter le traitement du code de validation directement sans continuer à tester les autres champs si cela se produit sur le premier.

    En terme de lisibilité, je trouve cela également plus clair. Il ne faut pas oublier que nous codons pour ceux qui passerons derrière nous et je trouve qu'avec une exception, on voit directement là où il y a quelque chose qui cloche. Avec un Messagebox.Show, il faut encore lire le message pour ce rendre qu'il s'agit d'un problème. Cela pourrait tout aussi bien être un message de confirmation par exemple.
    Kropernic

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    je pense qu'on a fait le tour sur ce qu'il y avait à dire sur les exceptions, donc un peu de hors sujet ne fait pas de mal ^^


    concernant les exit sub, imaginons une sub qui fait des tests pour savoir quelle méthode elle doit appeler

    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
    26
        Public Sub machin()
            If Me.Visible And Me.Enabled And Me.Left > 70 Then
                If var1 > 50 Then
                    If var2 < 30 Then
                        If var3 IsNot Nothing Then
                            sub2()
                        Else
                            sub3()
                        End If
     
                    Else
     
                        If var2 < 90 Then
                            If var3 IsNot Nothing Then
                                sub4()
                            Else
                                sub5()
                            End If
                        End If
                    End If
     
                Else
                    sub6()
                End If
            End If
        End Sub
    pour être sur de ne passer que dans une branche et donc de n'appeler qu'une sub il faut des tas d'imbrication

    le code précédent avec des exit sub ca donne ca :

    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
    26
    27
    28
       Public Sub machin2()
            If Me.Visible = False Then Exit Sub
            If Me.Enabled = False Then Exit Sub ' on peut même se permettre de ne faire qu'un test par ligne pour plus de lisibilité
            If Me.Left <= 70 Then Exit Sub
            If var1 <= 50 Then
                sub6()
                Exit Sub
            End If
     
            If var2 >= 90 Then Exit Sub
     
            If var2 < 30 Then
                If var3 IsNot Nothing Then
                    sub2()
                    Exit Sub
                End If
                sub3()
                Exit Sub
            End If
     
     
            If var3 IsNot Nothing Then
                sub4()
                Exit Sub
            End If
     
            sub5()
        End Sub
    ca fait à peu près autant de ligne de code, le résultat est aussi le même (si je me suis pas trompé ^^), par contre c'est beaucoup plus lisible car il y a moins d'imbrications
    en cas de debug, dans le 1er cas tu est obligé de lire tout le code pour comprendre où le code est passé, chercher où se terminent les end if etc...
    dans le 2ème cas tu lis jusqu'à trouver l'exit sub qui te correspond

    tu peux faire le test, si je te dis que visible valait true, enabled true, left 90, var1 127, var2 95, var3 nothing
    dans le 1er cas il faut chercher si le else correspondond bien au if qu'on pense
    dans le 2ème on lit bloc par bloc c'est simple et pas de risque de mal lire
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  16. #16
    Membre émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    En revanche j'ai beaucoup plus de mal avec l'idée de gérer l'UI via des exceptions. Ça me semble complètement tordu, ne serait-ce que parce que la bonne réponse est souvent plus complexe qu'une boîte de dialogue. Par ailleurs soit on est dans le code UI et alors c'est à lui d'afficher directement l'erreur comme il convient, soit on est dans une couche métier et alors un message d'erreur utilisateur n'y a pas sa place.

    La bonne solution dans ce dernier cas est soit de passer au code métier une interface (disons "IErrorHandler") avec les méthodes adaptées (quitte à lever après une exception non-utilisateur pour remonter dans le code), soit de lever une exception générale sans message particulier et ce sera au code UI de la traiter et de décider quoi en faire et quel message éventuellement afficher.
    -> Ce que je voulais dire par là, c'est que si un utilisateur depuis l'UI déclenche un événement (par exemple l'envoi d'un mail), l'UI monte jusqu'à la BL qui s'occupe de l'envoi. Grâce à un test, la BL se rends compte que le compte utilisé n'est pas accessible (ou autre chose).
    Donc on a une erreur bien spécifique. A ce moment, dans la BL, l'exception a bien été enregistré, puis je remonte l'exception jusqu'à l'UI. Par pour gérer l'exception, mais pour remonté jusqu'à l’événement de départ (envoi de mail), pour informer l'utilisateur que l'envoi est impossible... Si la cause de l'erreur est dans l'exception, alors on peut l'afficher à l'utilisateur.

    J'utilise donc un message personnalisé, soit au niveau de l'erreur si j'ai des détails, soit au niveau de l'UI si le message est générique : "Operation échoué".

    Le but étant, comme vous le dites, de n'avoir des messages utilisateurs QUE dans l'UI.

    Maintenant il est aussi fort possible que pour certain cas, il n'y ait pas besoin de remonté jusqu'à l'UI... Il y a certes du cas par cas.

    L'idée n'est pas tellement que l'UI est géré par des exceptions... Je me place plutôt dans une dimension événementielle. Un événement (UI) se déclenche, soit tout va bien il va au bout et remonte (et on informe que tout c'est bien passé). Soit a un certain stade du fil de l’événement (et on ne sait pas lequel, c'est la tout le principe), une erreur est remontée avec une info, et l’événement intercepte ce message et informe l'utilisateur du problème. Dans les deux cas, il y a descente et remonté. C'est un événement.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  17. #17
    Membre émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    je pense qu'on a fait le tour sur ce qu'il y avait à dire sur les exceptions, donc un peu de hors sujet ne fait pas de mal ^^


    concernant les exit sub, imaginons une sub qui fait des tests pour savoir quelle méthode elle doit appeler

    ca fait à peu près autant de ligne de code, le résultat est aussi le même (si je me suis pas trompé ^^), par contre c'est beaucoup plus lisible car il y a moins d'imbrications
    en cas de debug, dans le 1er cas tu est obligé de lire tout le code pour comprendre où le code est passé, chercher où se terminent les end if etc...
    dans le 2ème cas tu lis jusqu'à trouver l'exit sub qui te correspond

    tu peux faire le test, si je te dis que visible valait true, enabled true, left 90, var1 127, var2 95, var3 nothing
    dans le 1er cas il faut chercher si le else correspondond bien au if qu'on pense
    dans le 2ème on lit bloc par bloc c'est simple et pas de risque de mal lire
    Lol, tout s'explique : Le Exit Sub prennent effectivement tout leurs sens Si et seulement si on est interdit de faire plus de 2 If imbriqués.

    Et... ça marche... mais personnellement, je ne trouve pas tellement plus lisible. Voir cela pourrait paraître compliqué si il y a beaucoup de conditions... En lisant la procédure, on ne se rends pas forcement compte de la logique des tests effectués. C'est une succession de condition sortante... Ce qui n'est pas tellement le but des If-Else.

    En plus ça ressemble finalement à une Fonction qui ne dit pas son nom, ou j'ose... à un Goto !

    Mais avec comme condition pas plus de 2 if imbriqués, je comprends qu'il faille trouvé une solution sans tout écrire avec des Fonctions.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  18. #18
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    exemple avec et sans exit sub
    C'est sûr que dans ce cas-là, je préfère de très loin l'écriture avec Exit Sub. Je n'ai cependant encore jamais dû écrire de telle procédure. Cependant, je suis de l'avis de Mac Twist quant à sa ressemblance avec le GoTo. C'est pour ça à la base que je ne l'aime pas.

    Sinon, pour revenir sur l'utilisation des exceptions, voici un exemple concret de ce que je fais par exemple (que je viens d'adapter en tenant compte de différentes remarques) :
    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
        Private Sub tsmiConnection_Click(sender As Object, e As EventArgs) Handles tsmiConnection.Click
            Using dlg As New DlgConnection
                If dlg.ShowDialog = Windows.Forms.DialogResult.OK Then
                    Try
                        If dlg.Nickname.ToLower = "channel" Then
                            Throw New CustomException("Désolé mais ce pseudo n'est pas valide.")
                        End If
     
                        Dim nics() As Net.NetworkInformation.NetworkInterface = Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces
     
                        Dim nic As Net.NetworkInformation.NetworkInterface = (From n As Net.NetworkInformation.NetworkInterface In nics
                                                                             Where n.OperationalStatus = Net.NetworkInformation.OperationalStatus.Up
                                                                             Select n).First
     
                        ChatConnection(dlg.Nickname, nic.GetPhysicalAddress().ToString)
                    Catch ex As CustomException
                        MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    Catch ex As Exception
                        Throw
                    End Try
                End If
            End Using
        End Sub
    CustomException demande juste une string dans le constructeur qu'il utilise comme message dans le constructeur de Exception.

    On a donc un message dans le cas d'une erreur de "validation". Si c'est une erreur non prévue, elle sera rattrapée par l'event d'application UnhandledException pour être stockée.
    Kropernic

  19. #19
    Membre émérite 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 : 39
    Localisation : France, Saône et Loire (Bourgogne)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Moi j'aime bien.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  20. #20
    Expert confirmé
    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 : 41
    Localisation : Belgique

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Citation Envoyé par mactwist69 Voir le message
    Moi j'aime bien.
    Merci ^^
    Kropernic

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