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 :

Gros problème de conception : référence croisée


Sujet :

Java

  1. #1
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut Gros problème de conception : référence croisée
    Bonsoir,

    Tout d'abord, je sais pas vraiment si ça s'appelle bien des références croisées, mais je pense que ca lui va bien.

    Je suis en train de développer une application en utilisation le MVC, même le M(VC)C. C'est à dire que j'ai aussi un contrôleur purement Swing (ActionController) qui gère les actions des mes interfaces et un contrôleur de la vue générique (Controller).

    Voilà mon problème : Au début de mon programme, je demande à mon programme de charger toutes les actions du programme.

    Voilà en épuré la classe qui va faire cela :

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public class ActionControllerManager {
    	private static ArrayList<ActionController> controllers = null;
    	private static MyLogger logger = MyLoggerFactory.getLogger(ActionControllerManager.class);
     
    	static {
    		controllers = new ArrayList<ActionController>();
     
    		controllers.add(new AboutActionController());
    		controllers.add(new ConfigActionController());
    		controllers.add(new StatsActionController());
    		controllers.add(new FilmActionController());
    		controllers.add(new JThequeActionController());
    	}
     
    	/**
             * Retourne un controlleur en fonction du type passé en paramètre
             * @param controllerType Le type de controlleur voulu
             * @return Le controlleur adéquat
             */
    	public static ActionController getController(int controllerType){
    		logger.debug("Get controller " + controllerType);
    		for(ActionController controller : controllers){
    			if(controller.canControl(controllerType)){
    				logger.debug("Return controller " + controller);
    				return controller;
    			}
    		}
     
    		logger.debug("Controller not found, return null");
     
    		return null;
    	}
     
    	/**
             * Charge toutes les actions des différents controlleurs
             * @throws ActionLoaderException Cette exception est levée s'il y a eu une erreur durant le chargement des 
             * actions
             */
    	public static void loadAllActions() throws ActionLoaderException{
    		for(ActionController controller : controllers){
    			boolean good = controller.loadActions();
     
    			if(!good){
    				ActionLoaderException exception = 
    					new ActionLoaderException("Les actions n'ont pas pu être chargées correctement");
     
    				if(controller.getException() != null){
    					exception.initCause(controller.getException());
    				}
     
    				throw exception;
    			}
    		}
    	}
    }
    Le problème c'est que lorsqu'il éxécuter la méthode loadAction de AboutActionActionController, ca va appeller le constructeur d'une action (AcDisplayLicence) qui lui va utiliser ControllerFactory :

    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 ControllerFactory {
    	private static ArrayList<Controller> controllers = null;
     
    	static {
    		controllers = new ArrayList<Controller>();
     
    		controllers.add(new JThequeController());
    		controllers.add(new UpdateController());
    	}
     
    	public static Controller getController(int controllerType){
    		for(Controller controller : controllers){
    			if(controller.canManage(controllerType)){
    				return controller;
    			}
    		}
     
    		return null;
    	}
    }
    Voici le code de AcDisplayLicence :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class AcDisplayLicence extends MyAction {
    	private static final long serialVersionUID = -5130253480109588863L;
     
    	private LicenceController controller = 
    		(LicenceController)ControllerFactory.getController(Constantes.Controllers.LICENCE);
     
    	public void actionPerformed(ActionEvent e) {
    		controller.displayView();
    	}
    }
    Malheureusement, le fait d'initialiser JThequeController initialise aussi l'interface graphique et cette interface a besoin de JThequeActionController pour récupérer les actions, malheureusement, a ce moment là de l'éxécution, la méthode loadAction n'es pas encore lancée, je récupère donc logiquement des actions encore nulles et mon interface graphique est toute vide...

    Je sais pas si j'ai été bien clair, en plus le problème est assez compliqué... Mais quelqu'un aurait-il une idée ? Parce que là, j'ai un peu de peine... Mais je vais continuer à chercher.

    Merci

  2. #2
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Bon, j'ai trouvé une parade, il suffit de ne pas initialiser tout de suite mon Controller, mais à la première utilisation. Je suis sûr que les actions ne pourront pas être éxécutés avant la fin de la création de l'interface graphique donc c'est bon.

    Donc, il faudrai que je fasse ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class AcDisplayLicence extends MyAction {
    	private static final long serialVersionUID = -5130253480109588863L;
     
    	public void actionPerformed(ActionEvent e) {
    		ControllerFactory.getController(Constantes.Controllers.LICENCE).displayView();
    	}
    }
    Mais je pense qu'un problème pareil traduit tout de même un problème de conception...

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    D'une maniere générale, ce n'est pas tres bon de faire toutes les initialisations dans les blocs static, parce que :
    - tu ne controles pas l'ordre d'execution de ces blocs
    - la gestion des erreurs (et des exceptions) est plus compliquée, alors que c'est en général simple à faire dans le main.

    C'est un peu la même chose avec les constructeurs. Si il y a beaucoup de choses à faire, il vaut mieux ajouter une methode d'initialisation. Le constructeur ne se charge de ne faire que le strict minimum.

  4. #4
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Citation Envoyé par Sanguko
    D'une maniere générale, ce n'est pas tres bon de faire toutes les initialisations dans les blocs static, parce que :
    - tu ne controles pas l'ordre d'execution de ces blocs
    - la gestion des erreurs (et des exceptions) est plus compliquée, alors que c'est en général simple à faire dans le main.

    C'est un peu la même chose avec les constructeurs. Si il y a beaucoup de choses à faire, il vaut mieux ajouter une methode d'initialisation. Le constructeur ne se charge de ne faire que le strict minimum.
    Je suis assez d'accord avec, c'est en effet plus propre avec une méthode qui va initialiser le tout, mais l'avantage c'est qu'avec un bloc static, tu es sûr que ce soit initialisé dès qu'on utilise la classe alors que dans le cas d'une méthode tu dépends plus du code. Mais ca ne résouds pas mon problème...

  5. #5
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Citation Envoyé par Sanguko
    - tu ne controles pas l'ordre d'execution de ces blocs
    Ah bon ?
    Il y a une question dans le bouquin d'entrainement à la certif SCJP qui porte sur l'ordre d'exécution de blocs statics, non statics et du constructeur et la réponse n'est pas "impossible à déterminer". Ca dépendrait de la JVM sinon ?

  6. #6
    Membre expérimenté Avatar de g0up1l
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 341
    Par défaut
    le fait d'initialiser JThequeController initialise aussi l'interface graphique
    Comment un contrôleur peut-il intitialiser une interface graphiqe ?

    Normalement,c'est ton manager qui doit construire ton contrôleur, ton IHM et ton document puis effectuer les branchements: vue -> doc, vue->contrôleur et contrôleur->doc.

  7. #7
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Citation Envoyé par g0up1l
    Comment un contrôleur peut-il intitialiser une interface graphiqe ?

    Normalement,c'est ton manager qui doit construire ton contrôleur, ton IHM et ton document puis effectuer les branchements: vue -> doc, vue->contrôleur et contrôleur->doc.
    C'est intéressant ce que tu me dis là

    En fait, dans le constructeur du contrôleur, je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    setView(new JFrameJTheque());
    Toi tu le ferais ou alors ?


  8. #8
    Membre expérimenté Avatar de g0up1l
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 341
    Par défaut
    Popopop !

    Ce n'est pas à ton contrôleur d'initialiser les composants de l'IHM. D'ailleurs, il ne sait même pas qu'il y a une IHM !

    Il faut que tu aies une sorte de Manager ( ça peut-être dans le main ) qui se charge d'instancier les 3 parties du MVC ( Model-Vue-Contrôleur ) puis qui fasse les relations.

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    Citation Envoyé par natha
    Ah bon ?
    Il y a une question dans le bouquin d'entrainement à la certif SCJP qui porte sur l'ordre d'exécution de blocs statics, non statics et du constructeur et la réponse n'est pas "impossible à déterminer". Ca dépendrait de la JVM sinon ?
    Je suis d'accord que l'ordre entre bloc static, non static et constructeur est deterministe.

    Mais est ce que tu es capable de donner l'ordre d'execution entre plusieurs blocs static ?
    Par exemple si tu as
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class A {
     static {
        ...
     } 
    }
    class B {
     static {
       ...
     } 
    }
    qui s'execute avant qui ?

    Je pense qu'il n'y a pas de réponses simples, mais si tu as des explications, je suis preneur.

  10. #10
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Citation Envoyé par Sanguko
    qui s'execute avant qui ?
    Je pense qu'il n'y a pas de réponses simples, mais si tu as des explications, je suis preneur.
    Je ne m'y connais pas des masses, mais je pense passer la certif cette année alors j'ai fait le test du java.developpez.com ici :
    http://brabant.developpez.com/java/c...ions/factices/
    Tu vas à la question 3 (2.3)
    Bon il n'y a pas de bloc static dans Oiseau mais à priori s'il y en avait ils seraient exécutés avant ceux de Rapace.

    Désolé pour le Hors Sujet wichtounet...

  11. #11
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    Je suis allé me renseigner à la source
    Dans ce paragraphe "12.4 Initialization of Classes and Interfaces" est expliqué l'ordre et les conditions de déclenchement de l'execution des blocs static.
    Je ne vais pas paraphraser ce qui y est ecrit, je vous copie quelques exemples, pour vous mettre l'eau à la bouche :
    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
    class Super {
    	static { System.out.print("Super "); }
    }
    class One {
    	static { System.out.print("One "); }
    }
    class Two extends Super {
    	static { System.out.print("Two "); }
    }
    class Test {
    	public static void main(String[] args) {
    		One o = null;
    		Two t = new Two();
    		System.out.println((Object)o == (Object)t);
    	}
    }
    print :Super Two false
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Super { static int taxi = 1729; }
    class Sub extends Super {
    	static { System.out.print("Sub "); }
    }
    class Test {
    	public static void main(String[] args) {
    		System.out.println(Sub.taxi);
    	}
    }
     
    prints only:1729
    Tout ceci est deterministe, même s'il n'est effectivement pas simple de prédire comment vont être executés les blocs static. Sauf si on ajoute par dessus le multithreading ...(et a priori, on est dans ce cas avec AWT/SWING).

    Pour revenir au probleme originel, je vote (c'est la saison en France), pour la soluce de g0up1l.

  12. #12
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Vous inquietez pas pour le Hors-Sujet, c'est très intéressant tout ça

    Pour ce qui est de la séquence d'initialisation, tu as en effet, je vais changer ça

    à tous

    Si d'autres personnes ont un conseil sur mon architecture, n'hésitez pas

  13. #13
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Citation Envoyé par Sanguko
    [...]
    Bonne nouvelle
    C'est quand même bien plus pratique que ça soit déterministe.
    Ca serait même dangereux que ça ne le soit pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Toto {
        String toto;
        static {
             toto = "ici";
        }
    }
    class Tata extends Toto {
        String tata;
        static {
             tata = toto;
        }
    }
    On serait bien embêté si le bloc static de Tata s'exécutait en premier...

  14. #14
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    Citation Envoyé par natha
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Toto {
        String toto;
        static {
             toto = "ici";
        }
    }
    class Tata extends Toto {
        String tata;
        static {
             tata = toto;
        }
    }
    On serait bien embêté si le bloc static de Tata s'exécutait en premier...
    Note quand meme que les references circulaires sont possibles. Par exemple, on peut avoir
    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
    class Toto {
    	static String toto;
    	static String toto_2;
    	static {
    		toto_2 = Tata.tata;
    		System.out.println("toto_2 = "+toto_2);
    		toto = "ici";
    	}
    }
     
    class Tata extends Toto {
    	static String tata;
    	static {
    		tata = toto;
    	}
    }

  15. #15
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Citation Envoyé par Sanguko
    Note quand meme que les references circulaires sont possibles. Par exemple, on peut avoir
    C'est juste. Je n'ai pas pensé qu'on pouvait faire ça...
    Comme quoi il faut garder un minimum de bon sens quand on modélise ses classes

Discussions similaires

  1. Problème de déclaration avec références croisées
    Par lpierard dans le forum Débuter
    Réponses: 2
    Dernier message: 20/11/2009, 16h10
  2. problème de conception de requête croisée
    Par funkyjul dans le forum Développement
    Réponses: 2
    Dernier message: 24/10/2008, 09h43
  3. [Template] problème de références croisées
    Par ded jay dans le forum C++
    Réponses: 3
    Dernier message: 24/08/2008, 16h20
  4. Problème de référence croisée
    Par Nyphel dans le forum C++
    Réponses: 10
    Dernier message: 18/04/2007, 15h23
  5. Gros Problème avec DirectShow et la méthode RELEASE
    Par Olivier Delmotte dans le forum DirectX
    Réponses: 3
    Dernier message: 10/03/2003, 19h10

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