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 :

Choisir entre programmation générique et programmation OO


Sujet :

C++

  1. #21
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    C'est une option pratiquement jamais utilisée.

    Extrait de la faq à propos du CRTP:
    Cela permet donc de simuler le polymorphisme d'héritage, en disposant de fonctions que l'on pourrait croire virtuelles. Cela s'avèrera toutefois gênant si vous voulez stocker, ici, des widget<T>, avec différents types pour T. Il vous faudra alors ruser, et notamment regarder le principe de Type Erasure.
    Et même si on voulait l'utiliser, le Type Erasure serait-il une solution ?
    (Et, tiens tiens, il me semble que je parlais de "simuler" le polymorphisme au post #11 de la page précédente)

  2. #22
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    C'est une option pratiquement jamais utilisée.
    A mon avis plus que tu ne le crois. Rediriger un flux, c'est pas vraiment une fonctionnalité inutile qu'on peut se permettre de jeter à la poubelle. En tout cas personnellement je l'utilise assez souvent.

    Et même si on voulait l'utiliser, le Type Erasure serait-il une solution ?
    Le type erasure nécessite un héritage publique pour fonctionner, ça ne ferait que déplacer le "problème".

  3. #23
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je commençais à avoir une tendance ces derniers temps à "templatiser" à tout va
    Tu es loin d'etre le seul. Joel semble atteint de ;a meme malalie:

    Citation Envoyé par Joel F Voir le message
    Si tu n'as pas besoin du polymorphisme au runtime, prog. générique.
    Si tu en as VRAIMENT besoin, polymorphisme dynamique à l'ancienne.
    Je continue a avoir beaucoup de mal a parler de conception -- pour moi la
    conception est toujours une affaire de compromis entre des contraintes
    contradictoires et ignorer ces contraintes rend la discussion sur la
    conception vaine.

    Oui, on peut présenter des techniques comme solution a des problèmes -- tu
    en présentes deux ici -- mais sans le contexte le choix de la meilleure
    technique révèle plus les hypothèses de ceux qui en discutent qu'autre
    chose.

    Sur le fond, toute solution a base de polymorphisme paramétrique est
    implementable en terme de polymorphisme d'inclusion, au pris d'une certaine
    lourdeur et d'une absence de verification statique de certaines proprietes
    certes, mais une fois les schemas d'implementation connus, la traduction
    est presque mecanique. L'inverse n'est pas vrai. Cette constation faite,
    il est tentant d'ignorer le polymorphisme parametrique (voyez Java a ses
    debuts, Go plus recemment) ou, extreme inverse, d'adopter la position de
    Joel.

    C'est oublier un peu vite que les points de vue sont differents et qu'il
    peut y en avoir un plus clair que l'autre suivant le contexte.

    C'est aussi oublier un peu vite des contraintes pratiques. Les
    implementations courantes des templates en C++ utilisant l'instantiation
    gloutonne (et l'abandon d'export n'est pas un facteur qui va changer cet
    etat de fait), toute utilisation d'un objet rends l'unite de compilation
    contenant cette utilisation dependante de la definition de l'objet plutot
    que simplement de sa declaration. Et c'est transitif. Les consequences
    sont parfois prohibitives en temps de compilation.

  4. #24
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par camboui Voir le message
    Auraient-ils pu remplacer le membre pointeur sur streambuf des iostream (basic_ios) par un paramètre template supplémentaire ?
    1/ La conception des IOStream date d'avant l'introduction des templates en C++. Oui, c'est aussi vieux que cela, donc la reponse est d'office non si on tient compte du contexte historique.

    2/ Meme hors du contexte historique, ca veut dire que tout ce qui effectue des IO doit se retrouver templatise sur ce parametre supplementaire. Je suis loin d'etre sur que ce soit viable -- en pratique on parametrise deja rarement sur charT.

  5. #25
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par camboui Voir le message
    le Type Erasure serait-il une solution
    Ce n'est jamais qu'implementer le polymorphisme parametrique a base de polymorphisme d'inclusion tout en utilisant une couche supplementaire de templates pour cacher tout le code repetitif dans cette implementation.

  6. #26
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Tu es loin d'etre le seul. Joel semble atteint de ;a meme malalie:
    Je dois etre la phase de dénie alors, vu que je me considére pas comme malade.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    L'inverse n'est pas vrai. Cette constation faite,
    il est tentant d'ignorer le polymorphisme parametrique (voyez Java a ses
    debuts, Go plus recemment) ou, extreme inverse, d'adopter la position de
    Joel.
    J'ai déjà une telle réputation avec mes 40 pauvres postes ou y a eu des fuites chez les RG ?

  7. #27
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Joel F Voir le message
    J'ai déjà une telle réputation avec mes 40 pauvres postes ou y a eu des fuites chez les RG ?
    Il ne faut pas aller plus loin que le message que j'ai cite.

    (Mais il ne faut pas faire partie des RG pour trouver des choses sur quelqu'un qui ne cache pas son nom; et je suis aussi les ML de boost même si je n'y participe pas.)

  8. #28
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Il ne faut pas aller plus loin que le message que j'ai cite.

    (Mais il ne faut pas faire partie des RG pour trouver des choses sur quelqu'un qui ne cache pas son nom; et je suis aussi les ML de boost même si je n'y participe pas.)
    Certes. Ma remarque se voulait humoristique de toute manière

  9. #29
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Merci Jean-Marc pour tes commentaires, ils m'apportent un regard nouveau.

    Voici une nouvelle écriture en sus de celles citées dans le premier post et ensuite par 3Darchi. C'est la même que la deuxième approche mais avec gestion automatique de durée de vie de fichier_base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Traitement
    {
    	shared_ptr<fichier_base> m_fptr;
    public:
    	Traitement(shared_ptr<fichier_base> const & fptr): m_fptr(fptr) {}
    	void Faire();
    };
    Il est vrai que sans contexte il est sans doute difficile de proposer le choix "définitif".
    Je pensais parvenir à une solution générique indépendante des exigences que pourraient imposer les projets à venir, quitte à wrapper la solution générique par la suite pour un usage éventuellement dynamique.

    Je reviendrai cepandant plus tard avec un contexte d'utilisation bien concret.

  10. #30
    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 Un peu de ménage...
    La partie de la discussion portant sur les IOstream a été déplacée dans la discussion Sur la rapidité des IOstream
    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

  11. #31
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par koala01
    La partie de la discussion portant sur les IOstream a été déplacée dans la discussion Sur la rapidité des IOstream
    Merci !

  12. #32
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Pourquoi hériter ? Pourquoi hériter publiquement ?
    Pour étendre l'interface de la classe selon la politique donnée. Par contre, il faut effectivement faire attention à ce que la situation s'y prête, c'est à dire qu'il faut que les implémentations de politiques soient telles que le LSP soit respecté. Cette petite astuce que j'ai présenté dans mon article est issue de Modern C++ Design, et je pense que Alexandrescu lui-même avait dû lire à propos de cette dernière quelque part sur artima, ddj, C++ report ou autre. En résumé, ce n'est pas à mettre entre toutes les mains, mais ça peut s'avérer utile.

  13. #33
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Sinon, concernant "OO vs Générique", c'est un non-problème. Il n'y a pas une approche qui est meilleure que l'autre. Les templates introduisent le polymorphisme paramétrique au niveau du type system. C'est à dire qu'on a des types paramétrés par d'autres types & constantes (dependent typing). Concrètement, c'est comme si on avait des fonctions "compile time" qui nous donnaient en retour des types.

    Exemple : je veux une "fonction de type" qui prend un type en paramètre et me retourne le type "pointeur vers le type reçu en paramètre".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T>
    struct foo
    {
      typedef T* type;
    };
    "Appel" de la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int i = 3;
    foo<int>::type pi = &i;
    "foo<int>" va demander au compilateur de générer la structure "foo" en remplaçant T par int partout. L'accès à "::type" va du coup nous retourner "int*". Vraiment, c'est comme quand on appelle une fonction normale avec des valeurs, sauf qu'on est à la compilation et que c'est avec des types.

    A côté de ça, on a l'héritage et le polymorphisme induit par les fonctions virtuelles, que tout le monde connaît assez bien (comparé à ce que j'ai évoqué ci-dessus). Le cas d'utilisation de l'héritage public avec fonctions virtuelles est très simple : les points de variation de comportement sont à l'exécution. Autrement dit, on veut qu'un même "code client" puisse induire une variation de comportement selon le contexte, et ce durant une même exécution du programme (c'est ce qu'il se passe quand vous faîtes un .show() sur un QWidget& par exemple -- cela peut être un QPushButton, un QLabel, etc). Donc là, selon le type réel de l'objet le comportement variera.

    Après, on a les fonctions templates, là c'est un poil différent. Elles nous permettent de faire varier le comportement sans avoir recourt à l'héritage et aux fonctions virtuelles, en jouant avec les templates. Je pense principalement à SFINAE (cf ici ou ici ou encore ici) qui va permettre de détecter des propriétés *STATIQUES* sur un type passé en paramètre à la fonction (ou détecté automatiquement -- mais dans tous les cas, c'est le type qui instanciera le modèle de fonction). Par exemple "si le type passé en paramètre a une représentation mémoire de plus de 8 bytes, alors on va lancer telle version de cette fonction, sinon ça sera l'autre".

    On voit que les 3 offrent des possibilités orthogonales.
    1/ les classes/structures templates offrent des fonctions sur des types, principalement. après, à partir du moment que des fonctions membres entrent en jeu, on se retrouve soit dans le cas 2/ soit dans le cas 3/. (j'ai exclu le cas trivial où une classe template est juste template parce qu'on a abstrait le type d'un attribut ou quoi de sorte à ce qu'il soit passé en paramètre, ça c'est de la "bête" généricité)
    2/ l'héritage et le polymorphisme d'inclusion associé permettent qu'un même code, compilé, linké & lancé, puisse réagir différemment selon le type réel d'un objet à l'exécution.
    3/ les fonctions templates non-triviales (utilisant SFINAE p.ex) vont permettre de faire varier le comportement selon le type avec lequel on les instanciera, en détectant des propriétés sur ces types *à la compilation*.

    A partir de là, on ne se pose plus la question de OO vs Templates. A la place, on réfléchit précisément à nos besoins, et on implémente le nécessaire pour y répondre. Cela peut nécessiter 1/, 2/ ou 3/, aussi bien qu'une combinaison des 3.

    Après, la simulation de virtualité avec le CRTP c'est très bien, mais ça ne permet pas de stocker des Base<Fille> ensemble, et là on va vouloir faire appel à la Type Erasure, mais finalement on aura quelque chose d'assez proche d'une simple hiérarchie, et on aura été obligé d'introduire la virtualité au niveau de la classe dont hériteront les Base<T>.

    En résumé, les classes/structures templates font reposer beaucoup sur le compilateur, car c'est le type system qui va vérifier des choses pour nous. Les fonctions virtuelles vont être gérées à coups de vtables, et là on a intérêt à bien s'être débrouillé car ce n'est qu'à l'exécution qu'on saura si c'est OK. La tendance aujourd'hui est de se reposer autant que possible sur le typage FORT et STATIQUE. Par exemple, on encourage souvent un boost::variant<A,B,C> plutôt qu'une classe Base bête et A, B et C qui en dérivent, et on implémente l'équivalent des fonctions virtuelles via des visitors pour le boost:variant (voir ici). En gros, on essaye de rapprocher la façon de faire du C++ de Haskell plutôt que Python/Java. Mais comme dit plus haut, ça n'a pas tellement de sens en soi dit comme ça. C'est juste que les gens se rendent enfin compte que l'héritage et la virtualité sont sur-utilisés, et découvrent la puissance des templates et les possibilités qu'ils offrent. Après, cela dépend vraiment de *où se trouve le point de variation*, pour choisir entre 1/, 2/ et 3/, ou une combinaison de ces derniers.

    Pour mieux comprendre et raisonner sur tout ça, je conseille :
    - Lecture des docs / codes de Boost, en commençant par les rationale (ils y dégagent les concepts manipulés par la bibliothèque, vous pouvez donc ensuite voir comment ces derniers sont représentés dans le code)
    - Multi-Paradigm C++ Design, de Coplien
    - Utilisation de langages fonctionnels statiquement et fortement typés (OCaml & Haskell sont deux très bons candidats pour ça)

    Bon je vais m'arrêter là, j'ai essayé de résumer autant que possible, mais si tu as des questions sur un des points, n'hésite pas.

  14. #34
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Alp Voir le message
    Pour étendre l'interface de la classe selon la politique donnée.
    Yep. Nous sommes d'accord.
    Sauf que ça n'avait rien d'évident dans son exemple. D'où ma question, car j'avais peur que le schéma d'héritage est été recopié tel quel. Or ce n'est pas parce qu'on bascule du côté du monde générique que le LSP doit être oublié. L'héritage garde un sens (fort).

  15. #35
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Alp Voir le message
    En gros, on essaye de rapprocher la façon de faire du C++ de Haskell plutôt que Python/Java. Mais comme dit plus haut, ça n'a pas tellement de sens en soi dit comme ça. C'est juste que les gens se rendent enfin compte que l'héritage et la virtualité sont sur-utilisés, et découvrent la puissance des templates et les possibilités qu'ils offrent.
    Voila, exactement. Moins le C++ ressemblera à JAVA et mieux il se portera.

  16. #36
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Je plussoie aussi, pour la forme, et parce qu'il faut faire passer le message :p.

    Exemple : je veux une "fonction de type" qui prend un type en paramètre et me retourne le type "pointeur vers le type reçu en paramètre".
    A noter que le terme usité est metafonction. Ici pour être plus précis c'est une unary metafunction.
    Comprendre une "fonction" qui prend en paramètre des types, et retourne un ou plusieurs résultats via un "nested" type (l'usage de nom type est la *norme* surtout si tu veux travailler avec des bibliothèques comme MPL et consor).

  17. #37
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Voila, exactement. Moins le C++ ressemblera à JAVA et mieux il se portera.
    Probablement. Mais est-ce sûr ?

    Quoi qu'il en soit, je trouve cette discussion assez étrange - pour la simple et bonne raison que personnellement, je ne vois pas l'intérêt d'avoir recours à la programmation générique pour régler un problème pour lequel il existe une solution (à priori) triviale. Si toutes les instances utilisées par la classe Traitement définissent les interfaces charge() et sauve(), c'est peut-être qu'il y a une bonne raison à cela : ce sont probablement des flux. si c'est le cas, les types F dérivent logiquement d'une classe de flux(*). A partir de là, le fait d'injecter des templates dans l'équation revient à utiliser un tractopelle (merci le dictionnaire de Firefox pour me proposer "tractoriste" et "contractuelle", mais il me semble que je souhaite vraiment écrire "tractopelle") pour ramasser 8g de poussière : c'est nettement plus compliqué que d'utiliser une petite pelle et une petite balayette, mais quelqu'un de particulièrement doué avec un tractopelle peut y arriver.

    Tony Cox a paraphrasé Knuth pour dire : "premature abstraction is the root of all evil", parce que les gens ont une trop nette tendance à partir en live lorsqu'ils veulent écrire du code moderne en C++ - en confondant "utilisation de templates" et "code élégant". Il faut se rappeler deux choses :

    1) le code doit être aussi simple que possible. Trop compliqué, il rends la maintenance difficile et augmente le risque de problème. L'introduction de la programmation générique en C++ impose au programmeur de bien en comprendre les enjeux, notamment pour tout ce qui concerne le comportement du compilateur et celui du code généré par le compilateur. La complexité ainsi introduite est bien souvent plus dommageable que l'apparente simplicité du code produit.

    2) la généricité n'a d'intérêt que si elle existe conceptuellement. Dans le cas du PO, cette généricité n'existe pas puisqu'il travaille sur des flux(*). A quoi bon dans ce cas forcer une apparence de généricité qui sera au final plus dommageable qu'utile ?

    (pour rappel à mes lecteurs favoris dont bon nombre viennent du monde doux et chalereux de DVP.com : j'ai déjà écrit sur le sujet il y a quelques mois)

    Je terminerais par demander : est-ce vraiment nécessaire d'avoir ici une classe Traitement ? Est-ce qu'une simple fonction libre prenant en paramètre une instance de F ne suffit pas ? (il convient de répondre non à cette question dès lors que plusieurs traitements sont définis et interchangeable (pattern strategy)).

    (*) : si ce n'est pas le cas, kaboum, c'est qu'il y a dans le code une transgression majeure du principe de responsabilité unique - car l'objet est à la fois un flux et autre chose.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  18. #38
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Probablement. Mais est-ce sûr ?
    Opinion personelle

    Citation Envoyé par Emmanuel Deloget Voir le message
    Si toutes les instances utilisées par la classe Traitement définissent les interfaces charge() et sauve(), c'est peut-être qu'il y a une bonne raison à cela : ce sont probablement des flux. si c'est le cas, les types F dérivent logiquement d'une classe de flux(*).
    ou modélise le Concept Flux, ce qui, au niveau abstrait est identique, sauf que modeliser un Concept demande de vérifier cette propriété au niveau des type et non du runtime. C'ets donc strictement la même chose (Alp reprend moi si je glisse).

    Citation Envoyé par Emmanuel Deloget Voir le message
    A partir de là, le fait d'injecter des templates dans l'équation revient à utiliser un tractopelle (merci le dictionnaire de Firefox pour me proposer "tractoriste" et "contractuelle", mais il me semble que je souhaite vraiment écrire "tractopelle") pour ramasser 8g de poussière :
    Firefox insiste pour que j'ecrive "emasculation" a la place de "encapsulation", je compatis donc.

    Citation Envoyé par Emmanuel Deloget Voir le message
    1) le code doit être aussi simple que possible. Trop compliqué, il rends la maintenance difficile et augmente le risque de problème. L'introduction de la programmation générique en C++ impose au programmeur de bien en comprendre les enjeux, notamment pour tout ce qui concerne le comportement du compilateur et celui du code généré par le compilateur. La complexité ainsi introduite est bien souvent plus dommageable que l'apparente simplicité du code produit.
    C'est un probleme d'education. Lorsque tu maitrise la chose, tout ce passe bien. La quasi totalité de mes code générique font genre 5-10 lignes dans un petite clique de classes et fonctions libres.

    Citation Envoyé par Emmanuel Deloget Voir le message
    2) la généricité n'a d'intérêt que si elle existe conceptuellement. Dans le cas du PO, cette généricité n'existe pas puisqu'il travaille sur des flux(*). A quoi bon dans ce cas forcer une apparence de généricité qui sera au final plus dommageable qu'utile ?
    La généricité vient du fait qu'il existe de concept de Flux en premier lieu

    Citation Envoyé par Emmanuel Deloget Voir le message
    Je terminerais par demander : est-ce vraiment nécessaire d'avoir ici une classe Traitement ? Est-ce qu'une simple fonction libre prenant en paramètre une instance de F ne suffit pas ? (il convient de répondre non à cette question dès lors que plusieurs traitements sont définis et interchangeable (pattern strategy)).
    La par contre on est plutot d'accord.

  19. #39
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Citation Envoyé par Joel F Voir le message
    ou modélise le Concept Flux, ce qui, au niveau abstrait est identique, sauf que modeliser un Concept demande de vérifier cette propriété au niveau des type et non du runtime. C'ets donc strictement la même chose (Alp reprend moi si je glisse).
    C'est tout à fait ça. Comme je l'ai dit, il s'agit de faire de la programmation C++ quelque chose de plus proche de la programmation Haskell que de la programmation Java. Ici nos concepts, ce sont l'équivalent des typeclasses, et qu'ils soient directement dans le langage ou pas, on s'en sort très bien. Mais encore une fois, si on a besoin que le point de variation du comportement soit à l'exécution, bien évidemment qu'on utilisera l'héritage ! Là encore, il n'y a pas de question à se poser, c'est encore le "non-problème" dont je parlais !

  20. #40
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Joel F Voir le message
    ou modélise le Concept Flux, ce qui, au niveau abstrait est identique, sauf que modéliser un Concept demande de vérifier cette propriété au niveau des type et non du runtime. C'est donc strictement la même chose (Alp reprend moi si je glisse).
    Je vois bien. Ceci dit, ce concept est modélisé dans un type statique (la classe de base des flux) et donc vérifié de manière statique dès lors qu'on utilise une classe dérivée de la classe flux. C'est effectivement strictement là même chose, dans le sens ou ce n'est même pas le runtime qui vérifie le concept - mais bien le compilateur. Par contre, la décision de l'algorithme a exécuter s'effectue au runtime.

    Citation Envoyé par Joel F Voir le message
    Firefox insiste pour que j'écrive "émasculation" a la place de "encapsulation", je compatis donc.
    Je me demande dans quelle mesure ce n'est pas un message de la communauté des développeurs de FF à la communauté des programmeurs...

    Citation Envoyé par Joel F Voir le message
    C'est un problème d'éducation. Lorsque tu maitrise la chose, tout ce passe bien. La quasi totalité de mes code générique font genre 5-10 lignes dans un petite clique de classes et fonctions libres.
    Qui dit éducation dit aussi niveau d'éducation. Si sur une équipe réduite tu peux espérer d'avoir un niveau d'éducation et des connaissances homogène, ce n'est plus le cas dès que tu élargis l'équipe. Tu ne peux pas espérer que tout le monde ait le même niveau de maîtrise, ce qui peut avoir de graves conséquences pendant le développement et la maintenance.

    Citation Envoyé par Joel F Voir le message
    La généricité vient du fait qu'il existe de concept de Flux en premier lieu
    Concept que l'on retrouve dans la C++SL, où les flux dérivent tous des mêmes classes std::istream et std::ostream. Je n'ai pas pour habitude de recopier le design des autres, par contre je m'interroge souvent sur le pourquoi de leurs choix. De temps en temps, ça a du sens, de temps en temps ça n'en a pas. Même si il est évident que la notion de templates est postérieure à la première implémentation des flux, force est de constater que l'implémentation retenue pour ces flux fait intervenir les templates. A partir de là, on peut se demander si il était vraiment nécessaire de faire dériver tous les flux d'une série de même classe, ou si c'est un véritable choix d'architecture. Je penche pour la seconde solution, et je pense en outre que c'est un bon choix : un flux peut être passé en paramètre à une fonction et le choix de l'algorithme a utiliser s'effectue au runtime.

    Après, je ne voudrait pas donner l'impression que je ne suis pas d'accord avec ce qui a été dit : je le suis (au moins en partie), même si je reste très circonspect sur tout ce qui concerne la création d'abstractions artificielles.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Discussions similaires

  1. Sous-programmes génériques
    Par Tonio12 dans le forum Langages de programmation
    Réponses: 22
    Dernier message: 26/02/2007, 20h07
  2. Réponses: 2
    Dernier message: 30/08/2006, 18h44
  3. retirer une entrée du menu/démarrer/programmes pr un user
    Par mathieu_r dans le forum Autres Logiciels
    Réponses: 8
    Dernier message: 27/03/2006, 10h24
  4. [JDK-5.0]Programmation générique
    Par Bobo59 dans le forum Langage
    Réponses: 2
    Dernier message: 01/05/2005, 20h17
  5. [Programmation générique] template - iterator_traits
    Par Paul Atreide dans le forum Langage
    Réponses: 2
    Dernier message: 14/03/2005, 23h09

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