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

 C++ Discussion :

Problème de conception : chargement de config


Sujet :

C++

  1. #21
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Merci encore koala01 pour tes précieux conseils

    Voici ma nouvelle proposition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class QNetworkFacade
    {
      public :
        QNetworkFacade();
        ~QNetworkFacade();
     
        bool Listen() const;
     
      private :
        QNetworkConfig* m_config;
        QUdpServer* m_udpServer;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    QNetworkFacade::QNetworkFacade()
      : m_config(new QNetworkConfig())
      , m_udpServer(new QUdpServer())
    {
      m_config->load(CFG_NETWORK);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bool QNetworkFacade::Listen() const
    {
      if (!m_udpServer)
        return false;
     
      return m_udpServer->bind(QHostAddress::LocalHost, m_config->m_port);
    }
    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
    class QUdpServer : public QObject
    {
      Q_OBJECT
     
      public :
        QUdpServer(QObject* parent = 0);
        ~QUdpServer();
     
        bool bind(const QHostAddress&, const quint16) const;
     
      private slots :
        void readData();
     
      private :
        void initConnections() const;
     
      private :
       QUdpSocket* m_socket;
    };
    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
    class QModuleConfig
    {
      public :
        virtual ~QModuleConfig();
        virtual bool load(const QString&) = 0;
     
      protected :
        bool loadDom(const QString&);
     
      template <typename T>
      bool getParam(const QString& key, T& value)
     {
        // Get param from dom and return error code
      }
     
      protected :
        QDomDocument* m_dom;
    };
     
    template<>
    bool QModuleConfig::getParam<ushort>(const QString&, ushort&);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class QNetworkConfig : public QModuleConfig
    {
      friend class QNetworkFacade;
     
      public :
        QNetworkConfig();
     
      protected :
        bool load(const QString&);
     
      private :
        quint16 m_port;
    };
    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
    const QString CFG_PARAM_PORT = "Port";
    const quint16 CFG_PARAM_PORT_DEFAULT = 5000;
     
    QNetworkConfig::QNetworkConfig()
      : QModuleConfig()
      , m_port(CFG_PARAM_PORT_DEFAULT) {}
     
    bool QNetworkConfig::load(const QString& file)
    {
      if (!loadDom(file))
        return false;
     
      getParam<ushort>(CFG_PARAM_PORT, m_port);
     
      return true;
    }
    J'ai toutefois un problème au niveau de mon objet QAppli. Quand je vais appeler Listen, je voudrais par exemple récupérer le buffer pour le décoder et construire un modèle qui sera utilisé par l'IHM..

    Je vais donc avoir un autre module Graphic, et un module pour décoder et construire mon modèle. Il faudrait donc que je créé un point d'entrée dans le module Network comme un pointeur de fonction en argument de la méthode Listen pour appeler la callback au moment voulu ?

    J'imagine qu'il faudra procéder de la sorte aussi entre le modèle et la vue, à savoir, passer éventuellement des callbacks ou des pointeurs pour les connecter ?

    Autre problème, dans ma spécialisation de template pour la méthode getParam dans QModuleConfig, je vois via l'intellisense que ma méthode getParam est publique (car spécialisation publique même si la méthode générique est censée être protégée). Est-ce normal ?

    Merci

  2. #22
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    C'est déjà beaucoup mieux
    J'ai toutefois un problème au niveau de mon objet QAppli. Quand je vais appeler Listen, je voudrais par exemple récupérer le buffer pour le décoder et construire un modèle qui sera utilisé par l'IHM..
    Ben, ce serait bien le rôle du module réseau que de créer / mettre à jour le modèle avec les données qu'il obtient au travers du client UDP, tu ne crois pas

    Ou, du moins de faire la "transition" entre les données telles qu'elles sont reçues sur le réseau et le module "métier" (le module qui contient les données spécifiques à ton application).

    Note qu'il peut parfaitement y avoir quelque chose "entre les deux" (un ou plusieurs module(s) "modèle" auxquels les autres modules viendraient se rattacher)

    Je vais donc avoir un autre module Graphic, et un module pour décoder et construire mon modèle.
    Tu dois, surtout, avoir un module "Model" qui s'occupe de fournir les modèles "à qui en a besoin", qui est sans doute le seul à manipuler les données métier (plusieurs façades distinctes sont envisageables) et qui fait le lien avec les données d'une part et les autres modules d'autre part.

    Au final, tu pourrais avoir quelque chose comme (désolé, ASCII art )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
              Reseau
               / \ // ???
                |
               \ /
              Model  -- >  Metier
               / \
                |
               \ /
              IHM
    (Les flèches indiquent le sens des communications entre les modules)

    En effet, le module "réseau" peut parfaitement être considéré comme "une vue particulière" dans le sens où elle n'est pas affichée mais... transmise sur le web

    Et, comme tu est (il me semble) sous Qt, tu dispose des QAbstractModel et autres joyeusetés du genre qui, justement, sont prévus pour fonctionner de concert.

    Tout ce que tu dois pouvoir passer au module réseau (et au module IHM), c'est un pointeur vers le modèle créé par le module Model, (le même modèle pour les deux, simplement "manipulé" et utilisé différemment)
    Il faudrait donc que je créé un point d'entrée dans le module Network comme un pointeur de fonction en argument de la méthode Listen pour appeler la callback au moment voulu ?
    Quelle horreur !!!

    Pourquoi faire des callbacks

    Tu fournis un pointeur (ou une référence) vers le modèle (dérivé de QAbstractModel) créé par le module Model (ou carrement une référence vers une partie de la façade de celui-ci, si tu veux que ce soit le module Model qui s'occupe réellement du modèle) et basta: ton module réseau et ton module IHM n'ont qu'à s'occuper d'appeler les fonctions qui vont bien, sur le modèle ou sur la façade vers le module Model (je préférerais utiliser la façade vers le module, ca évitera les problèmes liés à l'évolution des éléments )
    Autre problème, dans ma spécialisation de template pour la méthode getParam dans QModuleConfig, je vois via l'intellisense que ma méthode getParam est publique (car spécialisation publique même si la méthode générique est censée être protégée). Est-ce normal ?
    Ce n'est pas forcément "normal" (généralement l'intellisense sait la visibilité des différents membres d'une classe), mais c'est "possible"...

    Quoi qu'il en soit, ce n'est pas "catastrophique"

    Ceci dit, étant donné que seul le module aura connaissance de la configuration, pourquoi te faire ch...er à créer une amitié (de très mauvais aloi ici) et à placer ta fonction getParam dans l'accessibilité protégée

    Pourquoi ne pas virer cette amitié et la placer en accessibilité publique
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #23
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Ceci dit, étant donné que seul le module aura connaissance de la configuration, pourquoi te faire ch...er à créer une amitié (de très mauvais aloi ici) et à placer ta fonction getParam dans l'accessibilité protégée
    Effectivement, j'ai mis en public le paramètre port. Par contre, j'ai laissé en protégée la méthode getParam puisque je n'ai pas envie qu'on s'en sert de manière indirecte dans la façade à la place d'appeler les membres publics.

    Il me reste un petit problème sur la dépendance entre façades.
    Ici, je dois spécifier mon modèle (façade model) à ma vue (façade graphic). J'ai donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class QGraphicFacade : public Common::QFacade
    {
      public :
        QGraphicFacade();
        ~QGraphicFacade();
     
        void setModel(Model::QModelFacade*);
     
      private :
        QTraceTableView* m_traceTableView;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void QGraphicFacade::setModel(Model::QModelFacade* modelFacade)
    {
      if (!m_traceTableView)
        return;
     
    //    m_traceTableView->setModel( ??? );
    }
    En passant par les façades, je risque de me retrouver souvent dans le cas ou j'ai besoin de récupérer un objet de celle-ci pour faire des liaisons depuis une autre façade. Que faire ? Définir des accesseurs ? Une amitié ?

    Autre point, je me suis rendu compte que je n'utilisais pas les modules (Network, Graphic, Model) mais que c'est mes façades qui contiennent directement tous les objets nécessaires aux traitements des informations. Je m'y suis peut être mal pris mais dans mon cas, ajouter un niveau d'abstraction avec le module (déplacer tous les objets dans le module plutôt que de les laisser dans la façade) ajouterait une indirection supplémentaire et serait donc redondant. Un exemple de ce que j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bool QNetworkFacade::listen() const
    {
      if (!m_udpServer) // objet défini dans la façade et non dans le module QNetwork
        return false;
     
      return m_udpServer->bind(QHostAddress::LocalHost, m_config->m_port);
    }
    Merci

  4. #24
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par koala01 Voir le message

    Or, une variable statique n'est jamais qu'une variable globale "Facon du chef, enrobée d'accessibilité sur lit de mystère, avec sa sauce OO"
    c'est tout à fait exact

  5. #25
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait, l'idée est, vraiment, de veiller à respecter scrupuleusement le D de SOLID qui est mis pour Dependency Inversion Principle, ou, si tu préfères en français, le principe d'inversion des dépendances.

    Autrement dit, chaque module ne doit exposer, au travers d'une façade, que le stricte nécessaire pour pouvoir être utilisé.

    Et, comme je te l'ai dit, le module "réseau" peut très facilement être considéré comme une "vue particulière", dans le sens où, tout ce qu'elle fait, c'est faire la transition entre des données externes (issues du réseau) à transmettre au modèle et des données internes (issues du modèle) à transmettre au réseau.

    Or, tu dispose d'un système génial pour faire communiquer les modèles avec les différentes vues : le système de signaux et de slots.

    La dépendance entre le module "modèles" et le module "réseau" peut donc être quasiment nulle.

    Je m'explique :

    Tu devrais avoir différents modules dont on pourrait dresser une liste proche de
    • Business : ce module ne contient que des données métier pures et dures
    • Modifications : ce module contient des données qui n'entrent pas tout à fait dans la définition de "données métier", mais qui permettent de manipuler et de modifier celles-ci (par exemple : l'identifiant d'un objet vendu et le prix obtenu lors de la transaction, l'identifiant du monstre attaqué et du sort (ou de l'arme) utilisé(e), ...)
    • Models : ce module contient les différents modèles que tu vas manipuler dans ton application
    • Views : ce module reprend l'ensemble des vue "graphiques" que tu feras afficher par ton application
    • Network : ce module s'occupe de gérer la connectivité avec le réseau.
    • Sound : ce module s'occupe de gérer tout l'aspect sonore de ton application.
    • Y en a peut être d'autres

    Comment va-t-il s'y prendre il va réagir à certains signaux qui sont émis par certains modules (essentiellement le module Network et le module Views).

    Comment pourra-t-il réagir à ces signaux en exposant au travers de sa façade un certain nombre de slots qui pourront être connectés aux différents signaux émis par les différents modules.

    Pour cet aspect spécifique, la façade du module Models se contente donc d'exposer les différents slots susceptibles d'intéresser les différents modèles et de faire la jonction entre ces slots exposés et les slots des modèles en question.

    D'un autre coté, les modifications apportées par le module Models au business sont, elles aussi, susceptibles d'occasionner l'émission de signaux, susceptibles d'intéresser des modules comme Network, Views ou sound.

    La façade de Models va donc exposer ces signaux "intéressants" (comprends : qui sont susceptibles d'intéresser d'autres modules que le module Models) et faire la jonction entre les signaux émis par les différents modèles et ces signaux exposés.

    La façade du module Sound exposera essentiellement des slots, correspondant aux différentes réactions sonores envisagées.

    La façade du module Network et celle du module Views exposera un certain nombre de slots qui seront connectés aux "signaux intéressants" (du point de vue du réseau) émis par le module Models afin de permettre l'émission des modifications apportées "en local" ainsi qu'un certain nombre de signaux -- auxquels viendront se connecter certains slots du module "Models" -- afin de permettre la prise en compte des informations reçues au travers du réseau.

    Enfin, il faut "juste" prendre en compte le fait que les vues "graphiques" sont généralement directement reliées à un modèle particulier.

    L'idée est donc peut être de faire en sorte que la façade de Views puisse permettre d'accéder à une vue particulière et que celle de Models puisse permettre de faire la relation entre une vue et le modèle à utiliser.

    Au final, tous les modules dépendent du module "Modifications" car ce ne sont que des "structures simples" qui représentent les modifications à apporter.

    La façade du module Models peut ressembler à quelque chose comme
    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
    class ModelsFacade{
        public:
           ModelsFacade(){
               createModels();
               connectSignals();
               connectSlots();
            }
            setModelToView(View * view, ModelId id) const{
                Model * model =/* trouver le modèle correspondant */;
                view->setModel(model);
            }
            /* peut être quelques autres fonctions utilitaires */
         signals :
             /* les différents signaux à exposer */
         public slots:
            /* les différents slots à exposer */
        private:
            void createModels(){
                /* on crée les modèles et on les ajoute à la map */
            }
            void connectSignals(){
                /* on connecte les signaux des différents modèles
                 * aux signaux exposés par la facade
                 */
            }
            void connectSlots(){
                /* on connecte les slots exposés par la façade aux
                 * slots des différents modèles
                 */ 
            }
            /* ce n'est qu'un exemple :D */
            std::map<ModelId, QAbstractModel *> allModels_;
            /* le fameux pimple idiome dont j'ai parlé plus haut */
            ModelsConfig * config_;
    };
    Pour le module Network, on exposerait essentiellement des signaux et des slots avec, peut être, une ou deux fonctions "utilitaires", sous une forme proche de
    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
    class NetworkFacade{
        public:
            NetworkFacade(){
                createConnection();
            }
            /* peut être une ou deux fonctions utilitaires ici */
        signals :
            /* les différents signaux susceptibles d'être émis */
        public slots :
           /* les différents slots de réaction intéressants */ 
        private:
            NetworkConnection connection_;
            /* le fameux pimple idiome dont j'ai parlé plus haut */
            NetwokConfig * config_;
     };
    et la façade du module Views pourrait ressembler à quelque chose comme
    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
    class ViewsFacade{
        public:
            ViewFacade(){
                createViews();
                connectSignals();
                connectSlots();
            }
            View * getViewById(ViewId id){
                View * found = /* recherche de la vue identifiée par id */
                return found;
            }
        signals :
            /* les différents signaux exposés */
     
         signals :
             /* les différents signaux à exposer */
         public slots:
            /* les différents slots à exposer */
        private:
            void createView(){
                /* on crée les vues et on les ajoute à la map */
            }
            void connectSignals(){
                /* on connecte les signaux des différentes vues
                 * aux signaux exposés par la facade
                 */
            }
            void connectSlots(){
                /* on connecte les slots exposés par la façade aux
                 * slots des différents modèles
                 */ 
            }
            /* ce n'est qu'un exemple :D */
            std::map<ViewId, QAbstractView *> allView_;
            /* le fameux pimple idiome dont j'ai parlé plus haut */
            ViewsConfig * config_;
    };
    Et ton application pourrait parfaitement ressembler à quelque chose comme
    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
    class Application{
        public:
            Application(){
                setupViewModels();
                connectSignals();
             }
        private:
            void setupViewModels(){
                /* on récupère les différentes vues de View et on définit leur modèle
                 * au travers de models_.setModelToView */
            }
            void connectSignals(){
                /* on connecte les signaux émis par les différentes façades aux slots
                 * des façades intéressées 
                 */
            }
            ModelFacade models_;
            ViewFacade views_;
            NetworkFacade network_;
            SoundNetwork sound_;
    };
    Sous une telle forme, tes trois modules peuvent fonctionner de manière strictement autonome.

    Mieux encore, tu peux développer tes différents modules dans l'ordre que tu souhaites, y compris par "petit morceau", sans que cela n'influe en rien sur le fonctionnement du reste

    Bon, bien sur, il faudra toujours tenir compte du module Modifications qui est un module "central" (comprends : dont dépendent tous les autres) et du module Business lorsque tu développera ton module Models, mais ce sont les deux seuls points de liaison entre les différents modules auxquels tu devras être attentif.

    Elle est pas belle la vie
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #26
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Tout paraît plus facile avec tes explications .

    Juste deux points qui sont encore un peu flous :
    1) Le module Business contiendra uniquement la déclaration des données métiers c'est bien ça ?
    2) Le module Modifications n'est pas très clair pour moi. En fait, je ne vois pas bien son intérêt.

    Si je prends l'exemple de récupération de trames réseaux pour le remplissage d'un modèle de données, dois-je faire :

    a) Le module Network récupère les trames, les décode, envoie un signal avec les données décodés, signal qui est connecté à un slot d'un modèle du module Model (ou encore à un slot de la façade du module Model qui se charge de passer les informations aux modèles voulus).

    b) Le module Network récupère les trames, les décode, envoie un signal avec les données décodés, signal connecté à un slot qui met à jour une collection des données récupérées, qui, à sa mise à jour, prévient à son tour le modèle lié à cette collection (le modèle possède un pointeur sur la collection par exemple).

    Dans ces deux cas, je ne vois pas vraiment ou va intervenir le module Modification.

    Merci encore

  7. #27
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sfarc Voir le message
    Tout paraît plus facile avec tes explications .

    Juste deux points qui sont encore un peu flous :
    1) Le module Business contiendra uniquement la déclaration des données métiers c'est bien ça ?
    Et de "tout ce qui va bien pour les manipuler, oui.
    2) Le module Modifications n'est pas très clair pour moi. En fait, je ne vois pas bien son intérêt.
    Hé bien, pose toi la question de savoir ce que tu vas envoyer sur le réseau.

    Vas-tu systématiquement envoyer toutes tes données métiers

    Ou vas-tu plutôt envoyer uniquement les informations qui permettront de reproduire la modification qui a été apportée entre un instant T et l'instant T+1

    Il semble beaucoup plus logique de ne renvoyer que "ce qui a changé" entre T et T+1, et encore, pas forcément la donnée en entier mais juste la "différence" entre l'état de la donnée telle qu'elle était à l'instant T et l'état dans lequel elle se trouve à T+1.

    Cela te permettra de n'envoyer que le "stricte minimum" sur le réseau et d'éviter de le surcharger avec un tas d'informations dont le récepteur n'a que faire.

    C'est d'autant plus justifié que c'est, en gros, la manière de fonctionner des signaux et des slots très spécifiques : quand un signal indique que l'index sélectionné d'un combobox a été modifié, il envoie juste un signal selectedIndexChanged( nouvel index), et le slot qui gère ce signal sait comment réagir en conséquence
    Si je prends l'exemple de récupération de trames réseaux pour le remplissage d'un modèle de données, dois-je faire :

    a) Le module Network récupère les trames, les décode, envoie un signal avec les données décodés, signal qui est connecté à un slot d'un modèle du module Model (ou encore à un slot de la façade du module Model qui se charge de passer les informations aux modèles voulus).

    b) Le module Network récupère les trames, les décode, envoie un signal avec les données décodés, signal connecté à un slot qui met à jour une collection des données récupérées, qui, à sa mise à jour, prévient à son tour le modèle lié à cette collection (le modèle possède un pointeur sur la collection par exemple).

    Dans ces deux cas, je ne vois pas vraiment ou va intervenir le module Modification.
    Encore une fois, pose toi la question de ce que le module Network récupère comme trame.

    Il va récupérer des données, certes, mais il n'y a aucun sens à ce qu'il récupère à chaque fois l'ensemble des données métier, même si cela se limite au données métier modifiées.

    Il va juste obtenir la différence entre l'état des données métier à l'instant T et celui à l'instant T+1. Et il doit juste décoder cette différence.

    Et son rôle s'arrête là : à émettre un signal qui sera "porteur" de la différence à appliquer.

    Parce que c'est le rôle du module "Model" de s'assurer que cette différence est cohérente et d'appliquer cette différence au données métier.

    Et parce que c'est aussi ce qui va se passer au niveau graphique, en réactions aux différents événement comme le clique de la souris ou l'utilisation du clavier

    Maintenant, je parle de "module" de modifications à apporter, c'est eput etre un peu excessif.

    Ce peut très bien n'être que l'ensemble des types primitifs utilisés ... Tout comme ce peut être des structures qui donnent un sens particulier à ces types primitifs en fonction de la différence à appliquer
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #28
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Vas-tu systématiquement envoyer toutes tes données métiers

    Ou vas-tu plutôt envoyer uniquement les informations qui permettront de reproduire la modification qui a été apportée entre un instant T et l'instant T+1
    L'idée est vraiment de récupérer par le réseau des traces donc effectivement, une fois qu'une trace est reçue avec ses infos (message, ligne, fichier, type de trace, ...), elle est insérée dans une liste au niveau des données.
    D'ailleurs au passage, la communication est unilatérale (réseau -> appli) puisque c'est surtout une application d'affichage de données (traces ici).

    Pour la question sur le meilleur moyen de procédé, j'ai dû mal m'exprimer . Ce que je voulais en fait savoir, c'est, est-il mieux de découpler le modèle (QTableModel) des données (liste des traces) ou de tout regrouper dans le modèle au niveau du module Model ? Quand je parlais de signal envoyé par le module Network à la liste des traces, je comptais uniquement insérer la nouvelle trace et prévenir le modèle qui à un pointeur sur cette liste plutôt que de remettre à jour l'ensemble de la liste.

    Voici un exemple de ce que j'appelle couplage entre les donneés et le modèle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename T>
    class QDataTableModel : public QAbstractTableModel
    {
      protected :
        QList<const T*> m_data; // Directement au niveau du modèle
    };
    Parce que c'est le rôle du module "Model" de s'assurer que cette différence est cohérente et d'appliquer cette différence au données métier.
    Ici, tu as l'air de coupler la liste des traces directement au modèle concernant dans le module Model donc.

    Maintenant, je parle de "module" de modifications à apporter, c'est eput etre un peu excessif.

    Ce peut très bien n'être que l'ensemble des types primitifs utilisés ... Tout comme ce peut être des structures qui donnent un sens particulier à ces types primitifs en fonction de la différence à appliquer
    Mais pour moi les types primitifs sont déjà définis dans le module Business en fait.

  9. #29
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sfarc Voir le message
    L'idée est vraiment de récupérer par le réseau des traces donc effectivement, une fois qu'une trace est reçue avec ses infos (message, ligne, fichier, type de trace, ...), elle est insérée dans une liste au niveau des données.
    D'ailleurs au passage, la communication est unilatérale (réseau -> appli) puisque c'est surtout une application d'affichage de données (traces ici).
    Ah, oui, mais quand tu auras tout dit... je saurai tout

    Moi, je partais sur une application plus "mmo" qui implique une communication bidirectionnelle .

    Ceci dit, le principe reste toujours le même
    Pour la question sur le meilleur moyen de procédé, j'ai dû mal m'exprimer . Ce que je voulais en fait savoir, c'est, est-il mieux de découpler le modèle (QTableModel) des données (liste des traces) ou de tout regrouper dans le modèle au niveau du module Model ? Quand je parlais de signal envoyé par le module Network à la liste des traces, je comptais uniquement insérer la nouvelle trace et prévenir le modèle qui à un pointeur sur cette liste plutôt que de remettre à jour l'ensemble de la liste.
    La règle d'or, c'est que chaque élément doit avoir sa responsabilité propre.

    Si tu as "quelque chose" dont la responsabilité est de récupérer des données depuis le réseau, elle ne doit faire que ca, et envoyer les données "à qui de droit".

    "Qui de droit", en l'occurrence, c'est "quelque chose" qui est utilisé par le modèle, dont la responsabilité est de maintenir ces données "en place", vu que la responsabilité du modèle est la "communication interne" entre les données métiers d'une part et les différentes vues.

    Au final, le module Network "écoute" le réseau et décode les informations qu'il reçoit.

    Quand il a reçu une information, il émet un signal qui indique "j'ai reçu telle information (même si c'est toujours le même type d'info ), à vous de vous en occuper".

    Ce signal est intercepté par le module Model qui va prendre les mesures adéquates, à savoir:
    1. Demander à un objet dont la responsabilité est le maintient des informations de rajouter l'information reçue à la liste (*)
    2. émettre un signal indiquant aux vues qu'il est temps de se mettre à jour.

    (*) La "gestion" de la liste des traces devrait, idéalement, échoir à une classe du module Business, totalement indépendant de tout ce qui a trait aux vues et aux modèle.

    En allant un peu plus loin, on pourrait presque dire que tu devrais n'utiliser que ce qui est disponible dans l'espace de noms std, histoire, pourquoi pas, de pouvoir décider "à n'importe quel moment" de lancer un projet parallèle utilisant une autre bibliothèque graphique, par exemple, en n'ayant que ce qui utilise les possibilités de cette bibliothèque à mettre en place (ou plutôt, en pouvant récupérer tout le module Business) sans avoir à te poser de question .

    C'est le but de l'idiome modèle vue contrôleur, c'est sa raison d'être : permettre de dégager tout ce qui a trait au métier de tout le reste
    Voici un exemple de ce que j'appelle couplage entre les donneés et le modèle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename T>
    class QDataTableModel : public QAbstractTableModel
    {
      protected :
        QList<const T*> m_data; // Directement au niveau du modèle
    };

    Ici, tu as l'air de coupler la liste des traces directement au modèle concernant dans le module Model donc.


    Mais pour moi les types primitifs sont déjà définis dans le module Business en fait.
    En fait, ici, tes données métier sont au final très limitées, et tu n'as, effectivement, pas besoin du module "modifications" dont je parlais plus haut.

    En gros, ton module Business va se limiter à quelque chose comme
    1. une structure reprenant la date, l'heure, le niveau de gravité de la trace, un message et quelques informations connexes en cas de besoin
    2. une classe qui gère les différentes instances de la structure décrite en (1)
    3. peut être quelques énumérations et quelques tableaux d'équivalence (pour avoir un aperçu "textuel" des différentes valeurs énumérées)


    Mais, et j'insiste sur ce point, la seule "entrée" par laquelle le module Model accède au données métier devrait être l'interface publique de cette classe qui gères les différentes instances de trace

    Finalement, à peu de chose près, la façade de ton module correspond à cette fameuse classe qui s'occupe de la gestion des trace
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #30
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Bonjour,

    J'espère que vous avez passé de bonnes fêtes ;-)

    Ah, oui, mais quand tu auras tout dit... je saurai tout
    Je m'en suis rendu compte au vu de tes réponses oui . En fait dans mon cas, c'est plutôt minimaliste effectivement. C'est comme pour le modèle, étant donné que pour cette application, il va se limiter à un "QTableModel", je n'ai pas vraiment besoin de définir une map dans ma façade. Mais bon, l'idée reste la même ça c'est sûr

    Ce signal est intercepté par le module Model qui va prendre les mesures adéquates, à savoir:
    - Demander à un objet dont la responsabilité est le maintient des informations de rajouter l'information reçue à la liste (*)
    - émettre un signal indiquant aux vues qu'il est temps de se mettre à jour.
    (*) La "gestion" de la liste des traces devrait, idéalement, échoir à une classe du module Business, totalement indépendant de tout ce qui a trait aux vues et aux modèle.
    Ok donc ma façade du module Business pourrait ressembler à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class QBusinessFacade
    {
      public :
        void setDataToModel(QModelFacade*);
     
      private :
        QTraceCollection* m_data;
    }
    En considérant pour simplifier qu'on ait que des données de trace.
    Une fois que le modèle connait les données, il peut alors les manipuler et mettre à jour la vue si nécessaire.

    Merci

  11. #31
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sfarc Voir le message
    Ok donc ma façade du module Business pourrait ressembler à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class QBusinessFacade
    {
      public :
        void setDataToModel(QModelFacade*);
     
      private :
        QTraceCollection* m_data;
    }
    En considérant pour simplifier qu'on ait que des données de trace.
    Une fois que le modèle connait les données, il peut alors les manipuler et mettre à jour la vue si nécessaire.
    Noonn!!!

    Ton modèle dois connaître le business mais le business doit être totalement indépendant (y compris au travers de la façade) du modèle.

    Dans l'ordre des dépendances, le modèle dépend du business, le module réseau dépend d'une partie du business (pour les traces en elles-même) et le module vue dépend du modèle. Mais business ne dépend d'aucun module et, pour aller plus loin, il ne devrait même pas dépendre de Qt.

    Dans l'idéal, ton business n'utiliserait que des classes comme std::(w)string, std::vector, std:map ou des type "personnels" (mais là, c'est mon côté puriste qui parle et il est un peu radical )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #32
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    le business doit être totalement indépendant (y compris au travers de la façade) du modèle.
    Ok ça parait logique dans le fond mais du coup, à quoi va servir la façade du module business ?
    Il faudrait au moins que je puisse exposer dans ce cas là les données, à savoir ici la collection des traces par exemple, pour que la façade du module modèle puisse les associer au modèle voulu.

    pour aller plus loin, il ne devrait même pas dépendre de Qt.
    C'est vrai que ce serait l'idéal

  13. #33
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sfarc Voir le message
    Ok ça parait logique dans le fond mais du coup, à quoi va servir la façade du module business ?
    En fait, la loi de Déméter s'applique aussi bien aux différents types qu'aux différents modules.

    La partie métier s'occupe de gérer les données "brutes".

    Dans ton cas, tu as deux types de données : Une classe (ou une structure) qui correspond à une ligne dans le fichier log et une classe qui permet de maintenir (et d'accéder à ) l'ensemble des lignes qui ont été lues dans le fichier log.

    On se fout pas mal, au niveau du module Business, de savoir d'où viennent ces données!!! Elle pourraient tout aussi bien avoir été lue sur le disque dur local que récupérées au travers du réseau.

    Tout ce que tu sais, c'est que tu vas manipuler des "traces" issues "de quelque part", et que tu dois donc être en mesure de les garder en mémoire .

    Le module Model a deux choses à faire :
    D'un coté, il doit être en mesure de rajouter les lignes de trace qui lui viennent "de n'importe où" (ici aussi, on se fout pas mal de l'origine de ces traces ).Et de l'autre, il doit pouvoir récupérer ces données afin de les transmettre à la vue qui s'occupera de les afficher.

    Bien sûr, lorsqu'il va au passage sans doute décider de la ligne, de la colonne ou de la couleur qui sera utilisée pour afficher un des éléments de la trace, mais le business n'a aucun besoin de connaître ces informations.

    Le modèle a donc besoin de quatre choses qui viennent du module buisness, ni plus, ni moins (alors que le module business en utilise sans doute d'avantage )
    La structure de ta trace, dont il utilisera certaines parties afin de transmettre ses ordres à la vue.
    Une fonction qui lui permette d'ajouter une trace parce que c'est le module Model qui décidera de rajouter une nouvelle information.
    Une fonction qui permette de savoir combien de traces le business contient
    Une fonction qui permette au modèle d'accéder à une trace bien particulière, par exemple, sur base d'un numéro incrémenté.

    En effet, si le log dure assez longtemps, le modèle n'a sans doute que faire de 153 497 premières lignes de log, et il pourrait très bien se contenter des 20 dernières.

    Il n'a même pas besoin d'utiliser un itérateur! il a juste à s'occuper de calculer le "numéro" de la trace qui l'intéresse sur base du nombre de trace que le business contient.

    Autrement dit, ton modèle fonctionnera sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void ilFautAjouterUneTrace( Trace const & t){
       business.ajouteLaTrace(t);
    }
    void jeVeuxLesVingtDernieresTraces(){
        size_t total =business.nombreDeTraces();
        size_t premiereTrace =  (total >20 ? total-20 : 0);
        for(size_t i = premiereTrace; i<total; ++i){
            Trace const t = business.donneMoiLaTrace(i);
            /* ... */
        }
    }
    Chaque fois que tu vois business apparaitre, c'est quelque chose qui doit être exposé par la façade du module en question, mais il ne faut strictement rien de plus

    Il faudrait au moins que je puisse exposer dans ce cas là les données, à savoir ici la collection des traces par exemple, pour que la façade du module modèle puisse les associer au modèle voulu.
    Non, je viens de t'en donner la preuve
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #34
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Effectivement, il suffit d'exposer des méthodes de la façade business pour que la façade modèle puisse mettre à jour les données brutes sans pour autant les exposer

    Dernier point, pour revenir sur ton ancienne réponse :
    Dans l'ordre des dépendances, le modèle dépend du business, le module réseau dépend d'une partie du business (pour les traces en elles-même) et le module vue dépend du modèle. Mais business ne dépend d'aucun module et, pour aller plus loin, il ne devrait même pas dépendre de Qt.
    Seulement, tu proposes dans la conception de mettre dans la façade du modèle une méthode SetModelToView pour associer à la vue un modèle. Dans ce cas, la façade du modèle dépendrait donc de la vue (paramètre de la méthode).
    Pourquoi ne pas exposer le modèle via la façade et plutôt faire dépendre la façade Graphic du modèle à la place en proposant une méthode similaire SetModelToView mais dans la façade Graphic avec en argument la façade du modèle?
    Bon après c'est vrai qu'exposer le modèle est potentiellement plus "dangereux" que d'exposer une vue.

  15. #35
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sfarc Voir le message
    Dernier point, pour revenir sur ton ancienne réponse :
    Dans l'ordre des dépendances, le modèle dépend du business, le module réseau dépend d'une partie du business (pour les traces en elles-même) et le module vue dépend du modèle. Mais business ne dépend d'aucun module et, pour aller plus loin, il ne devrait même pas dépendre de Qt.
    Seulement, tu proposes dans la conception de mettre dans la façade du modèle une méthode SetModelToView pour associer à la vue un modèle. Dans ce cas, la façade du modèle dépendrait donc de la vue (paramètre de la méthode).
    Cela mérite vraiment réflexion

    Il faut dire que les relations entre le modèle et la vue sont particulièrement complexes

    D'abord, parce que la communication entre les deux doit passer "dans les deux sens" :

    D'une part, le modèle doit pouvoir prévenir la vue qu'il est temps de se mettre à jour, et d'autre part, la vue doit pouvoir:
    • indiquer au modèle qu'elle a intercepté un événement pour lequel le module devra décider de le prendre en compte ou non
    • interroger le modèle afin de savoir quoi afficher.
    En plus, tu peux parfaitement avoir plusieurs vues qui travaillent de concert avec le même modèle (on a une relation de l'ordre de un modèle à plusieurs vues).

    La communication dans le sens modèle vers la (les) vue(s) qui utilise(nt) le modèle peut se faire à coup de signaux.

    Il en va de même quand la (les) vue(s) qui utilise(nt) le modèle doi(ven)t lui transmettre un événement qu'il doit prendre en compte.

    Mais le système de signaux et de slot sera insuffisant pour permettre à la vue d'interroger le modèle afin de savoir ce qu'elle doit afficher

    Ce n'est en effet pas un hasard si la classe QAbstractItemView (la classe de base pour tout ce qui doit afficher des données ) disposer d'une fonction setModel(QAbstractItemModel*). C'est parce que la classe QAbstractItemModel (la classe de base pour tous les modèles que nous voudrions utiliser) expose un certain nombre de services qui seront directement utilisés par les vues .

    On remarque donc qu'il y a, de facto, une dépendance de la vue (ou du module View) envers le modèle (ou envers le module Model). De ce point de vue particulier, il serait donc sans doute dommageable de rajouter une dépendance inverse (du module Model envers le module View), mais...

    Nous travaillons ici avec deux abstractions. "L'empreinte" de la dépendance du module Model vis à vis du module View serait donc particulièrement limitée (on peut se contenter de transmettre un pointeur ou une référence vers un élément de type QAbstractItemView). Et il faudra, de toutes façons, questionner la façade de Model pour pouvoir définir le modèle de tes vues, que ce soit au travers de la façade de View ou directement depuis tes vues.

    La question est donc: préfères tu écrire un code qui pourrait ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyView::askModelToModule(ModelFacade & facade){
        facade.setModelToView(this);
    }
    ou un code qui ressemblerait plutôt à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyView::askModelToModule(ModelFacade & facade){
        setModel(facade.giveMeModel());
    }
    Perso, je préfères "intuitivement" la première solution. Mais je n'ai aucune justification conceptuelle à te donner à ce sujet
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  16. #36
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Nous travaillons ici avec deux abstractions. "L'empreinte" de la dépendance du module Model vis à vis du module View serait donc particulièrement limitée (on peut se contenter de transmettre un pointeur ou une référence vers un élément de type QAbstractItemView).
    Effectivement, je peux très bien garder un type abstrait pour la vue défini par Qt. Mais, si je souhaite garder une indépendance avec la bibliothèque utilisée, tout comme ce que tu proposais pour le module business, on ne peut plus "se reposer" sur une vue abstraite offert par Qt.
    Enfin bon, l'idée reste la même j'imagine, définir une vue abstraite et garder cette petite dépendance avec le modèle de la façade du module Graphic.

    La question est donc: préfères tu écrire un code qui pourrait ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyView::askModelToModule(ModelFacade & facade){
        facade.setModelToView(this);
    }
    ou un code qui ressemblerait plutôt à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyView::askModelToModule(ModelFacade & facade){
        setModel(facade.giveMeModel());
    }
    Perso, je préfères "intuitivement" la première solution. Mais je n'ai aucune justification conceptuelle à te donner à ce sujet
    La deuxième solution a quand même un inconvénient que je trouve important. Il expose depuis la façade Model le modèle, qui possède d'ailleurs des méthodes publiques de gestion du modèle (ré-implémentation des méthodes du modèle Qt abstrait), méthodes donc potentiellement exploitables depuis l'extérieur.
    Exposer une vue, reste donc a priori, moins néfaste non?

    Je pencherais donc plutôt pour la première aussi

Discussions similaires

  1. [Conception] - Chargement
    Par defkid dans le forum Général Java
    Réponses: 5
    Dernier message: 24/10/2005, 17h20
  2. Gestion des départements problème de conception
    Par snoopy69 dans le forum Modélisation
    Réponses: 7
    Dernier message: 11/10/2005, 13h08
  3. Réponses: 3
    Dernier message: 08/12/2004, 21h11
  4. Problème de conceptions de tables
    Par dtavan dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 23/05/2004, 23h13
  5. Problème lors du chargement
    Par carlito dans le forum Flash
    Réponses: 26
    Dernier message: 06/01/2004, 15h21

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