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 :

Conception : remplacer 5000 if


Sujet :

Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut Conception : remplacer 5000 if
    Bonjour à tous,
    Je précise d'emblée pour les modérateurs que j'ai posté ce message dans la section "algorithme", mais vu le peu de réponse, je poste ici.
    Voici mon problème. Je travaille sur une interface d'exportation de messages mail. J'ai 10 critères d'exportation, qui peuvent se combiner les uns avec les autres sans restriction.
    Avec un exemple de 3 critères de sélection (date, titre, nombre de locuteurs), on a 7 possibilités :
    - si date = xxx
    - si date = xxx ET titre = xxx
    - si date = xxx ET nombre de locuteurs = xxx
    - si date = xxx ET titre = xxx ET nombre de locuteurs = xxx
    - si titre = xxx
    - si titre = xxx ET nombre de locuteurs = xxx
    - si nombre de locuteurs = xxx

    le truc horrible, c'est qu'avant je faisais ça avec des simples AND en SQL (un String sql dont le debut était un SELECT xxx FROM xxx WHERE et puis j’ajoutai mes critères et des AND selon les champs remplis) puisque les données venaient d'une BDD, et je m'en sortais avec 2000 lignes, mais là je sèche complètement ... J'ai beau retourné le problème, je me retrouve pour l'instant avec 6000 lignes de code, des if de if de if de if de if ... etc, sans avoir même fini le 1er critère!
    Autant dire que s'il y a un changement à faire, c'est la galère ...
    Avez-vous des idées d'amélioration ?
    Merci d'avance !

  2. #2
    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
    Salut,


    Et d'où viennent les données désormais ???


    a++

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    un objet message

  4. #4
    Membre éprouvé
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Points : 968
    Points
    968
    Par défaut
    Ce que je ferais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Faire un tableau de booléens qui dit quels critères sont sélectionnés.
    Pour chaque message:
      pour chaque booléen:
        si le booléen est VRAI
          si le critère associé est FAUX
            rejeter le message et passer au message suivant
      accepter le message
    A moins que j'aie pas compris le problème, ça devrait pas être plus compliqué que ça.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par math_lab Voir le message
    Ce que je ferais:
    ça devrait pas être plus compliqué que ça.
    Merci de pointer mon incompétence
    Le problème c'est que ton raisonnement marche bien pour des OU : critère 1 OU critère 2 OU critère 3 ... etc.
    Mais ne marche pas avec des ET car à la fin de ta boucle, lorsque tu rejettes le message, il ne faut pas le rejeter, mais re-tester avec les autres critères, ce qui ajoute tous ces if à la queue leu leu. De même si le critère associé est vrai, il faudra quand même tester avec les autres critères si ceux-ci sont sélectionnés !

  6. #6
    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
    Je suppose donc qu'ils sont stocké dans une collection ?


    La solution consiste tout simplement à passer par un filtre via des "predicates".
    Il n'y a malheureusement rien en standard pour le moment (c'est prévu pour Java 8).

    Tu peux te tourner vers des librairies plus évolué comme Google Guava ou bien implémenter cela toi même (ce n'est pas bien compliqué).


    Il suffit de définir une interface Predicate comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    interface Predicate<T> {
    	public boolean eval(T value);
    }
    Puis de se faire une méthode de filtre comme ceci :
    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
    	public static <T> List<T> filter(Iterable<T> values, Iterable<Predicate<T>> predicates) {
    		List<T> result = new ArrayList<T>();
     
    		// On parcours toutes les valeurs :
    		for (T value : values) {
    			// Si elle correspondent aux "Predicates" :
    			if (evalAll(value, predicates)) {
    				// On ajoute la valeur aux résultats :
    				result.add(value);
    			}
    		}
    		return result;
    	}
     
    	private static <T> boolean evalAll(T value, Iterable<Predicate<T>> predicates) {
    		// On évalue tout les "Predicates"
    		for (Predicate<T> p : predicates) {
    			if ( ! p.eval(value)) {
    				// Si un seul est faux, on arrête immédiatement
    				return false;
    			}
    		}
    		// Sinon c'est OK :
    		return true;
    	}

    Tu passes à la méthode ta collection, suivi de toutes les "Predicates" qui correspondent à tes diverses conditions.



    Le plus simple serait alors de se faire des méthodes static pour chaque "Predicate" de base :
    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
    class MessagePredicates {
    	public static Predicate<Message> dateEquals(final Date date) {
    		return new Predicate<Message>() {
    			@Override
    			public boolean eval(Message message) {
    				return message.getDate().equals(date);
    			}
    		};
    	}
     
    	public static Predicate<Message> titleEquals(final String title) {
    		return new Predicate<Message>() {
    			@Override
    			public boolean eval(Message message) {
    				return message.getTitle().equals(title);
    			}
    		};
    	}
     
    	public static Predicate<Message> speakerCountEquals(final int speakerCount) {
    		return new Predicate<Message>() {
    			@Override
    			public boolean eval(Message message) {
    				return message.getSpeakerCount() == speakerCount;
    			}
    		};
    	}
    }

    Ensuite tu ajoutes les Predicates selon la saisie utilisateur (ou autre) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	List<Message> list = new ArrayList<Message>();
    	List<Predicate<Message>> predicates = new ArrayList<Predicate<Message>>();
     
    	if (date!=null) {
    		predicates.add(MessagePredicates.dateEquals(date));
    	}
    	if (title!=null) {
    		predicates.add(MessagePredicates.titleEquals(title));
    	}
    	if (speakerCount>0) {
    		predicates.add(MessagePredicates.speakerCountEquals(speakerCount));
    	}
     
    	List<Message> result = filter(list, predicates);

    a++

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Points : 968
    Points
    968
    Par défaut
    Citation Envoyé par maccormick Voir le message
    Mais ne marche pas avec des ET car à la fin de ta boucle, lorsque tu rejettes le message, il ne faut pas le rejeter, mais re-tester avec les autres critères, ce qui ajoute tous ces if à la queue leu leu. De même si le critère associé est vrai, il faudra quand même tester avec les autres critères si ceux-ci sont sélectionnés !
    Si tu rejettes le message au premier critère faux, tu te retrouves avec le comportement d'un ET logique (vu que pour accepter le message, tout doit être vrai, s'il y a un faux, on met a la trappe).
    Pour faire un OU, il aurai fallu faire un 'si critère VRAI alors accepter le message, passer au message suivant'.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par math_lab Voir le message
    Si tu rejettes le message au premier critère faux, tu te retrouves avec le comportement d'un ET logique (vu que pour accepter le message, tout doit être vrai, s'il y a un faux, on met a la trappe).
    Pour faire un OU, il aurai fallu faire un 'si critère VRAI alors accepter le message, passer au message suivant'.
    Oui, j'avais dû comprendre que le tableau de booleens incluaient aussi les critères non sélectionnés, ce que ton algo laisse penser puisque tu mets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    pour chaque booléen:
        si le booléen est VRAI
    Mais je ne saisi toujours pas où, c'est à dire dans quelle partie de l'algo, tu acceptes le message ...

    Par contre, ça me fait penser qu'en adaptant ton algo et en faisant :
    - un tableau de tous les critères sélectionnés (qui aura donc comme taille le nombre de critères sélectionnés)
    - à chaque test du critère associé, si le test est réussi, j'incrémente un compteur
    - à la fin, si mon compteur est égal à la taille de mon tableau, je peux accepter le message
    ça doit marcher ça non ?

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 190
    Points : 153
    Points
    153
    Par défaut
    Tu as 10 critères et toutes les combinaisons sont possibles (soit 1024 cas différents).

    Je rejoins donc l'idée de math_lab: les énumérer automatiquement puis selon les besoins choisir celle dont tu as besoin.

  10. #10
    Membre éprouvé
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Points : 968
    Points
    968
    Par défaut
    Citation Envoyé par maccormick Voir le message
    Mais je ne saisi toujours pas où, c'est à dire dans quelle partie de l'algo, tu acceptes le message ...
    Le message est accepté après le passage en revue des critères. Dans mon pseudo-code, ça se fait sans vérifier quoi que ce soit parce que je pars du principe que tu peux sauter directement au message suivant, ce peut être un peu crade dans un vrai code. Mais en gros, tu as juste a faire un booléen du genre 'accepter' qui est a true avant de gérer les critères, et qui passe a false quand un critère n'est pas respecté.

    Citation Envoyé par maccormick Voir le message
    Par contre, ça me fait penser qu'en adaptant ton algo et en faisant :
    - un tableau de tous les critères sélectionnés (qui aura donc comme taille le nombre de critères sélectionnés)
    - à chaque test du critère associé, si le test est réussi, j'incrémente un compteur
    - à la fin, si mon compteur est égal à la taille de mon tableau, je peux accepter le message
    ça doit marcher ça non ?
    Oui, ça revient au même. Tu peux te faire une classe abstraite qui n'a qu'une fonction renvoyant un boolean en fonction d'un message et ensuite spécifier la classe pour chaque critère. Apres, tu te fais ton tableau de critères et tu passes ton message a ses elements.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    @adiguba : ouah, je suis bluffé, je ne connaissais pas les predicates ! c'est LA solution la plus évolutive selon moi ! je m'y mets de suite !
    @+

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    @LGnord et @math_lab : merci les gars, votre solution est très bien aussi, mais je vais d'abord essayer la solution "méthode" de adiguba !
    @+

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par maccormick Voir le message
    @adiguba : ouah, je suis bluffé, je ne connaissais pas les predicates ! c'est LA solution la plus évolutive selon moi ! je m'y mets de suite !
    @+
    c'est déconcertant une simplicité pareille !!
    merci encore adiguba !!!

  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
    N'oublies pas que Google Guava (ou d'autres librairies) implémente déjà cela (en plus complet) via la classe Predicates et la méthode Collections2.filter()


    a++

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    N'oublies pas que Google Guava (ou d'autres librairies) implémente déjà cela (en plus complet) via la classe Predicates et la méthode Collections2.filter()


    a++
    j'imagine qu'elles apportent plein de trucs mortels ?
    parce que là ça marche tellement bien ...
    tellement bien qu'il va falloir que je reprenne pas mal de truc où je me suis pris la tête pour rien ....

  16. #16
    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
    Google Guava comporte "beaucoup beaucoup beaucoup" d'autre chose qui pourrait être utile...



    Concernant les Predicates tu as notamment la gestion des OR et d'autres truc basiques dans la classe Predicates.

    Mais c'est du concept. Quand on y regarde bien il n'y a rien de bien méchant là dedans. Si la dépendance est problématique ce n'est pas ce qu'il y a de plus dur à implémenter.


    a++

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Google Guava comporte "beaucoup beaucoup beaucoup" d'autre chose qui pourrait être utile...



    Concernant les Predicates tu as notamment la gestion des OR et d'autres truc basiques dans la classe Predicates.

    Mais c'est du concept. Quand on y regarde bien il n'y a rien de bien méchant là dedans. Si la dépendance est problématique ce n'est pas ce qu'il y a de plus dur à implémenter.


    a++
    Juste un petit truc encore : aurais-tu un petit exemple d'utilisation comme l'exemple du tableau de predicate que tu m'as donné, mais avec ceux de guava ? Merci d'avance car il n'y a vraiment pas grand chose sur le net ...

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

Discussions similaires

  1. remplacement " concept dossiers et arborescence "
    Par gblassel dans le forum Windows 8
    Réponses: 10
    Dernier message: 16/10/2013, 22h57
  2. Remplacer un terme par un concept
    Par hanadi_09 dans le forum Web sémantique
    Réponses: 1
    Dernier message: 27/01/2012, 18h01
  3. Quels motifs de conception en remplacement de l'héritage multiple ?
    Par Neuromancien2 dans le forum Débats sur le développement - Le Best Of
    Réponses: 26
    Dernier message: 16/06/2011, 01h50
  4. [Conception] en remplacement de fopen
    Par Skeud007 dans le forum PHP & Base de données
    Réponses: 37
    Dernier message: 05/10/2006, 15h48
  5. [Conception] Remplacer des frames par du code PHP !!!!
    Par dragonfly dans le forum PHP & Base de données
    Réponses: 20
    Dernier message: 07/04/2006, 08h54

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