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 :

Que penser des frameworks et architectures qui font dériver toutes les classes d'un SuperObjet ?


Sujet :

C++

  1. #81
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par bretus Voir le message
    Qt unifie au sein de QObjet, où QObjet EST-UN "objet au sens de Qt", appartenant à une hiérarchie de classe arborescente, muni d'un mécanisme de signaux, attaché à un thread...
    Pour moi, c'est bien ce point résume bien ce que je n'apprécie pas dans le concept de super-objet. Plus que l'héritage public, sur lequel je ne vais pas revenir [1], ce qui me gêne c'est :
    • L'aspect contaminant du super objet. Pourquoi fournir à un objet un mécanisme de signaux si cet objet n'a rien à faire des signaux ?
    • Le rôle/responsabilité extrêmement flou (j'irais jusqu'à dire le côté fourre-tout) du super-objet.


    Quitte à utiliser l'héritage public pour fournir des fonctionnalités "techniques" du type gestion de signaux, gestion des threads, comptage de référence, ou que sais-je encore, j'aurais plutôt tendance à définir n classes de base ayant chacune un rôle clairement définie et à ne faire hériter de ces classes que les objets qui ont réellement besoin de ces services.





    [1] Pour résumer je suis plus ou moins d'accord sur le principe avec koala01 mais j'ai tendance à être plutôt souple (certains diront laxiste) quant au respect de ce principe.

  2. #82
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par gl Voir le message
    Quitte à utiliser l'héritage public pour fournir des fonctionnalités "techniques" du type gestion de signaux, gestion des threads, comptage de référence, ou que sais-je encore, j'aurais plutôt tendance à définir n classes de base ayant chacune un rôle clairement définie et à ne faire hériter de ces classes que les objets qui ont réellement besoin de ces services.
    Tous dépend. C'est vrai que cette solution as beaucoup de bon sens. Mais que se passe t'il s'il y as des dépendances entre deux type de gestion? si tu veut l'un il te faut l'autre. Et très vite tu peut te retrouver à devoir tous prendre.

    Pour Qt c'est le cas. Les signal/slot utilisent les metadata et l'appartenance au thread. Les metadata référence les signal/slot, ...

    Si tu veux rendre un framework comme Qt accessible à tous le monde (débutant à expérimenté), avoir qu'un seul object est plus simple.

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 69
    Points : 62
    Points
    62
    Par défaut
    Bonjour,

    Je remarque une chose :
    les tenants du superobject semble y voir un avantage au niveau de la simplicité du code (dans le style : "l'héritage c'est simple, le reste ça devient complique et donc dangereux").

    Je vais illustrer mes propos faits plus haut afin de dédramatiser la difficulté de mise en place de diverses solutions (il va y avoir cependant une 'montée en puissance').

    Tout d'abord, l'aggregation pour 'simuler' l'héritage.
    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
     
    class networkmodule
    {
    private:
        long ip; 
        // ... plein d'autres trucs
    public:
        bool sendData(id module, uchar* data, int lenght);
    };
     
    class MaWidget
    {
    public:
       networkmodule n;
       void fonctionAggrandirWidget(int x, int y);
    };
     
    // je pourrais ajouter un operator()(networkmodule*){} pour simplifier encore la chose..
    Bref, pas de soucis pour les accesseurs public c'est la meme chose, et pour les accesseurs private c'est la meme chose aussi, et les fonctions sont appellées identiquement.
    Bien sûr pas de fonction virtuelles a l'horizon, mais il 'suffit' d'ajouter des pointeurs de fonctions dans la classe de base. MaWidget a juste à les initialiser dans son constructeur vers ses propres fonctions). networkmodule peut le faire par défaut.
    Bon tout ça n'est pas folichon et je pense pas que ça pose de soucis particulier à qui que ce soit.

    Je passe a l'appel de fonction monothread/ multithread. Je laisse le code volontairement simple sans chercher à optimiser.
    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
     
    struct InfoDeThread
    {
       void setCurrentThreadId(int pId);
       int getThreadId();
    private:
       //... critical section etc...
    };
    struct MoteurAudio
    {
         InfoDeThread mInfoThread;
         void playSound(std::string name);
         void getSoundLength(std::string name); // renvoie durée
         static void threadFunction(MoteurAudio* This);
         // attend le thread pour executer la commande
         void storeCommande(Message m);
         // attend le thread, et renvoie la reponse.
         Message waitCommande(Message m);
    };
    struct MoteurDeJeu
    {
         InfoDeThread mInfoThread;
         void gagneUnePieceDOr();
         static void threadFunction(MoteurDeJeu* This);
     
         // attend le thread pour executer la commande
         void storeCommande(Message m);
         // attend le thread, et renvoie la reponse.
         Message waitCommande(Message m);
     
    private:
         MoteurAudio *mAudio;
    };
    On va avoir N thread. Parmi eux 1 va par exemple creer un moteur de jeu et un moteur audio. Ce thread va assigner l'ID a chacun des moteurs qu'il fait tourner. Et ensuite appeler en boucle a la suite les fonctions threadFunction correspondantes sur ces objets.
    Si les moteurs sont au contraire construits dans 2 threads differents, les fonctions s'executeront donc dans 2 threads differents.

    Le code intéressant est la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void MoteurDeJeu::gagneUnePieceDOr()
    {
          ++score;
         if(mAudio->mInfoThread.getThreadId() == mInfoThread.getThreadId())
    {
         // appel direct.
          mAudio->playSound("gagneOr.wav");
    }else{
     mAudio->storeCommand(ToMessage("playSound","gagneOr.wav"));
    }
    }
    Cet appel peut etre remplace par une macro :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void MoteurDeJeu::gagneUnePieceDOr()
    {
          ++score;
          FAIREAPPEL_POTENTIELLEMENT_MULTITHREAD(mAudio, playSound, ("gagneOr.wav") );
    }
    Et jusqu'à présent pas de trace de superobjet dans ce code.
    Ensuite, les thread faisant tourner les différents moteurs ont juste a choisir leur ID, et les assigner.
    J'ai pas le sentiment que cela soit si complexe .


    Ensuite, si on se dit : j'ai 2 instances de moteurs graphiques.
    Et bien je cree 2 moteurs graphiques, je mets a jours leur ID et ca marche toujours. Pas de soucis non plus.

    Ensuite, si on se dit : j'ai envie de changer dynamiquement le thread qui execute tel ou tel moteur. Il y a 2 choses a faire. 1/ il faudra d'abord remplacer les getThreadId() par des LockAndGetThreadId.
    2/ Il faudra boucler sur les moteurs. Le premier truc qui vient ensuite à l'esprit à ce niveau est effectivement l'héritage.
    Cependant on peut écrire les thread ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void function::ThreadCPU1(){
    while(true)
    {
    pour tous graphiques enregistres sur ce thread
    	MoteurGraphique::threadFunction(moteurGraphique)
     
    pour tous audios enregistres sur ce thread
    	MoteurAudio::threadFunction(moteurAudio)
     
    // et ainsi de suite pour tous les types...
    }
    }
    Ce qui, en C++, peut se traduire en une boucle sur un simple tuple<std::vector<MoteurAudio>, std::vector<MoteurGraphique>, ... >. La boucle sur le tuple est dispo dans boost::fusion.

    Il y a plein d'autres façon de faire (vector<boost::variant>, pointeurs de fonctions...,) mais je voulais rester simple. Bref, sans superobject, et compréhensible pour des lycéens.

    Y'a-t-il des difficultés?

    *********************
    Bon ensuite, concernant le composite de SuperObject, je suis d'accord que c'était plutôt une erreur de conception.
    Mais puisque je considère le SuperObject deja comme une plaie, il m'est difficile de dire "faut pas faire de composite (sur les super object)". Car j'ai rien contre les composite en général.

    *********************
    En ce qui concerne la Solution 3 de "recopie", je ne l'ai pas trop évoquée au dessus.
    Il s'agit d'utiliser une / des macros pour faire la recopie automatiquement du code manquant. De cette manière, on peut écrire juste 1 fois le .h d'une classe et en appelant 1 seule macro rendre la classe serializable / scriptable / networkable / fonctions multithreadees, mappables etc... rien de neuf sous le soleil, mais les gens ont tendance à l'oublier.
    Evidemment, le temps de compil est très rapide, et les performances à l'execution equivalentes à celles d'un code qui aurait été recopié à la main (moins besoin d'héritage).

    Mais les macros ne sont pas toujours jolies à lire et maintenir.

    D'où, pour la Solution3 la possibilité d'utiliser un generateur de code (comme QT). On écrit son propre langage de .h, et hop on génère son code correspondant. Le code dans les .cpp reste complètement identique, juste le .h est généré.
    Facile à mettre en place et à maintenir. Avec boost::spirit ça se fait en 2 jours.
    Cela revient à avoir de la recopie, mais c'est + efficace à tous les niveaux (sauf en temps de compil ). Bref c'est ça la "recopie".

    Bon faut que j'aille manger.

  4. #84
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par yan Voir le message
    Mais que se passe t'il s'il y as des dépendances entre deux type de gestion? si tu veut l'un il te faut l'autre. Et très vite tu peut te retrouver à devoir tous prendre.
    A froid, j'aurais tendance à dire que dans ce cas, il y a peu être un autre problème. Trop d'interdépendance.
    La question que je me poserais serait probablement : ces dépendances sont-elles justifiées ou est-ce juste une solution de facilité ?

    Citation Envoyé par yan Voir le message
    Pour Qt c'est le cas. Les signal/slot utilisent les metadata et l'appartenance au thread. Les metadata référence les signal/slot, ...
    Il faut vraiment que je me penche sur l'implémentation de Qt dans le détail un de ces jours. Autant je trouve de nombreuses fonctionnalités intéressantes, autant ce que je lis de leur implémentation me surprends parfois [1].


    [1] Même si je suppose qu'il y a certainement de bonnes raisons d'en être arriver à cette implémentation. Probablement, entre autres, des raisons historiques et, comme tu l'indiques, de simplicité.

  5. #85
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    L'aspect contaminant du super objet. Pourquoi fournir à un objet un mécanisme de signaux si cet objet n'a rien à faire des signaux ?
    +1, c'est un point noir des gros framework à base de SuperObjet face aux API de bas niveaux : difficile de limiter la propagation.

    Il est facile de limiter la contamination lorsque l'on utilise les classes de bases dans le framework (valable dot net, Qt).

    Dès lors que l'on veut "redescendre" la moindre fonctionnalité, il faut se tortiller, mais ça reste faisable... On arrive a encapsuler un composant à base de Qt ou à base de Dot Net ( merci à la faq pour gcroot<T> ). Par contre, on perd vite les facilités de communication entre les différents composants...

    Citation Envoyé par gl Voir le message
    Quitte à utiliser l'héritage public pour fournir des fonctionnalités "techniques" du type gestion de signaux, gestion des threads, comptage de référence, ou que sais-je encore, j'aurais plutôt tendance à définir n classes de base ayant chacune un rôle clairement définie et à ne faire hériter de ces classes que les objets qui ont réellement besoin de ces services.
    Idem pour l'avis sur Qt... A vrai dire, c'est surtout les fonctions de traductions qui m'ont chagrinées (effet java, plus rien ne choque )

    Sinon, QObject fait peut-être office de façade dont l'utilisation est facilement compréhensible par des "débutants"?

    Combien d'utilisateurs de la STL utilisent encore les fonctions C, faute de simplicité, pour convertir leurs chaines de caractères en double?

    Là encore, en vue du public visé, le choix d'architecture se défend...

  6. #86
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    @ElPedro : le problème dans ce que tu montre est que tu doit tout connaitre et tu peut très rapidement (un nouveau développeur qui veut faire à sa manière) te retrouver avec plusieurs méthode de gestion.
    Ton code est statique. Pour ajouter une classe, tu va devoir modifier là, là et là. Petit à petit cela va devenir vraiment compliqué.
    Si tu refile ton code à quelqu'un d'autre il va vite être perdu ou faire n'importe quoi. C'est bien connue le code que l'on reprend est toujours merdique à nos yeux

    La maintenance de code n'est pas anodin. Sur un petit projet ce que tu propose est surement plus adapté. Pour un framework comme Qt, wxWidget,... je ne le pense pas.

    Tu peut certainement simplifier tous cela à base de template (Laurent Gomila en as donné un exemples), mais cela restera tout de même très statique.
    Comment charger dynamiquement un code (plugin ) et que cela marche avec ton architecture?
    Comment ton architecture va savoir faire un teste d'appartenance au thread?
    Comment il va faire des appel asynchrone des méthodes de l'instance?
    etc, etc, etc

    [edit]
    Je me demande si le pattern décoration en serait pas plus adapté en C++ pour faire ce que tu propose.

    Citation Envoyé par gl Voir le message
    [1] Même si je suppose qu'il y a certainement de bonnes raisons d'en être arriver à cette implémentation. Probablement, entre autres, des raisons historiques et, comme tu l'indiques, de simplicité.
    Y as aussi la portabilité, c'est aussi cela qui leur permet de faire fonctionner un même code sur différente machine et même de supporter VC6 jusqu'à la version 4.3 (ou 4.4 je sais plus)

  7. #87
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par yan Voir le message
    Y as aussi la portabilité, c'est aussi cela qui leur permet de faire fonctionner un même code sur différente machine et même de supporter VC6 jusqu'à la version 4.3 (ou 4.4 je sais plus)
    Peux-tu préciser ce que tu entends par là exactement ?

    Si tu veux parler du support des template, de la STL et, d'une manière plus générale, des fonctionnalités "récentes" du C++ posant problème sur des compilateurs un peu anciens (dont VC6 mais pas uniquement), c'est ce que j'entendais par "raisons historiques" (bon d'accord, je le reconnais c'est très flou comme terme). Avais-tu autre chose en tête ?

  8. #88
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par gl Voir le message
    Avais-tu autre chose en tête ?
    non.

  9. #89
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 69
    Points : 62
    Points
    62
    Par défaut
    Comment ton architecture va savoir faire un teste d'appartenance au thread?
    Désolé c'est hyper trivial, compte tenu de ce que j'ai déjà écrit.
    Je vais faire un effort ( mais mets y un peu du tiens !) :
    tu as 1 class threadsystem qui crée tes threads et leur associe un ID. il est alors possible de créer, stocker et comparer ces IDs. C'est ce que je montre dans mon exemple. Et oui c'est bidon et basique. J'ajoute que je parie que boost::thread, les threads win32, dlib, et si ça se trouve les threads qt fonctionnent ainsi...


    J'ajoute que j'ai déjà fait des systèmes équivalents à camp, avec une archi quasiment identique basée sur les templates, et que je n'y ai rien vu de neuf. Ce sont des choses qui sont connues depuis des années...

    Comment il va faire des appel asynchrone des méthodes de l'instance?
    C'est ce que j'ai écris. Où est le problème sincèrement?
    Ah oui. Je vois. Désolé, je pensais que c'était évident.
    La méthode "storeCommande(Message m);" enregistre la demande dans une pile de l'objet (d'où le nom).
    La fonction de thread de l'objet vide cette pile et appelle la fonction correspondante avec les paramètres recrés grâce à m. (bon, on n'est pas oblige de passer par une classe intermediaire m, mais c'est bien utile si l'on souhaite serializer l'appel pour l'envoyer sur le réseau).
    La transformation en 'Message m' se fait par une classe template (un message contient un int (type), et pour le data vector<float> vector<int> vector<char>). C'est pas plus compliqué qu'un boost::serialize.

    La difficulté est d'avoir à recopier les appels pour chaque fonctions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if(m.type == 3) // numero de fonction3
    {
         std::string param1 = extractParam<std::string>(m); // type param1
         int param2 = extractParam<int>(m); // type param2
    // etc... puis appel direct
        This->mafonction(param1,param2);
    }
    D'où l'usage d'une macro pour générer automatiquement tous ces appels, ou d'un postprocess (comme Qt).

    Ce qui n'a rien à voir avec le fait qu'on parle d'un super object ou pas.... C'est juste de l'appel asynchrone de base, limite off-topic.

    Comment charger dynamiquement un code (plugin ) et que cela marche avec ton architecture?
    Ok alors absolument toutes les classes de ton archi doivent être des plugins alors??? (je rappelle qu'on parle des fonctionnalités du superobject là).

    Tu semblais prétendre qu'on ne pouvait pas faire de la gestion multithread/monothread asynchrone sans passer par un superobject. Je montre le contraire.

    Je n'ai pas vu que tu voulais que tes ints, tes doubles, tes vector3d, tes points2d, tes chars etc... soient tous des plugins ... je trouve ça difficile à concevoir, mais bon ok si tu y tiens...

    Et bien effectivement dans ce cas je ne sais pas comment faire pour un super object. J'avoue ne pas m'être du tout penché sur la question. Et j'avoue qu'elle ne m'intéresse pas plus car l'ABI C++ est avant tout celle du C, ce qui signifie que par dessus on peut l'enpaqueter comme on veut (template, heritage, macro etc...).

    Pour les plugins, j'utiliserai sûrement de l'héritage. Mais pas question que tous mes objets soient des plugins.

    te retrouver avec plusieurs méthode de gestion.
    Je te rassure, je fourni une belle doc avec tests unitaires et tutorial en 2 lignes pour tous mes frameworks. La maintenance est hyper simple. Tu vas pas me faire croire que ce que j'ai écris jusqu'à présent est difficile à lire ...

    Voici ce a quoi ressemble une classe au final utilisant mon système:
    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
     
    // dans le fichier qui sera utilise pour generer le .h
    class maClass inherits truc
    {
    [serializable]
        public:
           maClass();
           int unattribut;
    [qtgui, chaiscript, lua, python]
     
           void doSomething();
    [networkable, qtgui, chaiscript, lua, mappable]
     
    };
     
    // et dans le cpp :
    maClass::maClass ():truc(),unattribut(0)
    {
     
    };
     
    void maClass::doSomething()
    {
        // tout ce que tu veux
    };
    Et la tu as automatiquement les attributs que tu souhaites (serialization, etc...).
    Si tu trouves ça trop compliqué, ben je sais pas ce qu'il te faut...

    Malheureusement, ceci n'est que l'interface de programmation, et ce qui importe peu dans le débat sur le fait d'avoir un superobject ou pas.

    Qt pourrait tout a fait utiliser autre chose que de l'héritage pour faire un système équivalent et très (plus) puissant, avec une interface quasiement équivalente.

  10. #90
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par ElPedro Voir le message
    C'est ce que j'ai écris. Où est le problème sincèrement?
    1-que tu impose une méthode en pensant que ceux qui vont utiliser ta lib vont faire pareil.
    2- Rien n'empêche l'utilisateur de faire des choses qui ne marchera pas avec ce système et perdre des heures à comprendre pourquoi.

    Le superObject le guide.

    Ok alors absolument toutes les classes de ton archi doivent être des plugins alors??? (je rappelle qu'on parle des fonctionnalités du superobject là).
    ...
    Je n'ai pas vu que tu voulais que tes ints, tes doubles, tes vector3d, tes points2d, tes chars etc... soient tous des plugins ... je trouve ça difficile à concevoir, mais bon ok si tu y tiens...

    j'ai jamais dit cela. J'ai juste demandé comment ça se passerai avec ton architecture.

    Tu vas pas me faire croire que ce que j'ai écris jusqu'à présent est difficile à lire ...
    j'ai jamais dit que ce que tu montre est compliqué, mais qu'un développeur lambda peut faire assez facilement n'importequoi avec. La doc ne fait pas tout.

    Voici ce a quoi ressemble une classe au final utilisant mon système:
    tu utilise un générateur de code?

    Qt pourrait tout a fait utiliser autre chose que de l'héritage pour faire un système équivalent et très (plus) puissant, avec une interface quasiement équivalente.
    Franchement, j'y croie pas. Mais c'est mon point de vue et relie bien ce que j'ai déjà écrit(en particulier sur les signal/slot de Qt et le fonctionnement dynamique) et explique moi comment tu ferais.

    Ce que tu as fait semble très bien, je ne dit pas le contraire. Je dit juste, pour moi, en quoi je trouve le superObject mieux pour un gros framework comme Qt :
    1- base commune. Simplicité pour la compréhension et la maintenance du code
    2- abstraction des fonctionnalités importante. Plus de sécurité sur le code de l'utilisateur pour ces fonctionnalités.
    3- Ajout d'un fonctionnement dynamique

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Ce que tu semble ne pas vraiment intégrer yan, c'est qu'une grosse partie de ce que permet le super objet sera, de toutes manières, à usage strictement interne pour des classes qui, de toutes manières, serviront de base à des hiérarchies qui pourraient parfaitement être distinctes si elles n'avaient pas, comme c'est le cas de Qt, un ancêtre commun.

    De la même manière, ce que présente ElPedro sera en grande partie aussi à usage strictement interne, et totalement transparent pour l'utilisateur.

    La seule différence, c'est que, plutôt que d'avoir une seule grande hiérarchie présentant un nombre de niveau important, tu as une série de hiérarchies dont les responsabilités et les interconnexions sont moins diffuses et présentant un nombre de niveau beaucoup plus restreint.

    Effectivement, s'il s'agit de rajouter un "tout nouveau" module au framework, le super objet servant de base commune à tous les autres sera sans doute plus facile, mais ce n'est très certainement pas Monsieur Tout_Le_Monde qui va s'y risquer

    Par contre, on peut effectivement trouver, que ce soit avec Qt et son super objet ou avec la manière dont ElPedro présente les choses, des gens qui voudraient créer un composant spécial basé sur (héritant de ) l'existant, et, dans ce cas, la présence du super objet n'apporte de toutes manières aucun avantage, ni aucun inconvénient (hormis le nombre de niveaux de la hiérarchie).

  12. #92
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ce que tu semble ne pas vraiment intégrer yan, c'est qu'une grosse partie de ce que permet le super objet sera, de toutes manières, à usage strictement interne pour des classes qui, de toutes manières, serviront de base à des hiérarchies qui pourraient parfaitement être distinctes si elles n'avaient pas, comme c'est le cas de Qt, un ancêtre commun.
    Les metada, les connect, le GC de Qt, l'organisation des instances sous forme d'arbre, les eventloop, le fonctionnement asynchrone des classes (permet d'éviter de faire des thread quand c'est inutile) servirai à quoi si tous était interne et donc caché de l'utilisateur? Par exemple, le connect doit être accessible par le développeur. Changer l'appartenance d'un object à un thread aussi.
    Comment faire pour connecter la fin du téléchargement d'un fichier à un traitement? Pour créer des classes asynchrone ?
    Ajoute s'y un fonctionnement thread-safe dans le sens ou le slot sera exécuté dans son thread et éviter les accès concurrent et l'utilisation des mutex et tu as une partie de ce que propose le superObject de Qt.

    Si vous voulez, on peut faire sans (bien qu'il y as quelques petite des choses que je voie pas comment. DU moins aussi facilement. Comme tous le fonctionnement dynamique ajouté par l'architecture), mais par rapport au nombre de système qui cohabite et exploité par Qt, l'agrégation est beaucoup plus compliqué. On peut trés bien avoir plein de gestionnaire (de base et ajouté par les développeur) mais celui-ci n'est pas compatible avec celui-là, et celui-çi non plus,....
    Le superObject te permet d'exploiter correctement tous cela et est beaucoup plus simple à comprendre. On fixes les choses.

    De même que pour les évolutions. Si tu change le fonctionnement d'un des gestionnaire (par exemple remplacé la pile de message par une eventloop) tu te retrouve à devoir modifier toutes tes classes!!! Rien en t'empêche de nommer un gestionnaire différemment d'une classe à l'autre (chaque développeur fait à sa manière). Ça deviens vite compliqué pour rien. A la limite le pattern décoration à plus de sens (et plus propre) pour faire cela.


    Dans ce qu'à fait ElPedro, si j'ai bien compris, il propose un générateur de code. Donc cela simplifie grandement les choses. L'utilisateur n'est pas plus libre qu'avec le superObject car il lui impose un fonctionnement. Celui écrit par le générateur.

    Les classes héritant de QObject dans Qt sont uniquement celle qui ont un sens et exploite les fonctionnalités proposées par Qt. A la limite autant dire que QWidget ne sert à rien non plus. Après tout c'est le superObject de la partie IHM. Pour hiérarchiser les composantes de l'ihm ça commence à devenir assez dure.

    Pour bien me faire comprendre, je ne parler que du cas de Qt. Je n'ai jamais dit qu'il faut faire le superObject partout et que c'est la meilleur choses au monde.
    Mais pour le cas de Qt (et c'est certainement vrai pour wxWidget, gtkmm et autre) cela à beaucoup de sens et sans lui ils ne seraient aussi utilisés (et puissant ?)

    A l'opposé boost n'en as pas et heureusement. Là cela ne veut rien dire pour moi.


    ps : Quelque choses que j'ai pas compris dans vos réponse, l'agrégation donne du code plus rapide et moins lourd que de l'héritage??? j'aurais pensée que cela reviens au même. Surtout s'il n'y as aucune fonction virtuel.

  13. #93
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Les metada, les connect, le GC de Qt, l'organisation des instances sous forme d'arbre, les eventloop, le fonctionnement asynchrone des classes
    Je crois que tu as magnifiquement résumé toute la discussion là. Honnêtement si on te présentait un cahier des charges avec toutes ces spécifications, tu partirais sur une seule classe regroupant tout ça ? Moi non, je séparerais en au moins 2 ou 3 classes distinctes.
    Héritage ou aggrégation, peu importe, finalement ce n'est pas l'objet de la discussion.

  14. #94
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 69
    Points : 62
    Points
    62
    Par défaut
    relie bien ce que j'ai déjà écrit(en particulier sur les signal/slot de Qt et le fonctionnement dynamique)
    Le code que j'ai donné permet de faire cela déjà et avec des branchements dynamique. On pourrait aussi utiliser la librairie sigslot - de la nasa-...

    En ce qui concerne les techniques de communications asynchrone (boost::asio, mpi) , les sytèmes de threading, les signal/slots, ce sont des méthodes éprouvées que les gens utilisent (et que j'ai présenté). On retombe toujours sur les mêmes patterns.

    Il existe de nombreuses librairies de signal slot, à commencer par sigslot, mais aussi boost::signal2.

    Quand à la simplicité d'utilisation du superobject, j'ai eu l'occasion de travailler sur le projet AReVi (ce n'est pas un de mes projets), qui utilise un ARObject et un paquet de macros. Que se passe-t-il si jamais j'essaie d'utiliser AReVi avec QT ? Bref, aucune flexibilité.

    Quelque choses que j'ai pas compris dans vos réponse, l'agrégation donne du code plus rapide et moins lourd que de l'héritage??? j'aurais pensée que cela reviens au même. Surtout s'il n'y as aucune fonction virtuel.
    Si ton destructeur est non-virtuel ca devrait être aussi efficace .

  15. #95
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Sauf erreur de ma part, Yan le solitaire ne dit pas que ce n'est pas possible sans super-objet. Juste que c'est plus simple d'utilisation (surtout pour l'utilisateur lambda)

    Quand on regarde les questions posées par les débutants sur ce forum : mauvaise maîtrise des pointeurs, joyeuses utilisations de char*... et je ne parle même pas de ceux qui ne savent pas utiliser les templates, les desgin pattern et ne savent pas ce qu'est une composition.
    Et il y a ceux (comme moi) qui se moquent totalement de comment les fonctions sont implémentées en interne et qui préfèrent avoir 1 super-objet qui apporte toute les fonctions plutot que de devoir ajouter une composition pour chaque fonction qu'on utilise.

    Tout dépend le public visé (et des frameworks tels que wx ou Qt sont destinés à tous types d'utilisateurs, même ceux qui débutent la programmation et qui veulent pouvoir créer tout de suite un fenêtre avec des menus et des boutons)

  16. #96
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Et il y a ceux (comme moi) qui se moquent totalement de comment les fonctions sont implémentées en interne et qui préfèrent avoir 1 super-objet qui apporte toute les fonctions plutot que de devoir ajouter une composition pour chaque fonction qu'on utilise.
    Ce n'est pas tant la manière dont c'est implémenté (c'est pour ça que personnellement je ne débats plus de "héritage vs aggrégation"), c'est surtout la flexibilité, l'évolutivité et les contraintes que ça va poser à l'utilisateur. La facilité d'utilisation est une chose, mais quand on regarde un peu plus loin il y a d'autres considérations à prendre en compte, surtout quand on développe une grosse appli industrielle.

  17. #97
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    Je crois que tu as magnifiquement résumé toute la discussion là. Honnêtement si on te présentait un cahier des charges avec toutes ces spécifications, tu partirais sur une seule classe regroupant tout ça ? Moi non, je séparerais en au moins 2 ou 3 classes distinctes.
    Héritage ou aggrégation, peu importe, finalement ce n'est pas l'objet de la discussion.
    A la base je serais partie comme toi, je pense. Mais à la longue, sur un gros framework comme Qt, je pense que le super object amène plus de bien que de mal. Et je n'ai eu aucun contre exemple sur cela. Juste que l'on peut faire sans et à chaque fois sur des parties ou je n'ai pas dit contraire ou que vous m'avez démontré le contraire. Jamais sur le fonctionnement dynamique que propose Qt.

    J'ai l'impression que vous voulez absolument que ce que je dit soit blanc ou noire. J'essaie d'expliquer en quoi je préfère et trouve indispensable le superObject pour le cas de Qt et vous me répondais que l'on peut faire sans... J'ai l'impression que l'on ne parle pas de la même chose.

    Et je veut bien admettre que l'on peut tout (presque) faire sans. Ton exemple de CAMP et de ce qu'à exposé ELPedro montre pas mal de chose, et je ne dit pas que ce que vous dit est faux. Je suis même très intéressé.
    Mais je reste tout de même sur ma position. Le superObject simplifie et structure les choses pour un développeur qui va utiliser un framework type Qt.

    Ne me faite pas croire que vous pensez qu'un développeur débutant (et même parfois expérimenté) ne fera pas n'importe quoi si on ne borne pas ses actions.

    Soit vous avez beaucoup de chance et votre entourage sont de très bon développeur soit vous êtes en SSII et vous savez qu'il ne faut pas faire trop confiance à certain développeur.

    Il existe de nombreuses librairies de signal slot, à commencer par sigslot, mais aussi boost::signal2.
    dsl mais le fonctionne que propose Qt n'est pas le même. J'ai déjà expliqué la différence.

    Quand à la simplicité d'utilisation du superobject, j'ai eu l'occasion de travailler sur le projet AReVi (ce n'est pas un de mes projets), qui utilise un ARObject et un paquet de macros. Que se passe-t-il si jamais j'essaie d'utiliser AReVi avec QT ? Bref, aucune flexibilité.
    Qu'es ce qui t'empêche d'utiliser les deux? je connait pas, je demande juste.

  18. #98
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Je suis d'accord. Qt a choisi un chemin qui l'a mené vers ce super-objet et qui l'exploite aujourd'hui dans tous les sens, et on ne pourrait pas obtenir quelque chose d'équivalent en le supprimant.

    Maintenant sur des frameworks moins conséquents et/ou ayant moins d'histoire, je pense qu'on peut également être d'accord sur le fait que personne ne devrait commencer à baser son framework sur une telle classe. C'est pas vraiment ce qui se fait de mieux en terme de conception.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par yan Voir le message
    Les metada, les connect, le GC de Qt, l'organisation des instances sous forme d'arbre, les eventloop, le fonctionnement asynchrone des classes (permet d'éviter de faire des thread quand c'est inutile) servirai à quoi si tous était interne et donc caché de l'utilisateur? Par exemple, le connect doit être accessible par le développeur. Changer l'appartenance d'un object à un thread aussi.
    Peut être me suis-je mal exprimé...

    La manière dont les meta données, les connect, les eventloop ou le changement de thread sont gérés fera fatalement partie de la "mécanique interne" de ta bibliothèque, ce qui n'empêche absolument pas pour autant d'avoir une fonction permettant d'invoquer le comportement correspondant, qui, elle, sera accessible depuis... n'importe quel objet dont la responsabilité entre dans le cadre de la gestion de ces aspects.

    Le fait est que, si tu pars d'un super objet, tu obtiens une grosse hiérarchie "monolithique" qui finit par être bloquée par sa propre inertie et dont certains pans présentent une série de comportement qui n'ont, à l'extrême limite, pas forcément lieu d'être.

    Par contre, si tu travailles à coup de "petites" classes très spécialisées dans un domaine donné (tel que la gestion de l'appartenance à un thread, pour changer un peu), tu peux parfaitement avoir, au sein d'une hiérarchie spécifique une classe qui prendra la responsabilité (pour l'ensemble de la hiérarchie) de supporter cet aspect, à condition que cela "ait un sens" pour la hiérarchie visée, sans avoir *forcément* besoin de faire appel à un super objet.

    Au final, tes hiérarchies plus "spécialisées" chaque fois dans un domaine particulier sont plus "indépendantes", et donc sans doute plus flexibles et plus faciles à maintenir parce qu'elles n'ont pas à se battre contre l'inertie d'une hiérarchie monolithique imposée... par la seule présence d'un super objet dont tout dérive

    Ensuite, on peut discuter de la manière de s'y prendre, mais, entre les classes template, l'héritage privé et l'agrégation, ce n'est pas le choix qui manque

  20. #100
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    De base, je suis entierement d'accord avec toi koala01 et j'aime pas vraiment les superObject.
    Ce que j'essaie d'expliquer avec l'exemple de Qt, c'est que parfois, le superObject sera bien mieux adapté, plus pertinent et te fera gagner sur beaucoup de points. Et que ce type de projet, s'il n'avait pas le super object et qu'il grossi de plus en plus, ils auraient surement convergés irrémédiablement vers l'utilisation d'un superObject.

    C'est minoritaire mais c'est ce le cas de Qt, wxWidget, OpenInventor, GTK, ...

    Si leurs développeurs utilisent le superObject c'est qu'il y as de très bonne raison. Je voie mal comment affirmer que ce qu'ils ont fait est mal conçue...

Discussions similaires

  1. Réponses: 36
    Dernier message: 12/01/2011, 15h55
  2. Que penser des testeurs de Carte Mère
    Par Fabdeuche dans le forum Ordinateurs
    Réponses: 1
    Dernier message: 26/11/2010, 10h35
  3. Réponses: 0
    Dernier message: 15/11/2010, 11h51
  4. Un programme qui lance quelquechose toute les 50 minutes?
    Par altadeos dans le forum C++Builder
    Réponses: 4
    Dernier message: 12/03/2006, 11h16

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