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

C# Discussion :

Gestion des Exceptions dans une librairie


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    92
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 92
    Points : 83
    Points
    83
    Par défaut Gestion des Exceptions dans une librairie
    Bonjour,

    Sur un projet de librairies, je me suis basé sur ce que dit le msdn ici et ici pour gérer les exceptions, comme : ne pas rattraper les ApplicationException et les SystemException, ni en hériter. De plus, il indique (ici) de ne pas en abuser car l'instruction throw plombe les perf... Est-ce aussi le cas des blocs try/catch/finally ???

    Le dernier lien propose aussi 2 patterns (je ne sais pas si j'ai bien compris) :
    - Tester-Doer pattern : consiste à vérifier chaque paramètre avant l'appel d'une méthode pour éviter de l'appeler avec un paramètre qui génèrera une exception.
    - TryParse pattern : consiste à créer 2 fonctions... bref tout le monde connait, ex: int.Parse/TryParse ou DateTime.ParseExact/TryParseExact.
    Y a-t-il d'autres patterns de gestion d'exception ???

    J'ai tenté d'implémenter la 2nd option :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class MyClass
    {
        public void DoSomething() { [...] }
        public bool TryDoSomething()
        {
            try { DoSomething(); return true; }
            catch { return false; }
        }
    }
    Mais je ne vois pas l'avantage car dans un cas l'exception est rattrapée par la méthode "appelante", dans l'autre par la méthode appelée :
    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
    public class MyTester
    {
        public MyClass MyObject = new MyClass();
     
        public void DoSomethingTest() // cas 1
        {
            try { MyObject.DoSomething(); }
            catch { [...] } // Log error
        }
     
        public void TryDoSomethingTest() // cas 2
        {
            if (!MyObject.TryDoSomething()) [...] // Log error
        }
    }
    Or dans les 2 cas, une exception est lancée...
    J'ai du faire une erreur, quelqu'un peut m'aider svp ?

  2. #2
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Points : 2 331
    Points
    2 331
    Par défaut
    Oui, mais avec ton Try, la personne qui utilise ton API sait qu'aucune exception n'est levée. Dans certains cas c'est judicieux, dans d'autres il peut être utile de remonter l'exception... La problématique n'est donc pas uniquement les perfs.

    De plus, ton exemple peut être remanié :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ublic class MyClass
    {
        public void DoSomething() { [...] }
        public bool TryDoSomething()
        {
            if(myStream == null) //ou tout autre élément pouvant générer des erreurs... On peut imaginer tout une série de if pour tout contrôler (les arguments, la connexion SQL, la disponibilité d'un serveur distant...) et à la fin un bloc try/catch préventif
                return false;
            try { DoSomething(); return true; }
            catch { return false; }
        }
    }
    Et dans ce cas là tu ajoutes un contrôle de cohérence en interne, alors qu'avec DoSomething, tu exposes à l'utilisateur ces problèmes. ce sont des choix de design tout dépend comment tu souhaites communiquer... Tu peux très bien uniquement faire des DoSomething, et dans les commentaires, signaler les exception qui peuvent être levées,e t en déléguer la gestion au client (requête SQL).

    Une exception coûte plus cher qu'un simple test, car instanciation de l'objet et remonter la pile d'appels, mais ce n'est pas pour autant qu'il ne faut pas les utiliser.

  3. #3
    Membre habitué Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Points : 159
    Points
    159
    Par défaut
    Bonjour,

    Je pense qu'effectivement vous passez à coté d'un détail :
    - "Tester-Doer" (que j'interprete "Tester-faire") signifie tester et faire. Il y a cependant (à mon avis) un sous entendu : Tester sans try-catch.

    Par exemple, si vous devez faire la conversion suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    unEntierInt = int.Parse(unEntierString);
    Les deux patterns dont vous parlez s'implementerons des facons suivantes :

    Déclarations:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    string unEntierString;
    int unEntierInt;
    Modèle "Tester-Faire":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    bool unEntierStringEstVraimentUnEntierBool;
    unEntierStringEstVraimentUnEntierBool = System.Text.RegularExpressions.Regex.IsMatch(unEntierString, "[0-9]*");
    if (unEntierStringEstVraimentUnEntierBool)
        {
        // unEntierString ne contien que des chiffres
        unEntierInt = int.Parse(unEntierString);
        // Le reste du code
        }
    else
        {
        // Erreur previsible donc ...
        }
    Modele "Try Catch":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    try
        {
        unEntierInt = int.Parse(unEntierString);
        // Le reste du code
        }
    catch (Exception)
        {
        // Erreur non prévue ...
        }
    Sur un cas aussi simple, il est évident de tester tous les cas (Je suis certain que tout le monde aura remarqué que dans le modèle "Tester-faire" la presence d'un signe moins fera anormalement passer dans la partie "Erreur" et qu'un nombre trop important de digit levera une exception...).

    Sur des cas plus complexe en revanche, lorsque tous les cas ne sont pas connus un try-catch est plus sûre. Par exemple, qui prévoit lors de l'ouverture d'un fichier que celui-ci soit vérouillé par Excel ? Et pourtant, ca arive toujours aux clients !

    Par experience, dire qu'on a prévu tous les cas , ce qui rassure le client , est un peu prétentieux . Il est bien plus juste de dire que tous les cas prévus ont été implémentés, cela peut cependant lui faire peur ...

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    92
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 92
    Points : 83
    Points
    83
    Par défaut
    Citation Envoyé par Arnard Voir le message
    [...] tu ajoutes un contrôle de cohérence en interne, alors qu'avec DoSomething, tu exposes à l'utilisateur ces problèmes. [...]
    Merci Arnard ! Je n'avais pas vu ça sous cet angle. En fait dans mon code, le contrôle de cohérence est fait dans DoSomething mais lorsqu'une erreur est détecté, au lieu de retourner false, je lançais une exception, par exemple ArgumentNullException ou PropertyException<TDelegate>. Du coup, vu que le contrôle était déjà fait, je n'ai pas pensé à le refaire dans TryDoSomething.

    Par contre pour la maintenance du code, j'ajouterai juste un commentaire dans la méthode DoSomething pour indiquer qu'une modification du contrôle de cohérence doit être dupliqué dans la méthode TryDoSomething. Sinon j'ajouterai une méthode privée, je ne sais pas encore ce qui est le mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    /// <summary>
    /// Appeler dès le début de DoSomething et TryDoSomething.
    /// </summary>
    /// <return>Indique s'il est possible de lancer DoSomething ou non.</return>
    private bool _BeforeDoSomething(bool throwExceptionOrNot) { [...] }
    Citation Envoyé par LeCygne Voir le message
    [...]Sur des cas plus complexe en revanche, lorsque tous les cas ne sont pas connus un try-catch est plus sûre. Par exemple, qui prévoit lors de l'ouverture d'un fichier que celui-ci soit vérouillé par Excel ? Et pourtant, ca arive toujours aux clients ![...]
    C'est vrai, l'utilisation du bloc try/catch est primordiale dans de nombreux cas. Sauf qu'ici pour la conception de mes librairies, je me demandais s'il fallait prendre cette responsabilité ou la laisser à l'utilisateur de la DLL pour que ce soit carré... Je me suis documenté à droite, à gauche, et puis grâce à Arnard, j'ai opté pour la solution qui donne le choix à l'utilisateur en créant des méthodes Try, exemple :

    - DoSomething (c'est à l'utilisateur de faire le try/catch)
    - TryDoSomething (le try/catch est interne à la méthode)
    mais peut être aussi :
    - _BeforeDoSomething (contrôle avant le traitement, non visible par l'utilisateur de la DLL bien sûr)
    et pourquoi pas envisager :
    - _AfterDoSomething

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    92
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 92
    Points : 83
    Points
    83
    Par défaut
    Ah j'oubliai, sinon connaissez-vous d'autres patterns de gestion d'exception ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestion des exceptions dans une procédure stockée
    Par merlubreizh dans le forum DB2
    Réponses: 13
    Dernier message: 02/10/2012, 18h05
  2. Réponses: 0
    Dernier message: 07/11/2009, 11h46
  3. gestion des utilisateurs dans une solution 3-tiers
    Par nadia lydia dans le forum Oracle
    Réponses: 3
    Dernier message: 26/10/2005, 12h58
  4. [Conception] Gestion des accents dans une base de données
    Par MiJack dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 07/07/2005, 11h41
  5. [VB6] Gestion des erreurs dans une dll
    Par zimba-tm dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 02/08/2004, 11h20

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