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

Java Discussion :

Stratégies de gestion des exceptions


Sujet :

Java

  1. #21
    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
    c'est ce que je disais, on peux chainer l'exception

  2. #22
    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 et si les exceptions vous em...bètent
    bon je n'ai pas pu résister au plaisir (pervers) du hack au sujet des exceptions (attention contient du java 8)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      @FunctionalInterface
    public interface PeskyConsumer<X,T extends Throwable> {
        public void accept(X arg) throws T ;
    }
    Bon jusque là on a juste un Consumer qui a des problèmes d'exceptions
    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
     
    //d'accord il y a de l'abus ce n'est pas une interface mais une classe avec uniquement des méthodes statiques
    public interface Teflon {
     
        public default <X, T extends Throwable> Consumer<X> teflonize(final PeskyConsumer<X,T> consumer) {
            return new Consumer<X>() {
                @Override
                public void accept(X t) {
                    try {
                        consumer.accept(t);
                    } catch (Throwable exc) {
                        Teflon.<RuntimeException>forgetThrowsClause(exc);
                    }
     
                }
            } ;
     
        }
            public static <T extends Throwable> T forgetThrowsClause(Throwable t) throws T{
                throw (T) t;
            }
    }
    maintenant travaux pratiques :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // code  inutile (on pourrait directement appeler en "teflonizant") 
    class PlasticArrayList<T> extends ArrayList<T> implements Teflon{
         public void forEachPesky(PeskyConsumer<T,?> pesk) {
                forEach(teflonize(pesk));
            }
        }
    de plus en plus compliqué (sans augmentation du prix des places!)
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
     @FunctionalInterface
    public interface MayFail {
        public void check() throws Exception ;
    }
     
    public class PotentialFail implements MayFail{
        boolean fail ;
        static int num ;
        int number = num++ ;
     
        public PotentialFail(boolean fail) {
            this.fail = fail;
        }
     
        @Override
        public void check() throws Exception {
            System.out.println("call " +this);
            if(fail) {
                throw new Exception("failed" +this) ;
            }
     
        }
     
        public String toString() {
            return "PotentailFail " + number ;
        }
    }
     
    public class TestSneakyConsumer {
     
        public static void main(String[] args) {
            PlasticArrayList<PotentialFail> list = new PlasticArrayList<>() ;
            list.add(new PotentialFail(false)) ;
            list.add(new PotentialFail(true)) ;
            list.add(new PotentialFail(false)) ;
            try {
                list.forEachPesky(MayFail::check);
            } catch(Exception exc) {
                System.err.println("got Exception" +exc);
            }
        }
    }
    comme quoi: pourquoi faire simple quand on peut faire crade ?
    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)

  3. #23
    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
    Attends là, j'ai bien lu, tu as sod***sé à sec le compilateur et la jvm en déguisant un Throwable quelconque en RuntimeException?

    Je savais qu'il était possible de s'affranchir de l'obligation de catch dans la jvm, via des modifications du bytecode ou l'utilisation d'autres langages, mais pas que c'était possible juste en jouant avec les generic

    Bravo! Tu as gagné le prix du pyscodepathe du mois
    On commence comme ça et on fini par pondre du code pour ajouter dynamiquement des valeurs dans les enum ou pour construire un objet sans jamais appeler son constructeur

  4. #24
    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
    On commence comme ça et on fini par pondre du code pour ajouter dynamiquement des valeurs dans les enum ou pour construire un objet sans jamais appeler son constructeur
    Je suis d'accord avec le fait qu'on souhaite parfois le retour de la sainte inquisition
    en fait ce hack a été publié il y a 5 ans mais avec les objets de java.util.function on a un problème et là on peut (peut-être) faire un usage de ce truc qui ne nous garantisse pas une place en enfer ... voici , il me semble, un code, plus propre :
    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
     
    public class Cocoon {
         static <T extends Throwable> T forgetThrowsClause(Throwable t) throws T{
            throw (T) t;
        }
     
        public static <X, T extends Throwable> Consumer<X> consumer(PeskyConsumer<X,T> peskyConsumer) throws T {
            return new Consumer<X>() {
                @Override
                public void accept(X t) {
                    try {
                        peskyConsumer.accept(t);
                    } catch (Throwable exc) {
                        Cocoon.<RuntimeException>forgetThrowsClause(exc) ;
                    }
     
                }
            } ;
        }
     // etc, etc.. avec les principaux codes de java.util.function : Function, Supplier, ...
    ici l'obligation de faire un catch est juste reportée d'un cran.
    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)

  5. #25
    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
    @professeur shadoko : je trouve qu'il y a quelques soucis avec ce "hack" :
    • Cela cache le throw au compilateur, ce qui peut être gênant dans certains cas (le compilateur ne détecte pas la sortie de la méthode).
    • Mais surtout on ne peut pas catcher l'exception simplement, car le compilateur va nous empêcher de faire un try/catch sur une checked-exception si elle n'est pas déclarée dans les méthodes...


    Perso je préfère quand même les englober dans une RuntimeException, voir une exception perso avec une méthode fillInStackTrace() vide pour éviter le double stacktrace...


    Par contre il est clair que les checked-exceptions deviennent (encore plus) une plaie avec les lambdas.


    a++

  6. #26
    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
    reprenons le deuxième cas (Cocoon) : la méthode de masquage des exceptions n'est pas publique
    on ne cache que provisoirement le catch au compilateur et l'exception remonte correctement
    c'est comme si on disait: provisoirement j'ai une petite partie de code dans laquelle je ne peux retranscrire les clauses obligatoires (throws) mais :
    - les exceptions vont remonter correctement (et interrompre un traitement si nécessaire)
    - en bout de chaine je reinstalle l'obligation de faire un catch
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      try { /// try/catch obligé!
                Consumer<PotentialFail> cons = Cocoon.consumer(PotentialFail::check);
                list.forEach(cons);
            } catch(Exception exc) {
                System.err.println("got Exception" +exc);
            }
           // ici pas de try catch (toString est stupide : c'est juste pour montrer que le compilo n'exige pas de try/catch)
            Consumer<PotentialFail> cons = Cocoon.consumer(PotentialFail::toString);
            list.forEach(cons);
    j'ai donc une zone de code dans laquelle je neutralise l'obligation de clause throws (parceque les librairies de fonction ne le prévoient pas) mais je remets les choses proprement (sans rajouter une RuntimeException d'emballage)
    c'est un utilitaire à destination d'autres programmeurs
    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)

  7. #27
    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
    Citation Envoyé par adiGuba Voir le message

    Par contre il est clair que les checked-exceptions deviennent (encore plus) une plaie avec les lambdas.
    Le problème n'est pas selon moi les lambdas, mais surtout le fait qu'à aucun moment il semblerais, les apis stream n'aient envisagé qu'il puisse être vaguement possible qu'un machin de la chaine lance une exception


    D'ailleurs, si je lance une RuntimeException dans un parallelStream, il se passe quoi? Est-ce que la spec précise quoi que ce soit à ce sujet? Les autres threads continuent de consommer, tout s'arrête? quoi?

  8. #28
    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
    Citation Envoyé par tchize_ Voir le message
    Le problème n'est pas selon moi les lambdas, mais surtout le fait qu'à aucun moment il semblerais, les apis stream n'aient envisagé qu'il puisse être vaguement possible qu'un machin de la chaine lance une exception
    Il peut tout à fait y avoir une exception dans un Stream... du moment que c'est une RuntimeException car l'API ne déclare pas d'exception.
    (ou qu'on utilise un hack comme celui du professeur shadoko)


    Le problème c'est uniquement cette limitation des checked-exceptions qui impose de déclarer les exceptions.
    Il aurait fallut rajouter des "throws Exception" partout pour que cela puisse fonctionner avec des checked-exception, mais cela aurait eu l'effet pervers de devoir de trainer des try/catch partout même lorsqu'il n'y en a pas besoin !

    Une autre solution envisagé à un moment consistait à faire évoluer l'API des Generics pour qu'elle puissent gérer proprement des exceptions en paramétrage... mais cela emmenait pas mal de soucis et de complexité...


    Citation Envoyé par tchize_ Voir le message
    D'ailleurs, si je lance une RuntimeException dans un parallelStream, il se passe quoi? Est-ce que la spec précise quoi que ce soit à ce sujet? Les autres threads continuent de consommer, tout s'arrête? quoi?
    Ben il n'y a rien de particulier : le traitement est arrêté et tu reçois une exception.
    Les autres threads sont bien sûr stoppé (mais sauf erreur c'est l'API ForkJoin de Java 7 qui doit gérer cela).


    a++

  9. #29
    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
    est-ce qu'ici le problème n'est pas plutôt ce que fait l'agent situé dans le stream?
    Si c'est un filtre le code devrait lui-même s'occuper de l'exception et retirer (ou invalider d'une certaine manière) l'objet coupable du stream ....
    idée à demi-cuite: gérer alors un flot d'exceptions à part (j'ai un peu ça dans une gestion d'exception de démarrages de matériel: on essaye de démarrer tous les matériels qui sont indépendants les uns des autres et le code reçoit à la fin une Exception qui est en fait une séquence d'exceptions: le matériel A2 a ça, le matériel B5 a ça, le matériel C7 a ça , etc....- ce ne sont pas des "causes" au sens Java puisqu'on a des incidents indépendants qui sont collectés dans une même opération-)
    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)

Discussions similaires

  1. [EJB] [Stratégie] Gestion des exceptions
    Par nelob dans le forum Java EE
    Réponses: 0
    Dernier message: 15/05/2009, 16h40
  2. [ORACLE 9i] Gestion des exceptions
    Par sygale dans le forum SQL
    Réponses: 6
    Dernier message: 19/08/2004, 16h06
  3. Gestion des exception (EOleException)
    Par shurized dans le forum Bases de données
    Réponses: 5
    Dernier message: 30/06/2004, 18h25
  4. [XMLRAD] gestion des exceptions
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 28/01/2003, 18h48
  5. c: gestion des exceptions
    Par vince_lille dans le forum C
    Réponses: 7
    Dernier message: 05/06/2002, 15h11

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