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

Contribuez C++ Discussion :

L'avenir du C++


Sujet :

Contribuez C++

  1. #121
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par screetch Voir le message
    Pour etre plus precis le comportement est un jeu, la description est le gameplay (la vie du joueur, les degats de l'armes...) et la personne derriere l'editeur est un designer. Il est bien loin le temps ou les programmers decidaient du gameplay
    Marrant. Ce sont pour moi des exemples typiques de propriétés [1] pour lesquelles je ne voudrais pas de mutateurs (accesseur pourquoi pas).

    Mon abus de D&D et autres systèmes de règles me font dire qu'une chose (perso/objet) encaisse des points de dégats typés. On applique toutes les résistances, immunités et autres faiblesses (permanentes comme temporaires), et au final, l'état de la chose est modifiée (moins de points de vie, sorts perdus/volés, pertes d'attributs, ...). Et là, on n'a pas des mutateurs, mais des fonctions spécialisées

    Si c'est pour sortir les traitements des listes d'attributs, alors autant que les attributs soient publics. Inutile de faire semblant.

    C'est encore pire avec les systèmes simulationnistes comme Harnmaster où il n'y a plus de points de vie.

    Citation Envoyé par zais_ethael Voir le message
    a- En combinant de manière optimale String et StringBuilder, on obtient des complexités algorithmique pour le traitement des chaines de caractères meilleures qu'avec std::string.

    b- En dehors de ça, pour Jean-Marc: ok, on a compris que tu n'as pas besoin d'accesseurs parceque tu ne crées jamais d'objets qui sont une collection d'attributs, alors j'ai deux questions:
    - Comment tu fais?
    - Même si ta technique de conception OO est super au point, tu ne me feras pas avaler que le bon vieux exemple d'une classe voiture avec attributs couleur, longueur, ect... est objectivement mauvais et bon à jeter. Même si tu ne le fais jamais d'autres le font et peuvent tout de même être de très bon programmeurs, et pour eux les accesseurs sont utiles. Personnellement je connais le pl/sql, je le hais profondément, mais je ne vais pas prétendre pour autant que ça n'a de place dans aucune équipe de développement.
    a- si tu veux parler des concaténations, il faudrait comparer aux stringstream (je ne suis pas sûr qu'ils soient efficaces), ou à des concatenators -- cf p.ex. l'implémentation non standard de std::string dans les versions récentes de STLport. -- le genre de truc qui serat bien pour le C++09.

    b- J'accepte volontier que couleur et longueur sont des propriétés en lecture seule car on pourra les percevoir. => OK pour des accesseurs, pas pour des mutateurs.

    Contrairement à Mat007, j'accepte assez volontier les accesseurs (pour des raisons de debug, et de codage à la va-vite), et suis allergique aux mutateurs. C'est encore pire depuis que je cherche à déclarer toutes mes variables locales immuables.


    [1] Dans mon morceau de prose qui a été repris dans la FAQ, je faisais la distinction entre propriété et attribut. Ce sont deux concepts orthogonaux, mais ayant une intersection large qui introduit une confusion.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  2. #122
    screetch
    Invité(e)
    Par défaut
    je suis d'accord sur le terme propriete (ces champs nous les appelons comme ca!)

    de plus je suis d'accord qu'en general il est peu desirable de les muter au runtime. Sauf, comme je te l'ai indiqué, par un editeur (un game designer) qui modifie le jeu en temps reel.

    Je n'ai pas ete tres clair : Les attributs de vie du joueur font partie du comportement. Les proprietes de vie max d'une classe, les degats d'une arme sont bien des proprietes. Nous autorisons les designers a les muter alors que le jeu tourne pour accelerer le developpement.

  3. #123
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    a- si tu veux parler des concaténations, il faudrait comparer aux stringstream (je ne suis pas sûr qu'ils soient efficaces), ou à des concatenators -- cf p.ex. l'implémentation non standard de std::string dans les versions récentes de STLport. -- le genre de truc qui serat bien pour le C++09.
    Ben non justement, StringBuilder n'est pas plus optimisé que std::string (à moins que ce dernier ne soit mal conçu). Je parlais des comparaisons et des Maps pour String puis disais qu'une utilisation optimale de String et StringBuilder permettait une complexité égale ou moindre que std::string pour la plupart des opérations (d'après ce que je sais des stringstreams, ils utilisent un std::string en interne, la seule utilité est donc la surcharge des opérateurs de flux).

  4. #124
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par loufoque Voir le message
    À mon avis la seule manière de faire ça proprement c'est de travailler avec des chaînes de caractères "compile-time".

    Par exemple, on pourrait surcharger l'opérateur . ainsi :

    objet.foo

    appellerait en fait objet.operator.<boost::mpl::vector_c<char, 'f', 'o', 'o'> >();
    Pourrais tu détailler en quoi cette approche te semble plus intéressante que les deux autres régulièrement citées (mots clefs property, get et set, à la delphi/c#/COM et appel de fonctions sans parenthèses) ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #125
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Parce que c'est une approche générique, et non pas au cas par cas.
    Ce qui permettrait en particulier, de transmettre les membres quand on utilise des placeholders comme dans boost.lambda, ou encore de transmettre les membres quand on utilise du typage dynamique (smart references, boost.variant).
    On peut aussi l'utiliser pour en fait directement rediriger les membres (ou partie des membres) vers une std::map...
    Boost ftw

  6. #126
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 750
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 750
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    A propos des problemes avec les getter/setter, y'a cet article qui est interessant:
    http://blog.emmanueldeloget.com/inde...des-accesseurs

  7. #127
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Je trouve celui-ci plus intéressant : http://blog.emmanueldeloget.com/inde...-encapsulation

    Celui sur les accesseurs est assez anecdotique même si je suis également assez d'accord...

    MAT.

  8. #128
    screetch
    Invité(e)
    Par défaut
    Je ne suis pas d'accord du tout avec cet article.

    Le principe de l'encapsulation avec les set serait ici de publier "semantiquement" (j'espere que mes anciens collegues ne me lisent pas sinon ils vont rigoler) une valeur en en cachant l'implementation.

    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    template< class Key, class value>
    class Map
    {
    private:
      mutable pair<Key,value> cache;
      std::map<Key,Value>     impl;
    public:
      ...
      setValue(const Key& key, const Value& value)
      {
         cache = make_pair(key,value);
         impl[key] = value;
      }
    };
    La methode setValue porte mal son nom, car elle change la valeur du cache. D'apres cet article, je devrais l'appeler setValueAndUpdateCache. Je trouve cela completement faux; le cache est un detail d'implementation qui n'interesse pas l'interface publique de l'objet.

    La bounding box d'un objet 3d est un detail d'implementation; a chaque fois que j'ajoute un point, je ne suis pas sensé appeler la methode "setValueAndUpdateBoundingBox", c'est ca l'encapsulation aussi........

    donc c'est gentil mais non, les noms en set/get et les proprietés je continuerai a m'en servir pour decrire ce qui est publié de mon implémentation, sans tenir compte de l'implementation.


    un autre exemple est une machine a etat, en general changer d'etat entraine une modification du comportement un peu plus profonde (peut etre remplacer un etat par un autre, effectuer une action "onLeaveState" puis une "onEnterState"). Il est hors de question d'appeler autre chose que setState pour moi; que la machine a etat soit representee par un mecanisme complet ou par un simple enum qui est affecte par setState, celui qui utilise la machine a etat (c'est a dire le reste du jeu) il en a rien a faire, et appeler ca "setStateAndExecuteEnterLeaveCommands" est idiot puisque ca revele un comportement, qui peut d'illeurs changer.

    Donc, en bref, non, je m'oppose a la description formelle de ce que fait un setter, ce qui m'interesse dans l'interface pblique c'est l'abstraction, pas l'implementation.

  9. #129
    screetch
    Invité(e)
    Par défaut
    je critiquais le premier article et je viens de lire le second. Je trouve ces deux articles en contradiction l'un avec l'autre.

    Je suis aussi en desaccord avec sa definition de "set" et le lien qu'il donne vers le dictionnaire semble le contredire, il me semble.

  10. #130
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Bah c'est juste le terme 'set' qu'il critique je pense, en tous cas c'est comme ça que je le prends.
    En général je lui préfère 'update', mais bon ça fait plus de trucs derrière que juste une affectation.

    Là par exemple dans ta Map j'aurais pas mis 'setValue' mais 'add' ou 'register'...

    MAT.

  11. #131
    screetch
    Invité(e)
    Par défaut
    dans la map ce n'est pas un add, c'est un set!

    add impliquerait que ca n'existait pas avant. register, bof, ca me parait eloigné.

    Set : put, bring, or place into a specified state.

    en d'autres termes (enfin surtout en termes francais) :
    ajoute, amène ou place dans l'état specifié.

    Ce qui pour moi, signifie que lorsque l'on fait set :

    - il pouvait ne pas y avoir de valeur avant, ou bien y avoir une valeur (difference put/bring)
    - il peut y avoir un chemin a effectuer ou pas (l'idee bring le dit bien)

    donc set me parait de loin etre le meilleur terme dans ce cas!!!

    set implique pour moi l'etat final a atteindre sans se preoccupper de l'etat courant ni du chemin a accomplir. setState() est donc clairement un nom magique qui veut dire tout cela. Je crois egalement que setValue résume bien le fait d'ajouter ou de mettre a jour.

    Apres on peut tortiller du cul et dire "addOrUpdate" mais moi j'appelle un chat un chat, pas un "animal de la race des félins n'etant ni un tigre ni un guepard ni une panthere". question de concision.

  12. #132
    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
    Salut,

    Mais on pourrait très bien envisager une fonction (try)Update...

    Si, en plus, on lui fait renvoyer un booléen, au lieu de la déclarer vide, elle prend tout son sens

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(!mamap.Update(/*...*/)
    {
     
    }
    /*la suite */
    Mais il faut avouer que l'on est loin de l'idée que certains se font des "setters" (void setXXX)

    Et, de ce point de vue, purement sémantique, il n'a pas tord... set est généralement bien plus proche de "donne la valeur X à y de manière inconditionnelle" qu'autre chose

    [EDIT]la base du nom pourrait aussi bien être "(try)Modify" au lieu de (try)Update
    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

  13. #133
    screetch
    Invité(e)
    Par défaut
    je n'ai pas tres bien compris ce que tu voulais dire par la.

    set en anglais signifie non pas comme il l'a ecrit "initialiser avec une valeur" mais "apporter dans cet etat la". Il est donc tout a fait pertinent de mettre du code de verification de l'etat dans set, contrairement a ce qu'il dit. Il est pertinent de mettre du code dedans qui apporte a un etat precis.

    Un setter n'est pas juste fait pour faire m_machin = bidule.

    c'est soit un probleme de francais, soit un probleme d'anglais.

  14. #134
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 4 551
    Points
    4 551
    Par défaut
    J'ai vu que screetch m'avais aussi laissé un message (pratique, merci), et j'ai pu lui répondre de manière un peu plus précise.

    Avant de continuer, vous remarquerez que cet article est rangé dans la rubrique "Expériences" - je vais de ce pas le placer dans la rubrique "Opinions" qui a été créée ultérieurement, car c'était là sa principale raison d'être : donner mon opinion sur le sujet - sinon je l'aurais mis dans une des rubriques "Architecture...".

    Ceci dit, ce n'est pas forcément clair.

    Et mon "talent" (hum) pour embrouiller les lecteurs fait que l'article en question est assez difficile à saisir (pas dans le sens où la comprennette est secouée, mais dans le sens ou je ne dis pas ce que je souhaite réellement dire, et j'insiste sur des points de détails). Etrangement, ma réponse à screetch est peut-être plus claire que l'article original.

    En fait, ça se résume à ça: "Je propose surtout d'utiliser d'autres verbes, moins couramment utilisée, moins omniprésents que set et plus précis que ce dernier".

    Et screetch, pour ta map, storeValue() peut le faire aussi. Je crois. C'est moins idiomatique ceci-dit (bien que set() dans une map ne soit guère plus idiomatique en c++; vive operator[]()! ).
    [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.

  15. #135
    screetch
    Invité(e)
    Par défaut
    coucou

    euh je sais pas si je dois repondre ici ou dans ton blog, sans doute les deux.

    déjà pour la référence a mes collègues, passez, c'est une private joke ^^i désolé

    ensuite, ce que je reproche en fait est cité dans cette phrase :
    Ceci dit, la valeur que tu stockes [...] n'est pas une propriété directe de l'instance - elle est stockée dans un conteneur. Est-ce que cela peut avoir une influence? (c'est une question ouverte).

    la plupart (98 %) du code ecrit ressemble a ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    int m_value;
    float m_time;
    public:
        void setTime(float value);
        void setValue(int value);
    };
    La le set est un mauvais mot (sans doute) employé a tort et a travers, ce setter est mauvais et je n'irai pas cautionner le changement de valeurs internes comme cela.

    neanmoins, ce que j'essaye de faire en general ressemble beaucoup plus a cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Player
    {
        FILE* m_stream;
        Output* m_output;
    public:
        void setTime();
    };
     
    void Video::setTime(float time)
    {
        m_stream->seek( time * frameTime() * complex code + offset - age du capitaine);
    }

    ici, ma classe n'a pas de champ time, mais son interface publie une propriété qui est le temps : on peut recuperer le temps actuel dans la vidéo ou meme deplacer le curseur sur un temps particulier.

    Voila un exemple de setter qui ne me choque pas du tout! celui ci maintient la logique dans l'instance



    lorsque j'ecris le code plus haut, je permet la modification d'une valeu ou d'une autre independamment, sans vraie raison, juste pour que les gens puissent ecrire dedans. Dans ce cas autant etre franc et bidouiller le champ lui meme.

    Lorsque j'ecris ma classe player, elle possede son comportement interne ou le temps n'est pas vraiment representé (pas directement) mais ma classe "publie" dans son interface la propriété de temps, lequel agira sur l'implementation (le stream en l'occurrence) pour faire refleter la commande "setTime".

    Ne faites pas vraiment attention aux noms, je pense que la classe est loin d'etre propre, c'est juste un exemple pour montrer ce que je veux dire par encapsuler !


    je ne voudrai pas par exemple appeler cette methode "setStreamOffsetFromTime", cela montre l'implémentation de la classe, ni "adjustFrameToTime"

    a la rigueur, oui, "setPlayingTime" mais c'est tout quoi.

    donc moi je defend l'idee des accesseurs, des setteurs, a partir du moment ou cela permet de changer d'etat et pas juste d'ouvrir une breche sur le contenu de la classe. Si c'est pour bidouiller m_index, nan. Si c'est pour changer d'etat mais garantir la cohérence de l'état final, oui.

    Et dans ce cas, puisque l'utilisateur n'a pas besoin de savoir comment c'est implémenté a l'interieur, setXXX me parait un nom simple, qui laisse l'utilisateur dans l'ignorance. Mais en revanche, je passe un contrat avec mes getters/setters :
    - je represente un etat complet a travers les setters ou getters : il ne sera pas necessaire d'appeler
    setValue1
    setvalue2
    checkState
    si un tel besoin se font sentir, value1 et value2 sont "groupés" pour devenir une seule propriété ou alors un setter qui change les deux valeurs existent. il n'y a pas de fonction publique checkState; les propriétés ne sont pas décorellées
    - apres l'appel d'un setter, soit ca a fonctionné soit une exception a été lancée, donc l'etat de l'objet est toujours valable apres l'appel (en cas d'exception, tant que faire se peut j'essaye de ne pas changer l'état, je fais des choses assez basique pour que ca marche)

    il arrive que les champs se mappent directement vers des propriétés :
    ma classe Window publie un champ Renderer qui peut etre changé en runtime. Cela fonctionne : on peut changer en runtime le rendu de la fenetre en appelant setRenderer. Pour le coup c'est un champ mais ca pourrait etre representé autrement.


    Voila mon point! a prendre ou a detester!
    Dernière modification par koala01 ; 05/09/2007 à 17h41. Motif: code!=quote ;)

  16. #136
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    Bonjour,
    avant tout j'espere que je ne gacherai pas votre conversion forte interessante en m'imissant dans la conversion et pardon pour les accents manquants mais qwerty...

    Je suis tout a fait d'accord avec screetch pour la raison suivante : ce principe est celui de la logique mesuree du C++ : encapsulation. C'est a dire que l'objet est considere comme une entite complete et que si qq1 souhaite perturbe cette chose, elle reste malgre tout complete (enfin elle garde son sens, sa signification).
    CSQ : Si la valeur du "int" n'est pas soumise a restriction... autant le mettre public (sinon pourquoi s'embarrasser des public, private et protected). Si on souhaite controler la modification ou si en realite une information est cache, oui on est oblige de faire une methode pour. (et aussi et surtout pour faciliter la vie de l'utilisateur).

    Cependant, cette conception de base est peut-etre limitante (meme si je ne le pense pas) et concevoir des objets incomplet peut peut-etre se reveler tres utiles. (Bon j'avoue, j'ai pas d'exemple en poche).

    Ensuite si l'idee est de creer des standards... ben oui on peux limiter tout acces a l'objet a travers des methodes genre get, set et autre. Personnellement, je considere que c'est au choix du programmeur C++.

    Quand a savoir s'il faut mettre put, bring, etc. Ben pensez que l'un des principe du bon sens c'est que n'importe qui puisse comprendre l'action qu'il va entreprendre...
    Si le get fait plus qu'un get, il faut juste en parler dans la doc...

    Du moins c'est mon avis.

  17. #137
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 4 551
    Points
    4 551
    Par défaut
    Damned, j'en ai mis du temps pour répondre. Il faut me pardonner, je suis en train de quitter la Germanie où je vis depuis un peu plus d'un an pour retourner dans ma belle patrie provençale (et prendre un peu de vacances pendant que j'y suis).

    Citation Envoyé par screetch Voir le message
    coucou
    euh je sais pas si je dois repondre ici ou dans ton blog, sans doute les deux.
    Bah, n'importe

    Citation Envoyé par screetch Voir le message
    ensuite, ce que je reproche en fait est cité dans cette phrase :

    (...)

    la plupart (98 %) du code ecrit ressemble a ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    int m_value;
    float m_time;
    public:
        void setTime(float value);
        void setValue(int value);
    };
    La le set est un mauvais mot (sans doute) employé a tort et a travers, ce setter est mauvais et je n'irai pas cautionner le changement de valeurs internes comme cela.
    Personnellement, je trouve que là le nom de la fonction est correct, mais le principe est mauvais (= autant mettre la variable publique).

    Citation Envoyé par screetch Voir le message
    neanmoins, ce que j'essaye de faire en general ressemble beaucoup plus a cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Player
    {
        FILE* m_stream;
        Output* m_output;
    public:
        void setTime();
    };
     
    void Video::setTime(float time)
    {
        m_stream->seek( time * frameTime() * complex code + offset - age du capitaine);
    }
    ici, ma classe n'a pas de champ time, mais son interface publie une propriété qui est le temps : on peut recuperer le temps actuel dans la vidéo ou meme deplacer le curseur sur un temps particulier.

    Voila un exemple de setter qui ne me choque pas du tout! celui ci maintient la logique dans l'instance

    lorsque j'ecris le code plus haut, je permet la modification d'une valeu ou d'une autre independamment, sans vraie raison, juste pour que les gens puissent ecrire dedans. Dans ce cas autant etre franc et bidouiller le champ lui meme.

    Lorsque j'ecris ma classe player, elle possede son comportement interne ou le temps n'est pas vraiment representé (pas directement) mais ma classe "publie" dans son interface la propriété de temps, lequel agira sur l'implementation (le stream en l'occurrence) pour faire refleter la commande "setTime".
    Il y a setter et Setter - et comme j'ai dit, je ne considère pas ton exemple comme étant un Setter. Il s'agit à l'évidence d'une fonction dont le nom commence par set, mais en même temps elle ne manipule pas directement les propriétés de l'objet sur lequel elles s'appliquent.

    Selon ma propre définition interne que j'ai un mal fou à exprimer, ceci n'est pas un setter, mais est une encapsulation correcte d'une fonction précise - sans aucun doute. Personnellement, dans ma guerre personnelle contre les Mauvais Noms de Fonction et de Variables, j'ai tendance à toujours chercher un nom plus évocateur que setSomething(), même si setSomething() fait à peu près l'affaire - comme c'est le cas ici. Mais ne nous arrêtons pas au nom de cette fonction - il est valable, compréhensible, et c'est bien là le point important après tout.

    Citation Envoyé par screetch Voir le message
    Ne faites pas vraiment attention aux noms, je pense que la classe est loin d'etre propre, c'est juste un exemple pour montrer ce que je veux dire par encapsuler !
    OK, c'est noté (par contre, je n'ai rien contre l'emploi d'un sympathique tutoiement; quand on me donne du "vous", mes chevilles enflent et ça abime mes chaussures... . "Tu" n'est pas moins poli que "vous", même si c'est moins formel).

    Citation Envoyé par screetch Voir le message
    je ne voudrai pas par exemple appeler cette methode "setStreamOffsetFromTime", cela montre l'implémentation de la classe, ni "adjustFrameToTime"

    a la rigueur, oui, "setPlayingTime" mais c'est tout quoi.
    Moi non plus - mais ne va pas considérer que ma Quête du Nom Parfait (qui n'existe pas, bien évidemment) me ramène à ce type de nom. Si j'ai le choix entre setTime() et setStreamOffsetFromTime(), je prends le premier.

    Citation Envoyé par screetch Voir le message
    donc moi je defend l'idee des accesseurs, des setteurs, a partir du moment ou cela permet de changer d'etat et pas juste d'ouvrir une breche sur le contenu de la classe. Si c'est pour bidouiller m_index, nan. Si c'est pour changer d'etat mais garantir la cohérence de l'état final, oui.
    Et personnellement, je défends l'idée que le changement d'état d'un objet est défini en réponse à une action. Les deux positions ne sont pas incompatibles, bien sûr, mais j'évite l'utilisation de setters: si je dois initialiser une ou plusieurs valeurs avant de pouvoir effectuer une action particulière sur mon objet, je considère qu'il s'agit d'une faiblesse au niveau design (a chaque fois que j'exécute un setter, l'objet doit vérifier que son état reste cohérent. Plus j'ai de setters, plus le nombre de traitements particuliers et de vérifications différentes est important).

    Citation Envoyé par screetch Voir le message
    Et dans ce cas, puisque l'utilisateur n'a pas besoin de savoir comment c'est implémenté a l'interieur, setXXX me parait un nom simple, qui laisse l'utilisateur dans l'ignorance. Mais en revanche, je passe un contrat avec mes getters/setters :
    - je represente un etat complet a travers les setters ou getters : il ne sera pas necessaire d'appeler
    setValue1
    setvalue2
    checkState
    si un tel besoin se font sentir, value1 et value2 sont "groupés" pour devenir une seule propriété ou alors un setter qui change les deux valeurs existent. il n'y a pas de fonction publique checkState; les propriétés ne sont pas décorellées
    - apres l'appel d'un setter, soit ca a fonctionné soit une exception a été lancée, donc l'etat de l'objet est toujours valable apres l'appel (en cas d'exception, tant que faire se peut j'essaye de ne pas changer l'état, je fais des choses assez basique pour que ca marche)
    Et je fait exactement la même chose - sauf que j'évite setSomething() que je trouve trop imprécis Sont-ce les Trois Lettres de le Discorde? (et après, j'arrête avec les Majuscules sur les Mots).

    Citation Envoyé par screetch Voir le message
    il arrive que les champs se mappent directement vers des propriétés :
    ma classe Window publie un champ Renderer qui peut etre changé en runtime. Cela fonctionne : on peut changer en runtime le rendu de la fenetre en appelant setRenderer. Pour le coup c'est un champ mais ca pourrait etre representé autrement.

    Voila mon point! a prendre ou a detester!
    Enfin quelqu'un qui sait qu'on peut avoir plusieurs renderer à la fois et qu'il est par conséquent inutile voire dangereux que cette classe renderer soit un singleton. Tu ne veux pas enseigner ça aux débutants de GameDev.Net par hasard? (non, ne t'inquiète pas, on s'en charge au mieux de nos possibilités ).

    Plus sérieusement, et comme je l'avais dit dans mon commentaire sur mon blog, je pense sincèrement que tu vois juste sur un certain nombre de points - et en particulier sur celui de la simplicité du nom: si setSomething() est simple, idiomatique et suffisamment explicite, la quête d'un meilleur nom est au mieux une perte de temps, au pire un équivalent intellectuel improductif de la recherche du plaisir. Il est évident que lorsque je réalise une architecture, je m'adapte au besoin de mes clients - et aussi à ses faiblesses. Si le client est représenté par quelqu'un qui est contre la CSL, je vais tenter de lui expliquer l'intérêt de la librairie standard - si ça ne marche pas, je ne vais pas me battre contre lui (c'est lui qui paie à la fin, quand même). Si mes interlocuteurs sont des développeurs avec peu d'expérience en conception objet, je vais leur donner quelques informations mais je vais surtout adapter mon style à quelque chose qu'ils peuvent appréhender, parce que je ne serais plus là lorsqu'ils feront la maintenance - ils doivent donc se sentir à l'aise avec l'architecture. Au final, il est aussi courant pour moi de renommer une fonction qui, au départ, avait un nom qui me convenait en setSomething(). Je n'aime pas forcément, mais en même temps, ça ne va pas m'empêcher de dormir.
    [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. #138
    Membre expérimenté
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Points : 1 419
    Points
    1 419
    Par défaut
    encapsuler les acces a une variable permet aussi par exemple d'envoyer un message ... ce n'est jamais bien de mettre des variables publiques (par experience), mais ce n'est pas forcement mieux de se retrouver avec un objet et que des methodes get/set. C'est courant en Java à cause des javabeans, mais je ne pense pas qu'il faille l'appliquer aveuglement au C++. Il vaut mieux definir des methodes pour modifier le comportement plutot que les etats internes.

  19. #139
    Membre confirmé

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Points : 527
    Points
    527
    Par défaut
    L'utilisation des properties dans la VCL a révolutionné la programmation Windows, avec l'apparition de Delphi, C++ Builder, sa copie subséquente Winforms, en repoussant MFC dans les oubliettes (pour ceux qui ne sont pas familiers, en gros on a remplacé les Petzolderies Simonyiesques par des instructions limpides du genre "Fenêtre.ElementGraphique.Propriété = Application.Valeur;", ce qui, certes, déclenche silencieusement une cascade d'horreurs système, mais met en évidence l'intention du programmeur et transforme totalement la maintenance, la productivité individuelle, la cohésion du travail d'équipe (pas d'accumulation / interaction de ptites zastuces personnelles pour simplifier MFC), et la fiabilité des gros projets comprenant une forte dose d'IHM).
    Voilà donc un exemple industriel flagrant, massif, d'intéret d'encapsuler des comportements complexes par des properties, en ne laissant apparaitre que l'intention du programmeur, et même en la modélisant précisément sous forme de liste d'attributs et non pas d'actions systèmes sous jacentes à accomplir. Je ne pense pas qu'on change vraiment d'avis une personne particulière en citant un exemple, si répandu soit-il. En revanche, c'est significatif du fait que l'avis en question est au minimum à mettre en question.
    "Maybe C++0x will inspire people to write tutorials emphasizing simple use, rather than just papers showing off cleverness." - Bjarne Stroustrup
    "Modern C++11 is not your daddy’s C++" - Herb Sutter

  20. #140
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 27
    Points : 46
    Points
    46
    Par défaut
    Citation Envoyé par screetch Voir le message
    la plupart (98 %) du code ecrit ressemble a ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    int m_value;
    float m_time;
    public:
        void setTime(float value);
        void setValue(int value);
    };
    La le set est un mauvais mot (sans doute) employé a tort et a travers, ce setter est mauvais et je n'irai pas cautionner le changement de valeurs internes comme cela.

    neanmoins, ce que j'essaye de faire en general ressemble beaucoup plus a cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Player
    {
        FILE* m_stream;
        Output* m_output;
    public:
        void setTime();
    };
     
    void Video::setTime(float time)
    {
        m_stream->seek( time * frameTime() * complex code + offset - age du capitaine);
    }

    ici, ma classe n'a pas de champ time, mais son interface publie une propriété qui est le temps : on peut recuperer le temps actuel dans la vidéo ou meme deplacer le curseur sur un temps particulier.

    Voila un exemple de setter qui ne me choque pas du tout! celui ci maintient la logique dans l'instance



    lorsque j'ecris le code plus haut, je permet la modification d'une valeu ou d'une autre independamment, sans vraie raison, juste pour que les gens puissent ecrire dedans. Dans ce cas autant etre franc et bidouiller le champ lui meme.

    Lorsque j'ecris ma classe player, elle possede son comportement interne ou le temps n'est pas vraiment representé (pas directement) mais ma classe "publie" dans son interface la propriété de temps, lequel agira sur l'implementation (le stream en l'occurrence) pour faire refleter la commande "setTime".
    Sauf qu'en n'utilisant un setXXX uniquement pour les propriétés qui ne sont pas représentées par un champ, l'utilisateur de votre classe devra utiliser 2 sémantiques distinctes pour manipuler d'un côté la propriété temps de la vidéo (il utilisera setTime() ), et d'un autre côté une autre propriété qui, elle, sera accessible directement par le champ (public) lui-même.
    En séparant ainsi dans votre interface publique les propriétés qui sont implémentées par un champ d'une part (en laissant ce champ en public), et celles qui ne sont pas implémentées par un champ d'autre part (en fournissant une méthode setXXX), vous exposez du coup les détails d'implémentation de votre classe.
    L'avantage d'utiliser setXXX y compris pour accéder directement à un champ (comme vous donnez l'exemple dans votre première classe) est dès lors pour l'utilisateur de ne pas voir la différence entre lorsqu'il manipule directement le champ et lorsqu'il manipule une propriété qui n'est pas supportée par un champ. Ce qui offre AMHA une meilleure abstraction.

Discussions similaires

  1. [Débat] MERISE versus UML ? Avenir de MERISE ?
    Par Matthieu Brucher dans le forum Méthodes
    Réponses: 51
    Dernier message: 15/02/2022, 17h32
  2. Quel avenir du C++ par rapport au C# ou à Java ?
    Par phpdev dans le forum Débats sur le développement - Le Best Of
    Réponses: 209
    Dernier message: 09/11/2009, 02h25
  3. L'avenir est-il au PHP ?
    Par Manolo dans le forum Langage
    Réponses: 468
    Dernier message: 11/02/2008, 18h54
  4. L'avenir du BDE et des SQL Links révélé ! <officiel>
    Par Merlin dans le forum Bases de données
    Réponses: 12
    Dernier message: 02/06/2006, 10h18
  5. Quel avenir pour les outils de génération de code ?
    Par Bruno75 dans le forum Débats sur le développement - Le Best Of
    Réponses: 5
    Dernier message: 05/11/2003, 18h30

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