ça se ferait très bien en C++ si on disposait de surcharge de l'opérateur point (la fonction prendrait en fait une chaîne de caractères "compile-time") et de reflexion à la compilation appropriée.
ça se ferait très bien en C++ si on disposait de surcharge de l'opérateur point (la fonction prendrait en fait une chaîne de caractères "compile-time") et de reflexion à la compilation appropriée.
Ha bah, voila un avis bien tranché que j'ai beaucoup de mal à comprendre.
Si on considère une conception OO détachée du langage (pour faire simple: un modèle de classes UML, et on oublie le C++), en quoi peux-tu considérer que ce soit mal de mettre une propriété dans une classe? En sachant qu'une propriété est "un peu comme un attribut" mais en plus maléable, ce qui n'est pas pour déplaire au fans d'interfaces.
Si ce n'est pas déja le cas ce n'est pas sans raison, je vois difficilement comment adapter un tel fonctionnement en C++. Mais même en admettant que ce soit possible je ne vois pas non plus en quoi ça faciliterait l'émulation d'accesseurs.Envoyé par loufoque
J'avoue que l'exemple que j'ai pris n'est pas forcément bien choisi, puisqu'il est vrai qu'en général la position des objets dans une boîte de dialogue dépend d'un gestionnaire de layout. Maintenant, dans une application de type dessin, ou l'utilisateur manipule les coordonnées des objets à la souris, ça peut avoir plus de sens.
Et pour des éléments plus standard d'une IHM, il y a pléthore de choses pour lesquelles une propriété avec ses accesseurs me semble l'abstraction naturelle. Par exemple, pour un bouton, le texte, l'icône, le style d'affichage, les couleurs (soit en RGB, soit en rôle dans une palette de couleurs)... Tous me semblent des chose que l'utilisateur peut vouloir lire ou modifier manuellement, à l'aide d'accesseurs.
J'ai joint une copie d'écran des propriétés exposées d'un bouton dans .NET. Il y en a peut-être quelques unes qui mériteraient un traitement plus global que par une propriété isolée, par exemple le numéro d'ordre pour le bouton tab, mais pour la plupart, cette notion me semble usuelle.
En fait, en plus de l'IHM, il y a une autre catégorie d'objets pour lesquels la notion de propriété me semblerait une bonne chose, ce sont pour des petits objets, généralement des value types, qui semblent autant se définir par ce qui les compose que par un comportement.
Par exemple, un complexe me semble naturellement avoir quatre propriétés : real, imag, arg, abs. Une couleur me semble avoir les propriétés R, G, B et A. Une grandeur physique une valeur et une unité...
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.
Les setter/getter donnent des objets une vision "collection d'attributs indépendants". J'arrive très rarement à ce genre d'objets.
Le seul exemple donné jusqu'à présent -- et je crains que sans exemples convainquant, je resterai sur ma position -- me semble être bien mauvais. Je suis très loin d'être un spécialiste des IHM, mais la taille d'un widget en contenant d'autres ne devrait pas être à mon sens quelque chose que n'importe qui peut modifier. A priori, la taille du widget de plus haut niveau n'est pas fixée par le programme (il peut en proposer une, mais ce n'est qu'une proposition) mais par l'utilisateur. Après, le programme fixe le placement des widgets contenu en fonction de la taille choisie par l'utilisateur.
Pourtant ça s'implémente en bibliothèque et ça marche parfaitement...Si ce n'est pas déja le cas ce n'est pas sans raison, je vois difficilement comment adapter un tel fonctionnement en C++. Mais même en admettant que ce soit possible je ne vois pas non plus en quoi ça faciliterait l'émulation d'accesseurs.
C'est juste qu'il faut écrire soit-même les informations de réflexion pour chaque classe concernée, et que ce n'est pas aussi joli que obj.name mais obj.call<'n', 'a', 'm', 'e'>() au mieux.
l'interet de mettre des get/set c'est de pouvoir faire plus que m_index = value;
certains composants "publient" leur interface via un etat (par exemple un booleen)
setState(value) declenche alors un changement d'etat plus consequent, une serie d'operations qui passent l'objet de l'etat A a l'etat B.
mais vu de l'exterieur, l'etat est publie comme un simple enum.
Les classes de donnees regroupant un sensemble de valeurs sont egalement tres pratique; ca s'appelle separer la description et le comportement tout connement. Un programme qui ne contient que du comportement ferait mieux d'etre en C. Un programme contenant du comportement et de la description est en general mieux ecrit en C++. On peut choisir de grouper le comportement et les donnees ou les separer, le comportement travaillant sur des donnees qui lui sont attachees.
Je ne comprend pas bien le proces contre les proprietes, si on est contre les proprietes on est contre la description, on fait un programme qui, lorsqu'il doit etre "tweaké", doit etre recompilé. Ca depend sans doute des domaines d'application mais le fait d'introduire de la description et de la publier d'une mainiere ou d'une autre me parait tres confortable, meme si pas indispensable
screetch, j'ai bien compris que les proprietes permettaient une syntaxe plus legere que des set/get. Mais je conteste l'interet des deux: mes objets ne sont pas des collections d'attributs independants, vision que favorisent les set/get sous n'importe quelle forme syntaxique. Quand j'ai des attributs, ils sont generalement uniquement lisibles, soit qu'ils sont fixes pour la duree de vie de l'objet, soit que les modifications se font par des API qui font plus que ca et dont le nom indique clairement la fonction. Les cas ou j'ai bien des set/get, je les rescend comme des verrues en attente d'etre enlevees ou presentes pour des raisons historiques. Je ne vois pas l'interet d'alleger l'utilisation de verrues.
Comme je crois l'avoir precise, il est possible que ma perception soit liee au domaine dans lequel je travaille ou bien a mon style de conception. Mais pour me faire changer d'avis il me faut des choses plus convaincante que simplement "certains composants "publient" leur interface via un etat".
(Tiens, je viens de remarquer qu'il y a un message de Loic que je n'ai pas lu).
Il faudrait que je regarde ca plus en detail. Mais si je connais mal les IHM graphiques, c'est entre autre parce que chaque fois que je veux les regarder d'un peu plus pres, j'ai l'impression d'une complexite sans rapport avec la nature du probleme (en tout cas sans rapport avec la nature des problemes que je cherche a resoudre). Et j'arrive pas a savoir si elle est intrinseque ou si elle resulte d'un mauvais choix d'organisation.
Les classes valeurs, j'ai tendance a les faire non mutables, ce qui est incompatible avec la notion de proprieteEn fait, en plus de l'IHM, il y a une autre catégorie d'objets pour lesquels la notion de propriété me semblerait une bonne chose, ce sont pour des petits objets, généralement des value types, qui semblent autant se définir par ce qui les compose que par un comportement.std::string est un bon exemple des problemes qui arrivent quand on a une semantique de valeur combinee avec de la mutabilite.
Je pense qu'une des raisons est qu'avoir une IHM fonctionelle ne demanderait probablement pas tout ce qui est disponible. Avoir un IHM fonctionelle et faisant plaisir aux graphistes/chefs de projet/responsable marketing demande souvent de régler de manière non usuelle, et manuelle, nombre de petits détails, ce qui oblige donc à une explosion de l'interface pour permettre tous les cas non usuels possibles.
Je n'ai pas cette habitude. Mais je n'ai jamais particulièrement réfléchi sur le sujet. Je pense que je fais juste comme dans les exemples que j'ai du voir quand j'ai appris la POO, ou comme dans la SL. Tu peux rappeler les avantages ?
Du moins pour les propriétés en écriture. Typiquement, quand je code en C# (langage avec des propriétés), je pense qu'à vue de nez, la moitié de mes propriétés au moins ne sont accessibles qu'en lecture.
Des strings non mutables ne sont pas non plus la panacée. Elles ont comme effet, d'après ma faible expérience sur le sujet, de recopier la chaine bien plus souvent qu'il n'est nécessaire. D'où les stringBuilders qui apparaissent dans les langages ayant fait ce choix, ce qui complique un peu l'apprentissage (j'ai entendu parler de gros problèmes de perfs dans des vrais programmes Java résolus par l'utilisation judicieuse de StringBuilder, ce qui prouve que les gens ne les utilisent pas assez).
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.
Tout dépend de quel aspect t'intéresse.
Par exemple, comparer deux std::string est une opération très coûteuse : elle compare individuellement chaque caractère.
Or, avec du partage implicite, il suffit de comparer un pointeur.
C'est pour cette raison, en particulier, qu'utiliser une std::map<std::string, quelquechose> ce n'est pas terrible.
Ne serait-il pas preferable de chercher un moyen plus propre (eventuellement dans le langage) de regler cela plutot que d'en mettre la responsabilite a l'exterieur.
Ca me semble mieux correspondre a la nature des choses. Une valeur est une valeur, on ne la change pas. On change eventuellement une variable contenant une valeur en assignant une autre. (Oui, il peut y avoir un probleme de perf, d'ou le generalement).
Il y a aussi le cas des classes tuples avec tous les membres publics. Mais alors, ce n'est que des simples conteneurs sans avoir d'invariant a maintenir et les proprietes ne conviennent pas (sauf peut-etre pour facilite le refactoring).
Ca ne me generait pas du tout de pouvoir appeler des fonctions sans le () final (j'ai fait assez d'Ada pour etre familier avec cela)... mais je ne suis pas sur que c'est a ajouter au C++ en ne le permettant que dans certains cas et permettre tous les cas est impossible car cela casserait trop de code existant.Du moins pour les propriétés en écriture. Typiquement, quand je code en C# (langage avec des propriétés), je pense qu'à vue de nez, la moitié de mes propriétés au moins ne sont accessibles qu'en lecture.
(Note qu'une fois qu'on a cela, il suffit d'un proxy pour avoir les proprietes).
Il vaut mieux avoir une implementation qui GC le contenu.Des strings non mutables ne sont pas non plus la panacée. Elles ont comme effet, d'après ma faible expérience sur le sujet, de recopier la chaine bien plus souvent qu'il n'est nécessaire.
De mon point de vue, c'est exposer quelque chose qui peut etre fait dans l'implementation d'une classe de string non mutable.D'où les stringBuilders qui apparaissent dans les langages ayant fait ce choix, ce qui complique un peu l'apprentissage (j'ai entendu parler de gros problèmes de perfs dans des vrais programmes Java résolus par l'utilisation judicieuse de StringBuilder, ce qui prouve que les gens ne les utilisent pas assez).
Bonjour, es que quelqu'un pourrai expliquer ce que veut dire "string non mutable" et "string mutable"? je ne comprend pas trop ce que vous voulez dire
merci
Salut,
Non-mutable c'est lorsque toutes les méthodes sont 'const' et que pour effectuer une modification tu appelles une méthode qui te renvoit un (en général nouvel) objet modifié mais qui ne modifie pas l'objet initial.
Mutable c'est lorsque tu peux directement modifier l'objet au travers d'une méthode.
Par exemple en C++ les 'strings' sont mutables, en Java elles sont non-mutables.
MAT.
Jean marc, j'ai dit que l'interet des get/set etait de pouvoir faire PLUS (a l'heure actuel) que m_chose = bidule ^^
comme je te l'ai dit, la ou je bosse nous separons le comportement de la description. Si tu ecris du comportement, ca n'a pas de sens d'ecrire des set et peu de sens d'ecrire des get (lire un comportement, say bizarre)
Par contre pour des donnees de description, ca a du sens de les lire et de les changer
nous avons donc 3 gros modules :
- le comportement : le code, pas de get/set
- la description : des get/set, modifier la description change le comportement et le comportement peut changer une description pour modifier un autre comportement, etc
- l'editeur : permet de changer les donnees (offline ou online, c'est a dire alors que le module tourne) et changer le comportement.
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
donc voila comment on se sert des get/set, le fait d'avoir des proprietes au lieu des get/set a peu d'importance mais ca reste du sucre syntactique, ca a jamais ete necessaire mais des fois pratique.
Je suis complètement de l'avis de Jean-Marc.
Un mutateur ne me dérange pas spécialement, après tout c'est quand même quelque part une demande de traitement, bien que minimale.
Par contre je suis particulièrement allergique aux accesseurs qui vont à mon sens à l'encontre de l'élégance et de la simplicité d'un design orienté objet.
Dans la grande majorité des cas les accesseurs n'ont pas lieu d'être et ils participent surtout à la vision procédurale du code :
"oh tiens j'ai besoin de telles données pour effectuer le traitement que je suis en train d'écrire => get get à droite get get à gauche et voilà !"
C'est pas tant le fait d'éclater l'encapsulation qui me dérange que celui d'inverser le flux d'exécution :
si A utilise un accesseur dans B on va se dire que A manipule B alors que c'est quelque part l'inverse puisqu'en fait B envoie des données vers A.
Quand on commence à alterner les appels de demande de traitement et les appels à des accesseurs c'est là que le code devient spaghetti et qu'il perd son bel ordonnancement linéaire du flux d'exécution des entrées jusqu'aux sorties.
Je partage tout à fait ce sentiment d'échec d'avoir à mettre un accesseur à un endroit, je suis reste persuadé qu'on peut faire mieux.
Après que ça soit ajouté ou non dans le language ça m'est un peu égal, de toute façon il y a déjà une sur-utilisation systématique et je ne pense pas que ça change grand chose...
MAT.
Une petite remarque sur les strings java: il y a plusieurs raisons non citées pour lesquelles il sont non mutables.
Tout d'abord, le java ne permet pas la const-correction. Donc, si String était mutable et qu'on concevait une classe avec un... accesseur en lecture seule, rien n'empecherait de modifier le string (illogique, vu qu'en lecture seule).
Ensuite, il y a aussi une certaine utilité pour l'optimisation si on sait bien s'en servir, nottament pour les comparaisons. En java, tous les objets sont sensés proposer la méthode hashcode, qui renvoie un crc32 des parties identifiantes de l'objet. Pour les strings, le calcul de ce crc se fait à la création du string. Donc, lors d'une comparaison case sensitive on commence par comparer les réfèrences, puis on passe au hashcode et ensuite seulement à une vérification caractère par caractère. C'est aussi très utile pour la création de Map (classement par crc dans un arbre binaire). Si String était mutable, ce serait impossible.
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.
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.
J'ai des classes qui sont une collection d'attributs. Les membres sont alors tous publics et je n'ai que faire d'ajouter du comportement.
J'ai aussi des setter/getter, mais comme je l'ai signale plus haut, la plupart je les ressens comme des verrues soit en attente de refactorisation, soit a conserver pour des raisons historiques. Je ne suis pas parfait ni ne travaille pas dans un environnement ideal. J'essaie simplement d'etre pragmatique et de favoriser les pratiques que je considere comme saines. J'essaie aussi de m'instruire, en cherchant a comprendre pourquoi certains veulent favoriser des conceptions qui me semblent batardes; ce n'est pas impossibles de me faire changer d'avis -- il suffit d'avoir des arguments convainquants.
Donne moi un exemple qui ressemble a quelque chose et j'y reflechirai. Loic est en train de me convaincre qu'il y a un probleme dans le cas des IHM. Pour le moment je cherche a le comprendre a mes rares moments perdus. J'en suis a me demande si une solution plus propre ne serait pas autre chose. Peut-etre un moyen plus leger de creer des classes derivees (eventuellement meme non nommee).- Comment tu fais?
Je n'en sais rien. Je suis certainement plus un specialiste de mon domaine qu'un specialiste de la POO. Je manque d'experience dans d'autres domaines que le mien, c'est certain. Et je ne considere pas la POO comme une panacee universelle -- voir mes messages sur le sujet par ailleurs.- Même si ta technique de conception OO est super au point,
Donne moi un probleme reel. C'est le genre d'exemples utilises pour exposer la POO qui me semblent plus nuisibles que profitables parce qu'ils sont tellement simplifies qu'ils forcent des solutions denaturees qu'on enseigne comme exemples a suivre.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.
Est-ce qu'il y a en a tant que cela qui sont convaincus que le C++ serait mieux avec que sans? J'ai trouve trois papiers du commite. Par ordre du plus recent au plus vieux.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.
- David VdV en entete d'un document presentant les properties de C++/CLI: "This document is neither a proposal to include this extension in standard C++, nor an endorsement of this extension by the author"
- Lois Goldthwaite a bien ecrit "C++ Properties -- a Library Solution", mais en lisant les deux premieres pages, on a l'impression d'un requisitoire contre la notion en C++ "I can't help feeling that is an effort to impose an alien idiom in C++", "I think this is A Bad Idea", "summary of a member having about a decade of experience with property: properties made our code easier to write, but immensely more difficult to maintain", "other member experience: very elegant and usable in Delphi, rather less in C++" -- etre aussi peu convaincue de l'interet de qqch qu'on presente est extraordinaire.
- le plus positif est le plus vieux: Borland (pas d'auteur individuel) presentant les extensions de leur compilateur.
les papiers sur les proprietes parlent elles däajouter des extensions qui permettent de les interroger en runtime par leur nom ? de fournir un vrai RTTI avec introspection ?
ou juste une methode de feignasse qui veut pas ecrire les parentheses ?
À 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'> >();
objet.foo2(arg1, arg2)
appellerait en fait objet.operator.<boost::mpl::vector_c<char, 'f', 'o', 'o', '2'> >(arg1, arg2);
Ensuite, pour pouvoir bien exploiter ça (en particulier pour pouvoir directement appeler les réelles fonctions), il faudrait des outils d'introspection à la compilation qui permettent à partir du nom d'un membre de l'appeler, par exemple.
Partager