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

Langage Java Discussion :

Anti-pattern : exception métier


Sujet :

Langage Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 333
    Points : 295
    Points
    295
    Par défaut Anti-pattern : exception métier
    Bonsoir,

    Suite à une discussion avec un collègue, celui-ci m'a indiqué qu'utiliser le système d'exception de java pour traiter des cas métier (faire ses propres exceptions )dans une application était un anti-pattern classique.

    Son argument principal était les performances, les stacktraces consomment beaucoup....

    Je n'ai personnellement jamais utilisé d'exceptions personnalisées pour traiter des cas métier dans le cadre d'une grosse application, donc j'ai du mal à me faire une opinion.

    Une petite recherche google ne m'a vraiment convaincu de l'existence de cet anti-pattern ! Qu'en pensez vous ?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Citation Envoyé par LittleBean Voir le message
    Suite à une discussion avec un collègue, celui-ci m'a indiqué qu'utiliser le système d'exception de java pour traiter des cas métier (faire ses propres exceptions )dans une application était un anti-pattern classique.
    Attention, "faire ses propres exceptions" ne veut pas dire "utiliser le système d'exception de java pour traiter des cas métier".

    La création d'une exception est en effet assez lourde, c'est pourquoi il faut réserver les levées d'exceptions aux réels cas d'erreur, peu fréquents.
    Ce qu'il ne faut pas faire, c'est utiliser les exceptions pour gérer les cas métiers, c'est-à-dire les différents cas prévisibles sur lesquels on s'attend à tomber dans le cadre d'une utilisation normale de l'application.

    L'utilisation d'exceptions "personnalisées" est en revanche tout à fait normale, dans le cadre de la gestion d'erreurs.

  3. #3
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    je suis un peu surpris là .... on pourrait avoir un exemple pour comprendre?
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Un exemple à la con :
    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
    public static void traitement(String arg)
    throws BonjourException, AuRevoirException, UnexpectedArgException
    {
       if (arg.equals("bonjour")) throw new BonjourException();
       else if (arg.equals("aurevoir")) throw new AuRevoirException();
       else throw new UnexpectedArgException("Cet argument n'est pas valide. Arguments acceptés : 'bonjour' et 'aurevoir'.");
    }
     
    public static void main(String[] args)
    {
       try {
          traitement(args[0]);
       }
       catch (BonjourException e) {
          System.out.println("Bonjour !");
       }
       catch (AuRevoirException e) {
          System.out.println("Au revoir !");
       }
       catch (UnexpectedArgException e) {
          System.out.println(e.getMessage());
       }
    }
    Dans cet exemple la méthode traitement a trois points de sortie : deux points de sortie "normaux" (l'argument vaut 'bonjour' ou 'aurevoir') et un point de sortie d'erreur (l'argument ne fait pas partie de la liste des arguments acceptés).
    L'utilisation d'une exception pour l'erreur d'argument ne pose pas de problème: l'utilisateur est censé avoir lu la doc et lancer l'application avec le bon argument, il s'agit donc d'un cas d'erreur "exceptionnel"...
    Par contre, s'amuser à lancer des exceptions pour différencier les cas d'utilisation "normaux", c'est une utilisation abusive du système des exception.

    Bon, ici, mon exemple est très artificiel, il doit y avoir des cas où l'utilisation d'une exception en tant que point de sortie "normal" d'une méthode doit paraître moins absurde
    Mais en gros le problème c'est quand on commence à utiliser les exceptions pour transporter des informations sur un traitement "normal" au lieu d'utiliser par exemple des valeurs de retour et de réserver les exceptions aux cas d'erreur.

  5. #5
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 559
    Points : 15 484
    Points
    15 484
    Par défaut
    Je confirme ce que dit Astaree, les exceptions comme leur nom l'indique sont prévues pour gérer les situations exceptionelles qui sortent du fonctionnement de base, typiquement des paramètres invalides, des ressources inaccessibles, ...
    Il est tout a fait valable d'en définir de nouvelles, mais elle ne devraient pas être utilisées pour un fonctionnement normal.

    Cependant, comme le dit LittleBean, la génération du stacktrace est couteuse.
    Si dans un programme critique au niveau performance, on se trouve dans la situation rare où l'on devra lever énormément d'exceptions qui correspondent pourtant bien à un comportement exceptionnel, cela peut être préjudiciable pour les performances pure.
    Dans ce cas là, une solution possible serait de faire une méthode de vérification séparée qui retournera un booléen et non une exception
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // objet.addParam retourne une ParamException si le paramètre est invalide
    if (objet.isParamValid(param)){
      objet.addParam(param);
    }

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 333
    Points : 295
    Points
    295
    Par défaut
    Attention, "faire ses propres exceptions" ne veut pas dire "utiliser le système d'exception de java pour traiter des cas métier".
    Tout à fait d'accord c'est pour ça que j'ai rajouté une précision en parenthèse

    La création d'une exception est en effet assez lourde, c'est pourquoi il faut réserver les levées d'exceptions aux réels cas d'erreur, peu fréquents.
    Ce qu'il ne faut pas faire, c'est utiliser les exceptions pour gérer les cas métiers, c'est-à-dire les différents cas prévisibles sur lesquels on s'attend à tomber dans le cadre d'une utilisation normale de l'application.

    L'utilisation d'exceptions "personnalisées" est en revanche tout à fait normale, dans le cadre de la gestion d'erreurs.

    Est ce que tu pourrais détailler un peu plus ? Par exemple dans le cas où tu ne trouve pas un utilisateur en base ?

    Le seul argument contre cette pratique est les perf ?

    Edit : arg pas vu les 2 dernières réponses trop lent à poster :p
    => pour les exemples ok mais pour les contre argument je ne vois que les perf

  7. #7
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 559
    Points : 15 484
    Points
    15 484
    Par défaut
    Par exemple pour reprendre l'exemple d'Astaree, La version propre serait:
    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
    public static void traitement(String arg)
    throws BonjourException, AuRevoirException, UnexpectedArgException
    {
       if (arg.equals("bonjour")) System.out.println("Bonjour !");
       else if (arg.equals("aurevoir")) System.out.println("Au revoir !");
       else throw new UnexpectedArgException("Cet argument n'est pas valide. Arguments acceptés : 'bonjour' et 'aurevoir'.");
    }
     
    public static void main(String[] args)
    {
       try {
          traitement(args[0]);
       }
       catch (UnexpectedArgException e) {
          System.out.println(e.getMessage());
       }
    }
    On vois bien que le code de traitement exceptionnel est séparé du code de traitement normal ce qui est clairement plus propre. C'est le but des exceptions.

  8. #8
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    Citation Envoyé par Uther Voir le message
    Je confirme ce que dit Astaree, les exceptions comme leur nom l'indique sont prévues pour gérer les situations exceptionelles qui sortent du fonctionnement de base, typiquement des paramètres invalides, des ressources inaccessibles, ...
    Il est tout a fait valable d'en définir de nouvelles, mais elle ne devraient pas être utilisées pour un fonctionnement normal.
    je dois être bouché mais j'ai vraiment besoin d'un exemple qui veuille dire quelque chose!
    Si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class CompteEnBanque {
           private double solde ; // je mets double pour simplifier
           private  double découvertAutorisé ; // idem
           /// codes
           public void retrait(double montant) throws 
                                     ExceptionDepassementDecouvert {
                   // code métier qui déclenche l'exception
          }
    }
    je ne vois pas en quoi ceci serait un anti-pattern.
    On a un "code appelant" qui demande un service et qui n'a pas de moyen de connaitre les conditions de l'echec de sa demande...
    Il est normal donc d'avoir une exception controlée pour signifier l'echec de la demande de service.
    Le contraire serait un drôle de détournement des principes de Java: avoir une méthode "à la fonction C" qui rendrait ....? quoi au fait?
    adopter une stratégie "à la C" aurait pour conséquence:
    - de laisser le code appelant écrire un code qui n'est pas forcé de prendre en compte l'échec du service.
    - de spécifier dans bien des cas un résultat de retour assez tordu
    (quid si la méthode doit déjà rendre un résultat "normal", quid si l'échec de service concerne un constructeur).
    Donc pour revenir à ma question initiale: un exemple pertinent svp. merci
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  9. #9
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 559
    Points : 15 484
    Points
    15 484
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    je dois être bouché mais j'ai vraiment besoin d'un exemple qui veuille dire quelque chose!
    Si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class CompteEnBanque {
           private double solde ; // je mets double pour simplifier
           private  double découvertAutorisé ; // idem
           /// codes
           public void retrait(double montant) throws 
                                     ExceptionDepassementDecouvert {
                   // code métier qui déclenche l'exception
          }
    }
    je ne vois pas en quoi ceci serait un anti-pattern.
    On a un "code appelant" qui demande un service et qui n'a pas de moyen de connaitre les conditions de l'echec de sa demande...
    Il est normal donc d'avoir une exception controlée pour signifier l'echec de la demande de service.
    Le contraire serait un drôle de détournement des principes de Java: avoir une méthode "à la fonction C" qui rendrait ....? quoi au fait?
    adopter une stratégie "à la C" aurait pour conséquence:
    - de laisser le code appelant écrire un code qui n'est pas forcé de prendre en compte l'échec du service.
    - de spécifier dans bien des cas un résultat de retour assez tordu
    (quid si la méthode doit déjà rendre un résultat "normal", quid si l'échec de service concerne un constructeur).
    Donc pour revenir à ma question initiale: un exemple pertinent svp. merci
    Ton exemple correspond typiquement à un usage pertinent des exceptions. Le dépassement de découvert correspond à un état exceptionnel.

    Alors que l'exemple d'Astartee est un exemple de mauvais usage: "bonjour" et "aurevoir" correspondant visiblement a un fonctionnement normal, qui ne devrait pas être traité par exception.

  10. #10
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    ton exemple est correct shadoko. On considère le dépassement comme étant un cas d'erreur. Ce qui signifie probablement qu'il existe une méthode getMontant() et isDepassementAutorisé() qui permettent à l'appelant, au préalable, de savoir si oui ou non il peut faire le retrait. Autrement dit, le retrait est supposé faisable par l'appelant. Une exception, c'est un "cas d'erreur" et c'est ce qui devrait diriger le choix de l'exception. Si une méthode a plusieurs résultats normaux possible, alors on utilise la valeur de retour. L'un ne dois pas se substituer à l'autre. On n'utilise pas une valeur de retour pour gérer des cas d'erreur, on utilise pas une exception pour gérer des valeurs de retour multiples.

    Maintenant, une exception c'est lourd, et il existe comme toujours une zone grise ou on devrait utiliser une exception mais les besoins en performance l'empechent, mais ces zones grises sont ténues et rare (en 5 an de prog, jamais tombé sur ce genre de cas)

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    La méthode retrait de la classe CompteEnBanque n'a rien d'anti-pattern ça force le client à prêter attention lors de son utilisation!

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    je dois être bouché mais j'ai vraiment besoin d'un exemple qui veuille dire quelque chose!
    Donc pour revenir à ma question initiale: un exemple pertinent svp.
    Bah, en fait, j'ai un peu de mal à trouver un exemple pertinent de code à ne pas faire

    Utilisation recommandée des exceptions :
    On appelle un méthode censée effectuer un traitement. Il se peut qu'en cours de traitement un problème apparaisse : mauvais input qui rend le traitement impossible, ressource indisponible, etc. Dans ce cas on arrête tout et on lève une exception, récupérée par le code appelant qui peut alors utiliser les informations contenues dans l'exception pour décider de la suite des opérations...
    Ton exemple est une utilisation correcte de l'exception : le code appelant essaie d'effectuer un traitement (retrait d'argent sur un compte), mais en cours de traitement on se rend compte que ce n'est pas possible (découvert dépassé) donc on lève une exception, ce qui permet au code appelant 1/ de comprendre que son traitement a échoué qqpart 2/ grâce à l'utilisation d'une exception personnalisée, de savoir plus précisément ce qui a échoué (compte inexistant ? découvert dépassé?) et donc de décider du traitement de l'erreur.

    Utilisation déconseillée des exceptions :
    Certains développeurs trouvent formidable cette possibilité de sortir d'un traitement à tout moment, en renvoyant un objet (l'exception) qui peut ensuite facilement être filtré (par les blocs catch) pour décider du traitement suivant. Il se servent alors des exceptions comme d'une sorte de "valeur de retour", afin de transmettre des informations au code appelant, même si le traitement initialement demandé a effectivement réussi.
    Il s'agit d'une utilisation abusive, car la création d'une exception est lourde, et qu'il vaut mieux utiliser une réelle valeur de retour (return blablabla; ) si l'on veut transmettre une information au code appelant.
    C'est cela que le collègue de LittleBean qualifiait d'"anti-pattern" : l'utilisation d'un "pattern" classique de Java (les exceptions) mais dans un contexte détourné (en dehors des cas d'erreur), ce qui rend le code peu efficace et peu compréhensible par la plupart des développeurs pour qui "exception"="erreur".
    J'ai malheureusement du mal à trouver un exemple pertinent de cette utilisation des exceptions puisque, justement, ce n'est pas pertinent !

    Autre cas où l'utilisation des exceptions peut être déconseillée :
    Comme l'a indiqué Uther, il se peut que dans un code pour lequel les performances sont critiques l'utilisation d'exceptions soit trop coûteuse (même si d'un point de vue logique, dans le code, elle est parfaitement justifiée).
    Dans ce cas il peut être plus efficace de se priver des exceptions et de revenir à une gestion "à la C" des erreurs, avec différentes valeurs de retour en fonction de la réussite ou de l'échec du traitement.
    Mais il s'agit là d'un autre problème que celui initialement évoqué par LittleBean.

  13. #13
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    A une époque, on trouvait des bouts de code utilisant ArrayIndexOutOfBoundsException au lieu d'un index de tableau, qui prétendaient être plus performant car ne faisant pas de test sur la taille du tableau à chaque itération. Typiquement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    // A l'époque certains prétendaient que ce traitement était plus performant:
    Object[] array = ...;
    int i=0;
    try {
        while(true) {
            Object o = array[i];
            doSomethingWith(o);
            i++;
        }
    } catch(ArrayIndexOutOfBoundsException e)  {
        // c'est bon on a parcouru tout le tableau
    }
    ... ce qui n'est évidement pas conseillé
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  14. #14
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    L'anti-pattern ne concerne pas particulièrement les exceptions personnelles, mais plus globalement la manière dont on utilise les exceptions.

    Les exceptions doivent uniquement gérer les cas d'erreurs.

    Or ce n'est pas toujours le cas, et les exceptions peuvent être utilisé en remplacement des structures de contrôles traditionnelles. C'est difficile à expliquer car bien souvent le code est plus long et plus complexe à comprendre qu'un code tout simple, et qu'il peut faire hurler beaucoup de monde



    Par exemple une erreur basique serait d'utiliser les exceptions pour indiquer que la méthode s'est terminé normalement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	public static void read() throws IOException, OKException {
    		// code qui provoque une IOException en cas d'erreur
     
    		// On retourne une exception pour signalé que la méthode à réussi
    		// => C'est le monde à l'envers 
    		throw new OKException("ok");
    	}
    On est carrément dans le cas extrême car les exceptions sont utiliser à l'inverse même de leurs objectifs initial.


    On peut vouloir simuler une type de retour pouvant prendre différentes formes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	public static void multipleRetour() {
    		if (condition) {
    			throw new UnTypeException(new Type());
    		} else if (condition2) {
    			throw new UnAutreTypeException(new UnAutreType());
    		} else if (condition3) {
    			throw new MultipleTypeException(new Type(), new UnAutreType());
    		} else {
    			// Le seul cas d'erreur :
    			throw new IllegalStateException();
    		}
    	}
    On préfèrera bien sûr utiliser un type commun ou un type générique.



    On peut les utiliser pour effectuer un genre de GOTO :
    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
    	try {
     
    		// ...
    		if (condition) {
    			throw GoToAction1();
    		}
    		// ...
    		if (condition) {
    			throw GoToAction2();
    		}
    		// ...
    		if (condition) {
    			throw GoToAction3();
    		}
     
    	} catch (GoToAction1 e) {
    		// Traitement métier 1
    	} catch (GoToAction2 e) {
    		// Traitement métier 2
    	} catch (GoToAction3 e) {
    		// Traitement métier 3
    	}
    Ce serait plutôt l'algorithme et/ou le découpage qui serait à revoir.



    En clair, l'erreur survient lorsque le code de traitement de l'exception est ignoré ou effectue un traitement métier et non pas un traitement de l'erreur.
    C'est souvent lié à des exceptions personnels lorsque l'exception en elle-même n'est pas pensé pour gérer un cas d'erreur...



    On peut bien sûr avoir le même type de problème avec les exceptions de bases en les détournant de leurs objectifs originaux.

    Par exemple en parcourant une collection jusqu'à obtenir une erreur plutôt que d'utiliser la méthode hasNext() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	Iterator<String> iterator = list.iterator();
    	while(true) {
    		try {
    			System.out.println(iterator.next());
    		} catch (NoSuchElementException e) {
    			break;
    		}
    	}



    En fait on peut même considérer que le code suivante est une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	public static boolean isNumber(String s) {
    		try {
    			NumberFormat.getIntegerInstance().parse(s);
    			return true;
    		} catch (ParseException e) {
    			return false;
    		}
    	}
    Voyez-vous pourquoi ???


    a++

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Pill_S: Effectivement ton code est un peu plus performant dans le cas où la taille du tableau est très grande (> 100.000 éléments) car en interne la JVM vérifie l'index d'un tableau, donc avec une boucle normal on fait une double vérification de l'index.

  16. #16
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    En fait on peut même considérer que le code suivante est une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	public static boolean isNumber(String s) {
    		try {
    			NumberFormat.getIntegerInstance().parse(s);
    			return true;
    		} catch (ParseException e) {
    			return false;
    		}
    	}
    Voyez-vous pourquoi ???
    sur ce dernier je reconnais que j'ai comme une hésitation
    (en utilisant Integer.parseInt(s)).
    En supposant déjà que les spécifications de la méthode isNumber soient pertinentes je suis horriblement tenté (vade retro satanas ) j'ai des doutes affreux sur s.matches(exprReg) car je ne suis pas sûr qu'elle tienne la meme route que Character.isDigit() - et dans ce cas ça revient à reécrire parseInt(s)- une solution élégante et politiquement correcte?
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  17. #17
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    je dirais oui c'est une erreur d'antipattern doublée d'une méconnaissance de numberformat.

    En effet, le code sortira les valeurs suivantes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    isNumber 123 -> true
    isNumber 123vv -> true
    isNumber aa -> false

    La méthode propre et plus rigoureuse:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	public static boolean isNumber(String s) {
    		ParsePosition pp = new ParsePosition(0);
    		NumberFormat.getIntegerInstance().parse(s,pp);
    		return pp.getIndex()==s.length();
    	}
    qui retourne bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    isNumber 123 -> true
    isNumber 123vv -> false
    isNumber aa -> false
    et qui, notez le bien, fait 3 lignes de moins Je crois que cet exemple est très bon car utilisé par beaucoup, dans une méthode potentiellement fortement utilisée (on pourrait imaginer qu'une boucle de traitement sur un document texte l'utilise pour savoir si oui ou non on est face à un nombre afin de décider d'un traitement) et ou donc l'utilisation d'exceptions est préjudiciables.


    Utiliser l'exception de parseInt ou de NumberFormat est finalement donc utiliser l'effet de bord d'un code. On est par contre je pense, tous assez d'accord pour dire qu'il manque à Integer un méthode statique isInteger(String s)

    Cependant, number.matches("^-?[0-9]+$") me semble le plus rapide à mettre en oeuvre :p

  18. #18
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Cependant, number.matches("^-?[0-9]+$") me semble le plus rapide à mettre en oeuvre :p
    l'avantage de NumberFormat c'est que ça va marcher dans un contexte d'internationalisation (merci pour le truc avec parsePosition) alors que le matches ne va pas marcher.
    l'autre solution c'est de faire une boucle avec Character.isDigit()
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Cependant, number.matches("^-?[0-9]+$") me semble le plus rapide à mettre en oeuvre :p
    le ^ et $ ne sont pas nécessaire si tu utilise matches qui va matcher sur tout le string et pas juste une portion. Pour plus de performance vaut mieux compiler le Pattern une seule fois (variable static) et utiliser Pattern.matches(String) autant de fois..

  20. #20
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    effectivement, on oublie souvent les chiffre dans les langues non latines. (arabe, chinois, japonais...)

Discussions similaires

  1. Réponses: 10
    Dernier message: 06/10/2010, 17h06
  2. Les exceptions métiers
    Par zoaax dans le forum Général Dotnet
    Réponses: 12
    Dernier message: 15/04/2010, 14h31
  3. singleton == anti pattern?
    Par yan dans le forum C++
    Réponses: 5
    Dernier message: 17/04/2008, 14h17
  4. Réponses: 11
    Dernier message: 26/09/2007, 11h28

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