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

avec Java Discussion :

Architecture programme JAVA


Sujet :

avec Java

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 64
    Points : 46
    Points
    46
    Par défaut Architecture programme JAVA
    Bonjour à tous, étant novice dans le développement JAVA, je souhaiterai avoir votre avis sur l'architecture de mon programme.

    J'ai développé quelques petites applications en PHP+MySQL avec le modèle MVC. Dans la couche Métier, je m'étais tous ce qui était interrogation de la base de données, la vue correspondait à l'IHM et le contrôleur faisait le lien entre les 2.

    Je ne sais pas trop comment mettre en place un contrôleur dans une application locale développé en JAVA. J'ai toujours ma couche métier qui me permet de communiquer avec la BDD, mais pour l'instant c'est ma vue qui fait office en même temps de contrôleur.
    Chaque vue interroge indépendamment la couche métier et affiche le résultat à l'écran.

    J'ai du mal à trouver des tutoriaux sur l'architecture d'un programme en JAVA. Pour l'instant voici comment je m'organise, à l'ouverture de mon programme, je crée ma JFrame (mon pseudo contrôleur) dans laquelle j'instancie les différentes vues (dans mon cas les JPanel).
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    public class Controler extends JFrame {
     
    	public Controler() {
    		super();
     
    		// Menu Animal
    		JMenuItem itemChien = new JMenuItem("Chien");
    		itemChien.addActionListener(new ChienListener());
    		JMenuItem itemChat = new JMenuItem("Chat");
    		itemChat.addActionListener(new ChatListener());
     
    		JMenu menuAnimal = new JMenu("Animal");
    		menuAnimal.add(itemChien);
    		menuAnimal.add(itemChat);
     
    		// Menu Véhicule
    		JMenuItem itemVoiture = new JMenuItem("Voiture");
    		itemVoiture.addActionListener(new VoitureListener());
     
    		JMenu menuVehicule = new JMenu("Véhicule");
    		menuVehicule.add(itemVoiture);
     
    		// Menu général
    		JMenuBar menuGlobal = new JMenuBar();
    		menuGlobal.add(menuAnimal);
    		menuGlobal.add(menuVehicule);
     
    		this.setTitle("Mon programme");
    		this.setJMenuBar(menuGlobal);
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		this.setPreferredSize(new Dimension(1024, 768));
    		JFrame.setDefaultLookAndFeelDecorated(true);
     
    		this.pack();
    		this.setExtendedState(MAXIMIZED_BOTH);
    		this.setLocationRelativeTo(null);
    		this.setVisible(true);
    	}
     
     
    	// EVENEMENT
    	class ChienListener implements ActionListener	{
    		public void actionPerformed(ActionEvent e) {
    			getContentPane().setVisible(false);
    			getContentPane().removeAll();
    			getContentPane().add(new PanelChien());
    			getContentPane().setVisible(true);
    		}
    	}
     
    	class ChatListener implements ActionListener	{
    		public void actionPerformed(ActionEvent e) {
    			getContentPane().setVisible(false);
    			getContentPane().removeAll();
    			getContentPane().add(new PanelChat());
    			getContentPane().setVisible(true);
    		}
    	}
     
    	class VoitureListener implements ActionListener	{
    		public void actionPerformed(ActionEvent e) {
    			getContentPane().setVisible(false);
    			getContentPane().removeAll();
    			getContentPane().add(new PanelVoiture());
    			getContentPane().setVisible(true);
    		}
    	}
    }
    Je voudrais avoir votre avis sur ce code qui est propre à ma façon de procéder. Pouvez vous me donner des exemples, des conseils ou des liens pour la mise en place de mon conteneur principal?

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    940
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 940
    Points : 1 817
    Points
    1 817
    Par défaut
    Personnellement, je divise l'interface graphique en éléments. Pour chaque élément, je crée une classe vue et une classe contrôleur.

    La vue contient tous les composants Swing, tout ce qui concerne l'apparence de l'application, et rien de ce qui concerne son comportement.

    Le contrôleur ne contient pas une seule classe Swing, rien de ce qui concerne l'apparence, et tous les comportements.

    Une vue ne peut jamais communiquer qu'avec son propre contrôleur. La seule exception : une vue peut être transmise à une autre vue si elle doit être affichée à l'intérieur de celle-ci. Elle ne peut l'être que par l'intermédiaire des contrôleurs de ces deux vues.
    Le contrôleur appelle une fonction de la vue chaque fois qu'un changement d'affichage est nécessaire.
    Tous les listeners dans la vue appellent une méthode du contrôleur pour le prévenir.

    Exemple :
    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
    public class Controller {
     
    	private View view;
     
    	public Controller() {
    		view = new View();
    	}
     
    	public void notifyDog() {
    		view.displayDogPanel();
    	}
     
    	// ...
    }
     
    public class View extends JFrame {
     
    	private Controller controller;
     
    	public View(Controller controller) {
    		assert controller != null;
    		this.controller = controller;
    		initialize();
    	}
     
    	private void initialize() {
    		// Menu Animal
    		JMenuItem itemChien = new JMenuItem("Chien");
    		itemChien.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e) {
    				controller.notifyDog();
    			}
    		});
     
    		// ...
    	}
     
    	public void displayDogPanel() {
    		getContentPane().setVisible(false);
    		getContentPane().removeAll();
    		getContentPane().add(new PanelChien());
    		getContentPane().setVisible(true);
    	}
     
    	// ...
    }
    (Code non testé.)

    C'est la méthode que j'utilise et qui marche assez bien. Il y en a d'autres.

    Dans la pratique, j'utilise également des interfaces IView et IController pour toutes les vues et contrôleurs. Les contrôleurs ont une méthode getView utilisée exclusivement quand une vue doit être transmise pour être affichée comme élément d'une autre. Cela signifie généralement que les contrôleurs de ces deux vues communiquent.

    J'insiste : une vue ne peut jamais communiquer qu'avec son propre contrôleur, et seul le contrôleur d'une vue peut communiquer avec elle. Si un autre élément souhaite modifier le contenu d'une vue, il doit s'adresser à son contrôleur.

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 64
    Points : 46
    Points
    46
    Par défaut
    Merci pour ta réponse rapide et très complète. J'ai bien compris ton explication mais la mise en place d'une telle architecture me parais assez complexe à mettre en place dans un premier temps.

    Je me suis posé cette question car je fais face à une difficulté dans mon programme. J'ai une fenêtre modale qui s'ouvre via la barre de menu de l'application. Lorsque j'effectue une action à l'intérieur de cette fenêtre modale, je voudrais appeler une méthode du ContentPane de la fenêtre mère pour que celui-ci se rafraîchisse.

    Le problème est que je ne sais pas quel est le ContentPane actif dans la fenêtre mère, surement du à une mauvaise conception dans mon architecture.

    La couche métier ne me pose pas de problème particulier, j'y mets tout ce qui concerne la connexion à ma base de données et le modèle de mes tables.

    Pour le reste j'avoues que cela reste encore très flou, voici un exemple d'un JPanel que j’instancie dans la fenêtre principale.
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    @SuppressWarnings("serial")
    public class PanelChien extends JPanel {
       private JTextField txtSearchValue;
       private JButton btnSearchValue;
       private JTable tblChien;
     
     
       // CONSTRUCTEUR
       public PanelChien() {
          super();
     
          this.txtSearchValue = new JTextField();
          this.btnSearchValue = new JButton();
          this.btnSearchValue.addActionListener(new BtnSearchValueListener());
          this.tblChien = new JTable();
     
          // création des panels
          JPanel panFiltre = new JPanel();
          panFiltre.setLayout(new FlowLayout(FlowLayout.CENTER));
          panFiltre.add(this.txtSearchValue);
          panFiltre.add(this.btnSearchValue);
     
          JPanel panCentre = new JPanel();
          panCentre.setLayout(new BorderLayout());
          panCentre.add(new JScrollPane(this.tblChien));
     
          // ajoute les panels sur la fenêtre
          this.setLayout(new BorderLayout());
          this.add(panFiltre, BorderLayout.NORTH);
          this.add(panCentre, BorderLayout.CENTER);
     
          this.initTableChien();
       }
     
       private void initTableChien() {
          try {			
             // ouvre la connexion a la BD
             Connex connex = new Connex();
    	 ConnexChien connexchien = new ConnexChien(connex);
    	 Vector<tblChien> vChien = ConnexChien.vChien(txtSearchValue.getText());
             connex.closeConnex();
     
             // initialise le header et les datas du tableau
             Vector<Vector<Object>> vDatas = new Vector<Vector<Object>>();
    	 Vector<Object> vHeader = new Vector<Object>();
    	 vHeader.addElement("Identifiant");
    	 vHeader.addElement("Nom");
    	 vHeader.addElement("Race");
     
             int lastRow = vChien.size();
    	 for (int i = 0; i < lastRow; i++) {
    	    Vector<Object> vCol = new Vector<Object>();
    	    tblChien chien = vChien.elementAt(i);
     
    	    vCol.add(chien.getIdchien());
    	    vCol.add(chien.getNomchien());
    	    vCol.add(chien.getRaceChien());
     
    	    vDatas.add(vCol);
             }			
     
             // mise à jour de la Jtable chien
             tblChien.setModel(new DefaultTableModel(vDatas, vHeader));
          }
          catch (SQLException e) {
             JOptionPane.showMessageDialog(this, "Erreur SQL : " + e.getMessage(), "Attention !!!", JOptionPane.ERROR_MESSAGE);
          }	
          catch (Exception e) {
             JOptionPane.showMessageDialog(this, "Erreur interne : " + e.getMessage(), "Attention !!!", JOptionPane.ERROR_MESSAGE);
          }
       }
     
     
       // EVENEMENT
       class BtnSearchValueListener implements ActionListener {
          @Override
          public void actionPerformed(ActionEvent e) {
             initTableChien();
          }
       }
    }
    Si quelqu'un connais un bon tutoriel sur l'architecture MVC, je suis preneur, car je comprends assez vite mais il faut m'expliquer longtemps.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    940
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 940
    Points : 1 817
    Points
    1 817
    Par défaut
    Ca n'a rien de complexe, comme souvent, c'est juste une question de discipline.

    Dans ton cas, je discerne les éléments suivants :
    - la fenêtre principale, avec notamment une barre de menu,
    - une fenêtre modale,
    - plusieurs ContentPane, tous à l'intérieur de la fenêtre principale, dont l'un est actif.

    On aurait donc :
    - un couple MainController, MainView pour la fenêtre principale,
    - un couple ModalController, ModalView pour la fenêtre modale,
    - un couple Content1Controller, Content1View, puis Content2Controller etc... pour chacun des ContentPane.

    D'après les comportements que tu as décris, on peut en déduire que :
    - MainController dispose d'une référence vers tous les ContentController, puisque les éléments correspondant s'affichent à l'intérieur. (Dans 99% des cas, les applications s'affichent dans une fenêtre. Cette fenêtre devient toujours l'élément "principal".)
    - Tous les ContentController disposent d'une méthode getView. En appelant cette méthode, le MainController peut passer les ContentViews (les ContentPane) à sa propre vue (probablement une JFrame), ainsi les ContentPane s'affichent dans la fenêtre principale.
    - MainView dispose de méthodes setSubView, grâce auxquelles MainController peut transférer les ContentViews.
    - MainController dispose également d'une référence à ModalController. Ceci lui permet de demander d'afficher ou de cacher la fenetre modale quand on clique dans la barre de menu.
    - ModalController dispose d'une référence vers MainController, afin de l'avertir des actions nécessitant un rafraichissement.

    Le scénario que tu demandes est alors logique à programmer.
    - L'utilisateur clique sur un composant.
    - ModalView en est avertie par la méthode actionPerformed d'un de ses listeners.
    - L'événement est transmis à ModalController via une methode prévue à cet effet.
    - ModalController n'a pas à gérer les ContentPane, ce n'est pas on boulot. Il transmet donc à son tour vers MainController.
    - MainController doit gérer les ContentPanes, puisqu'ils sont "à l'intérieur" de lui. Mais pas directement: les ContentPanes ont leur propres contrôleurs. Ca tombe bien : on avait justement dit que MainController devait avoir les références vers ces contrôleurs. Il n'a qu'à à nouveau transférer l'événement au ContentController actif. (Ou, si ce n'est pas lui qui sait si tel ou tel ContentController sont actifs, tous les appeller. A leur charge de ne se rafraîchir que si ils sont actifs.)

    Voici un tutorial MVC avec Swing : http://baptiste-wicht.developpez.com...ion/mvc/#LII-A. Ce n'est pas tout à fait ma méthode mais c'est clair.

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 64
    Points : 46
    Points
    46
    Par défaut
    Merci beaucoup pour toutes ces explications. Cela me parait un peu plus clair.
    Dans tous les cas cela demande une grande rigueur et une très bonne organisation.

    Une telle architecture est je pense primordiale pour une application web mais dans mon cas, c'est une application locale en JAVA. Dans tous les cas, je souhaite prendre de bonnes habitudes dès le départ (perdre les mauvaises va être le plus gros du travail).

    Merci encore pour tous ces conseils, je vais essayer de les mettre en pratique.

    ++

  6. #6
    Membre actif
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 130
    Points : 276
    Points
    276
    Par défaut
    Citation Envoyé par RomG7 Voir le message

    Une telle architecture est je pense primordiale pour une application web mais dans mon cas, c'est une application locale en JAVA.
    L'architecture est dans tout les cas primordiale, que ce soit pour une appli web, une appli locale, et même un batch.

    Une archi bien pensée, et claire, permet une meilleure implémentation, et au final, une meilleure maintenance.
    MigouW

    La seule bataille perdue d'avance est celle que l'on refuse de livrer.


    Pensez au tag
    Ma réponse vous a été utile, votez plus 1 sur le message.
    Ma réponse est hors sujet, votez moins 1 sur le message.

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

Discussions similaires

  1. [Avis] Les meilleurs programmes Java ?
    Par christopheJ dans le forum ImageJ
    Réponses: 69
    Dernier message: 07/10/2008, 01h12
  2. [Débutant] [Thread] Faire patienter un programme java....
    Par yoxx dans le forum Concurrence et multi-thread
    Réponses: 3
    Dernier message: 25/09/2005, 12h36
  3. [Apis]parser les arguments d'un programme Java
    Par sacofan dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 06/08/2005, 14h32
  4. [votre avis m'interesse] Interface avec un programme Java
    Par LineLe dans le forum Interfaces Graphiques en Java
    Réponses: 29
    Dernier message: 11/12/2004, 11h39
  5. Lancement d'un programme java depuis un script php
    Par gexti dans le forum Développement Web en Java
    Réponses: 8
    Dernier message: 07/05/2004, 17h40

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