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 :

Formaliser une "interface" commune pour différentes classes templates


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut Formaliser une "interface" commune pour différentes classes templates
    Salut à toutes et à tous !

    Une question de débutant... mais que je n'arrive pas à trouver sur mes moteurs de recherche préférés...

    Une classe Factory est templatée sur le type T d'objets à fabriquer : Factory<T>, et elle construit T petit à petit en appelant certains services.
    En l'état, elle marche avec une première classe A, et Factory<A>::build() marche très bien.
    Au moment de coder une deuxième classe B pour pouvoir instancier une Factory<B>, je me vois obligé de re-parcourir l'implémentation de la Factory pour lister les services de D qu'elle nécessite pour la construction. C'est faisable parce que ma classe Factory n'est pas non plus démente, mais c'est assez pénible à faire pour que je me doute que les vrais développeurs s'y prendraient autrement. Ma question était de savoir comment

    Bien cordialement

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Je ne comprends pas ton problème précis, mais il me semble que tu devrai te renseigner sur "interface segregation principles", le I de SOLID

    Les hiérarchies OO ne sont pas toujours la solution, mais pour en dire plus, il faut un contexte plus précis.

  3. #3
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    OK merci de ta réponse
    J'ai édité le message précédent. Est-ce plus clair ?
    J'avais déjà lu sur l'ISP. D'ailleurs je crois bien que quelque part mon ennui est que j'ai poussé l'ISP à l'extrême en ne regroupant aucun service

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Une "Factory" n'est pas forcement template, c'est même assez rarement le cas.
    Si A et B sont constructibles via Factory<X>, c'est qu'ils partagent assez de point commun pour qu'un template (avec quelques spécialisations si nécessaire) puisse construire indifféremment l'un ou l'autre.

    Vous prenez le problème dans le mauvais sens.

    Vous voulez que A et B soient constructibles via un DP Factory, vous devez commencer par spécifier l'API que A et B (et les autres classes constructibles) doivent implémenter pour être constructible.
    Une fois cette API spécifiée, l'implémentation de Factory<X> l'utilise.

    Et les concepteurs des classes A, B et autres, n'ont cas implémenter cette API de construction.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par bacelar Voir le message
    Une "Factory" n'est pas forcement template, c'est même assez rarement le cas.
    Si A et B sont constructibles via Factory<X>, c'est qu'ils partagent assez de point commun pour qu'un template (avec quelques spécialisations si nécessaire) puisse construire indifféremment l'un ou l'autre.

    Vous prenez le problème dans le mauvais sens.

    Vous voulez que A et B soient constructibles via un DP Factory, vous devez commencer par spécifier l'API que A et B (et les autres classes constructibles) doivent implémenter pour être constructible.
    Une fois cette API spécifiée, l'implémentation de Factory<X> l'utilise.

    Et les concepteurs des classes A, B et autres, n'ont cas implémenter cette API de construction.
    Je ne peux que plussoyer!!!

    En fait, si tu veux faire une fabrique template, il faut non pas un paramètre template mais deux, sous une forme qui serait sans doute proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template<typename Type, typename Policy>
    class Factory{
        std::unique_ptr<A> create() const{
            return Policy().create();
        }
    /* ... */
    };
    où type correspond au "type de base renvoyé par la fabrique" et où polycy correspond à "tout ce qui doit être fait pour construire l'élément demandé".

    Ainsi, le créateur de la classe A devrait fournir non seulement la classe A, mais aussi la politique qui permet la création de cette classse, sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class A{
        /* tout ce que le createur de la classe peut souhaiter */
    };
    struct
    TheMainingfullCreatorForA{
        std::unique_ptr<A> create() const{
            /* tout ce qui doit être fait */
            return std::make_unique<A>(/* paramètres éventuels spécifiques à A */ );
        }
    };
    Maintenant, on pourrait sans doute également envisager de fournir l'interface spécifique pour Policy, sous une forme qui serait sans doute proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    ObjectCreator{
        template <typename DERIVED>
        std::unique_ptr<T> create() const;
    };
    De cette manière, il deviendrait possible de fournir une spécialisation (complète) de la ObjectCreator::create renvoyant un std::unique_ptr sur n'importe que type de base (spécialisation de T), mais dont le type réel correspondrait à n'importe quelle classe dérivée (spécialisation de DERIVED), et notre classe Factory pourrait alors prendre la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template <typename T, typename Policy = OBjectCreator<T>>
    class Factory{
    public:
        template <typename DERIVED
        std::unique_ptr<T> create() const{
            return Policy()::create<DERIVED>();
        }  
    };
    Mais bon, si on en arrive à ce point, on se demande quel est l'intérêt de la fabrique par rapport à celui de la classe que j'ai appelée ObjectCreator... Même si l'on pourrait estimer que le deuxième s'occupera surtout de rassembler et de regrouper des données utiles à la création (DP builder inside )
    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. #6
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Merci pour vos réponses et l'échantillon de code, ça m'a servi pour tout ré-écrire !
    En fait, même si je semble être parvenu à mes fins, peut-être que je n'ai pas vraiment compris ce que je voulais faire.
    Je voulais dire à un objet "je te donne telle stratégie de simulation et telles données, fabrique moi ce dont j'ai besoin".
    Voilà dessous le code que j'ai fait :

    Ce que j'ai appellé "Factory" (peut être à tort) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Factory
    {
    public:
    	template<typename simulation_trait>
    	auto create(typename simulation_trait::data_type const& data) const {
    		return Object<simulation_trait>(data);
    	}
    };
    Ce que j'ai appelé simulation_traits c'est des petites classes de traits dans un namespace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    namespace simulation_traits
    {
    	struct strategy1 {	using data_type = double; };
    	struct strategy2 { using data_type = unsigned int; };
    }
    L'objet à fabriquer, qui contient en fait deux sous objets dont les types sont dépendants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<typename simulation_trait>
    class Object
    {
    private:
    	using A_type = A<simulation_trait>;
    	using B_type = typename A_type::B_type;
    	using data_type = typename simulation_trait::data_type;
    	A_type m_A;
    	B_type m_B;
    public:
            Object(data_type const& data) : m_A(data), m_B(data) {}
    };
    Et enfin des spécialisations pour les différentes implémentations qui varient selon les stratégies de simulation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename Trait>
    class A{};
     
    template<>
    class A<simulation_traits::strategy1> { // implémentation 1};
     
    template<>
    class A<simulation_traits::strategy2> { // implémentation 2};
     
    // et pareil pour B
    Qu'en pensent les experts ? A quel point c'est une usine à gaz ? Pourquoi est-ce que manifestement le nom de Factory est mal choisi ?
    Et enfin, la question initialement posée (même si les choses ont un peu évoluées entre temps) : est-ce que je me plante à ne pas faire hériter les différents A et B d'une même interface ?

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

Discussions similaires

  1. [MySQL] afficher une seule fois un titre pour différents clients qui ont le même titre
    Par Prisss dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 01/12/2010, 10h52
  2. Réponses: 5
    Dernier message: 29/11/2010, 15h49
  3. Réponses: 9
    Dernier message: 08/01/2008, 10h55

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