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 :

structures simples : services or not services [Débat]


Sujet :

C++

  1. #21
    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
    Citation Envoyé par Bousk Voir le message
    Et à laisser mentir l'utilisateur au reste de son programme sur sa classe Position qu'il peut passer sans souci en référence ou par copie, en tous cas non constantes, parce que "je m'en moque, derrière j'ai accès uniquement à des membres const" ?
    Dans la genre initiateur de mauvais réflexes, ça se pose là.
    A priori, la nature immuable d'un objet ne devrait absolument pas entrer en ligne de compte dans le respect de la const correctness.

    La première est le résultat d'une constatation toute simple : en changeant une valeur, tu obtiens une autre valeur, alors que la deuxième est une bonne pratique qui apporte une aide efficace à la programmation, permettant au compilateur de nous indiquer où notre raisonnement pourrait être pris en défaut

    Bien sur, il y aura toujours des imbéciles qui suivront ton raisonnement, j'en conviens, mais ils feront de toutes manières partie de la tranche de personnes qui n'ont simplement pas compris l'intérêt de la const correctness de manière générale.

    Par contre, la nature immuable de la valeur leur évitera, malgré tout, de faire n'importe quoi
    J'imagine aussi qu'aucun de vous n'utilise jamais de POD alors.
    Si, mais de manière particulièrement limitée.

    Généralement, je limite l'utilisation de POD au cas de structures imbriquées, déclarées dans une accessibilité privée (ou au pire protégée) car ce ne sont que des détails d'implémentation.

    De cette manière, je peux modifier "à loisir" (ou peu s'en faut) ce pod en fonction de mes besoins, sans que cela n'interfère en quoi que ce soit au niveau du code utilisateur .

    Ce n'est, au final, qu'une manière de respecter OCP, non
    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

  2. #22
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce n'est pas une question de mentir, mais une question qu'on ne change pas un membre individuel d'un objet avec sémantique de valeur: On fait des copies différentes.

    Je te le dis tout de suite, en C# ou en C++/CLI, j'utiliserais directement une struct/value class avec membres constants (readonly/initonly), que j'exposerais directement nus; mais c'est parce qu'en .Net, de tels types sont affectables.
    En C++, ce n'est pas le cas: On est réduit à ces trois options:
    • Renoncer à l'affectation
    • Ne pas déclarer les membres const (violation de la sémantique de valeur)
    • Utiliser des accesseurs.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #23
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Dans un monde de contraintes en tout cas, car dans l'embarqué c'est bien de cela qu'il s'agit même si les deux sont étroitement liés, j'imagine qu'on doit être obligé de faire des choix du style "tanpis pour la robustesse, la maintenabilité, etc, il faut surtout que je penses en dessous des 3ko de mémoire"... mais après ça devient de la déformation professionnelle de vouloir procéder comme cela partout.

    Typiquement si vous avez de quoi vous faire plaisir avec les ressources, faut en profiter pour faire un truc plus maintenable et plus robuste, sinon autant arrêter le C++ et faire de l'assembleur directement. Les "tableaux nus" du C sont aussi connus pour être plus performants que les vector (d'après un article que j'ai lu sur des benchmarks effectués lors d'un concours Intel), faut-il arrêter de s'en servir pour autant ?
    Nullius in verba

  4. #24
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    De plus, un compilateur C++ décent n'a aucune raison de ne pas inliner un accesseur trivial, vu que ça gagnera forcément tout à la fois en taille, vitesse et localité. Un tel inlining n'a pas de coût.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #25
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    De plus, un compilateur C++ décent n'a aucune raison de ne pas inliner un accesseur trivial, vu que ça gagnera forcément tout à la fois en taille, vitesse et localité. Un tel inlining n'a pas de coût.
    Le compilateur va inliner si on est dans le meme fichier (ou si l'interface chaise clavier est assez folle pour activer l'IPO par ex chez Intel), mais quand il s'agira de vectoriser, de paralleliser, les compilateurs s'arreteront et la perf partira en fumee.
    L'encapsulation, c'est bien, mais dans le domaine du calcul, on enleve tout cet enrobage afin de simplifier la vie au compilateur et au lecteur. Et pourtant on arrive encore a utiliser des templates, des methodes statiques... Mais on est en imperatif.

  6. #26
    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
    Citation Envoyé par Matthieu Brucher Voir le message
    Le compilateur va inliner si on est dans le meme fichier (ou si l'interface chaise clavier est assez folle pour activer l'IPO par ex chez Intel), mais quand il s'agira de vectoriser, de paralleliser, les compilateurs s'arreteront et la perf partira en fumee.
    L'encapsulation, c'est bien, mais dans le domaine du calcul, on enleve tout cet enrobage afin de simplifier la vie au compilateur et au lecteur. Et pourtant on arrive encore a utiliser des templates, des methodes statiques... Mais on est en imperatif.
    En étendant le domaine des PODs, C++11 permet d'écrire des classes qui ont les mêmes propriétés que le couple structures+fonctions libres. Le compilateur est censé les optimiser de la même manière (et vive std::is_pod<> pour les cas les plus tordus).

    Après, le problème est plus un problème de définition : aliasing strict, alignement correct, etc - tout ça est nécessaire au compilateur pour qu'il puisse vectoriser les calculs (là aussi, avec l'introduction des directives d'alignement dans le langage, le C++11 viens à notre rescousse).

    Citation Envoyé par Kamui
    Dans un monde de contraintes en tout cas, car dans l'embarqué c'est bien de cela qu'il s'agit même si les deux sont étroitement liés, j'imagine qu'on doit être obligé de faire des choix du style "tanpis pour la robustesse, la maintenabilité, etc, il faut surtout que je penses en dessous des 3ko de mémoire"... mais après ça devient de la déformation professionnelle de vouloir procéder comme cela partout.
    Là, c'est plus le runtime C++ qui pose problème. En termes de performances, on a des choses très similaires entre le C et le C++. En terme de taille de binaire, on gagne peu en C (dès lors qu'on désactive les exception et le rtti et qu'on utilise les bonnes options de compilation - notamment -Os avec g++). Par contre, même la lib µc++ fait près de 200 ko (et je ne parle pas de la libstdc++ de GNU). Sur certains système, ce n'est pas important, mais sur un système avec 4 ou 8 Mo de flash, c'est juste impossible à tenir. En fait, même sur un système avec plus de flash (par exemple 128 Mo - et c'est beaucoup), 200 ko peuvent avoir leur importance - c'est, par exemple, 200 ko de log en moins, ou 200 ko d'espace que le système de fichier ne peut pas utiliser pour de la redondance, ...

    Citation Envoyé par Bousk
    J'imagine aussi qu'aucun de vous n'utilise jamais de POD alors.
    Je dois dire que j'en utilise peu. Je réserve les POD (mauvais choix de mots ; comme dit précédemment, les PODs ont vu leur définition s'élargir avec C++11 ; je ne suis pas sûr qu'un POD C++11 ait toutes les caractéristiques auxquelles on pense lorsqu'on parle habituellement de POD. Je n'irais pas jusqu'à parler de pseudo-POD, parce que le terme a une image visqueuse) à une catégorie particulière d'objet, qui doit respecter les conditions suivantes :

    • l'objet doit être une valeur ; pas question bien évidemment de gérer les entités via des POD.
    • l'objet ne doit pas avoir d'invariant ; l'objet est donc toujours valide, quel que soit les valeurs des propriétés.
    • dans le cadre de mon application, l'objet ne définit pas de comportements (autres, bien évidemment, que la construction, l'affectation d'objet et l'accession aux membres). C'est plus rare qu'on ne le pense.


    Dès lors qu'une de ces conditions n'est plus respectée, l'objet se transforme en classe.

    De fait, Il n'est pas rare (dans mon code) de voir un objet commencer sa vie sous la forme d'une structure dont toutes les propriétés membres sont publiques et de le voir muter sous la forme d'un classe avec un contrôle d'accès fort - généralement à cause de refactoring successifs.
    [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.

  7. #27
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Citation Envoyé par Koala01
    Bien sur, il y aura toujours des imbéciles qui suivront ton raisonnement, j'en conviens, mais ils feront de toutes manières partie de la tranche de personnes qui n'ont simplement pas compris l'intérêt de la const correctness de manière générale.
    Erf, doucement les insultes . Et quel est selon toi l'intérêt du const-correctness ? (c'est une question ouverte, évidemment sujette à débat)

    Ce n'est pas une question de mentir, mais une question qu'on ne change pas un membre individuel d'un objet avec sémantique de valeur: On fait des copies différentes.
    Si c'est la règle, je la trouve stupide, ce pour des raisons bassement matérielles.

    Citation Envoyé par Koala01
    Que tu arrives simplement "en bordure de monde /d'univers" et que le fait de dépasser ces limites te fasse "tomber dans le néant" ou que tu envisage un monde sphérique où le passage par le pole, le méridien de référence ou l'équateur ait pour résultat de mettre une valeur à 0 (à moins qu'il ne l'inverse), tu auras forcément des états invalides, des positions réputées invalides / inaccessibles, sans aucun espoir qu'elles le deviennent un jour.

    Tu as donc "tout à gagner", à prévoir "l'imprévisible" et à t'imposer le principe d'encapsulation, même s'il peut sembler "futile" ou inutile
    Dites-moi, suis-je en train de rêver ou les partisans de la conception bien faite avant le développement militent en faveur d'une structure qui pare à tout et n'importe quoi dont les contraintes réelles ne sont pas définies ? J'ai lu ça avant de rentrer chez moi, et tout ce que j'ai pensé c'est "wtf ? " !

  8. #28
    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
    Citation Envoyé par germinolegrand Voir le message
    Erf, doucement les insultes .
    Je ne voulais offenser personne...

    Si c'est le cas, je t'en présente mes excuses les plus sincères
    Et quel est selon toi l'intérêt du const-correctness ? (c'est une question ouverte, évidemment sujette à débat)
    L'intérêt est d'être sur de se faire insulter par le compilateur si l'on essaye de modifier une donnée qui n'a pas lieu de l'être dans le contexte dans lequel elle est utilisée, indépendamment de la possibilité qui nous est donnée de le faire (ou non) en dehors de ce contexte particulier.
    Dites-moi, suis-je en train de rêver ou les partisans de la conception bien faite avant le développement militent en faveur d'une structure qui pare à tout et n'importe quoi dont les contraintes réelles ne sont pas définies ? J'ai lu ça avant de rentrer chez moi, et tout ce que j'ai pensé c'est "wtf ? " !
    Je crois plutôt que les partisans de la conception bien faite avant le développement (en tout cas moi ) gardent à l'esprit que l'on est sur que d'une seule chose c'est qu'on ne peut jamais être sur de rien (et même ca, on peut presque en douter ) et que, partant de là, les besoins exprimés demain risquent de ne pas correspondre à ceux que l'on a exprimés hier.

    Le fait de prévoir le fait qu'il soit seulement possible que les besoins de demain puissent impliquer des changements au niveau des structures de données les plus simples (et donc, quelque part, les plus utilisées) tend à nous offrir la possibilité de respecter au mieux le principe "ouvert / fermé" en limitant au maximum les endroits où le code devra être modifié afin de s'adapter aux nouveaux besoins

    Du moins, c'est ainsi que je le conçois... Libre à quiconque d'avoir une autre optique
    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

  9. #29
    Membre chevronné
    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 : 43
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Matthieu Brucher Voir le message
    Le compilateur va inliner si on est dans le meme fichier (ou si l'interface chaise clavier est assez folle pour activer l'IPO par ex chez Intel), mais quand il s'agira de vectoriser, de paralleliser, les compilateurs s'arreteront et la perf partira en fumee.
    L'encapsulation, c'est bien, mais dans le domaine du calcul, on enleve tout cet enrobage afin de simplifier la vie au compilateur et au lecteur. Et pourtant on arrive encore a utiliser des templates, des methodes statiques... Mais on est en imperatif.
    Sans parler que en general, y a pas de cas ou le developpement ets du one shot figé et ou les evolutions seront de la reimplantation.

    C'ets bien de prevoir l'avenir mais :
    - faut qu'il y ai un avenir
    - faut que cet avenir serve

    Pour rebondir sur le premier point, je pense que je suis de l'avis de germino. POD avant tout, non POD si les besoins evoluent.

  10. #30
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Les valeurs envisageables pour X et pour Y subiront, d'office, une limite maximale et / ou une limite minimale très peu en rapport avec les limites du type utilisé.

    Que tu arrives simplement "en bordure de monde /d'univers" et que le fait de dépasser ces limites te fasse "tomber dans le néant" ou que tu envisage un monde sphérique où le passage par le pole, le méridien de référence ou l'équateur ait pour résultat de mettre une valeur à 0 (à moins qu'il ne l'inverse), tu auras forcément des états invalides, des positions réputées invalides / inaccessibles, sans aucun espoir qu'elles le deviennent un jour.
    À mon sens ce n'est clairement pas à Position de se soucier de ça. Ça dépend complètement du contexte dans lequel elle est utilisée (et tu peux vouloir, dans un même programme, implémenter des limites différentes à des positions différentes : la position d'un personnage sur une planète, et la position d'un vaisseau en orbite par exemple).

    Le seul argument qui était valable en C++03 pour justifier l'abstraction des services x() et y() c'était la possible nécessité de passer à un tableau de deux valeurs plutôt qu'au couple x et y. Mais depuis le C++11 on peut gérer manuellement l'alignement des variables, et on peut donc faire un changement totalement transparent pour l'utilisateur même en utilisant une bête structure.

    Je pense que le service rendu par une classe aussi simple ne peut être que bien définit dès le départ, et n'aura jamais à changer. Qui plus est, c'est le genre de variable qu'on retrouve partout dans le code. Ce serait dommage d'alourdir systématiquement l'écriture juste "au cas où". Sinon, pourquoi ne pas pousser la logique jusqu'au bout et écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class MonEntier
    {
        int valeur;
     
        public :
            MonEntier();
            // tous les constructeurs imaginables ...
     
            int i()
            {
                return valeur;
            }
    };
     
    for (MonEntier i = 0; i.i() < 10; ++i)
        // Ah... je vais peut être modifier i() pour lancer une exception si 'valeur' atteint 10 !

  11. #31
    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
    Citation Envoyé par Joel F Voir le message
    C'ets bien de prevoir l'avenir mais :
    - faut qu'il y ai un avenir
    - faut que cet avenir serve
    Seulement, seul l'avenir pourra nous dire si ca servira ou non
    Pour rebondir sur le premier point, je pense que je suis de l'avis de germino. POD avant tout, non POD si les besoins evoluent.
    Je comprend ton point de vue, mais je ne le partage décidément pas.

    Nous parlons de structures simples, et donc de structures qui serviront sans doute de "brique de base", en tant que membre, à de nombreuses structures / classes.

    Partant de là, on peut se dire (ce sera d'ailleurs très vite confirmé à l'analyse du code ) que les raisons d'accéder aux différents champs seront au moins aussi nombreuses que le nombre de classes qui les utilisent.

    Dans de nombreux cas, les évolutions de besoins n'auront qu'un seul impact relatif à cette structure simple (si tant est qu'elles aient cet impact) : ajouter un endroit supplémentaire où le code a besoin d'accéder à ces données.

    Tant que l'évolution n'a que cet impact là, on pourrait estimer que tout va bien dans le meilleur des mondes

    Mais remettons nous dans le cadre de la discussion qui est à l'origine de ce débat, car il me semble que c'est l'exemple type qui démontre ma thèse.

    Pour l'instant, le PO crée pour se (re)mettre au C++ un petit RPG qui utilise la sortie console uniquement.

    Le choix est peut etre discutable, mais, il s'avère malgré tout être une excellente mise en bouche dans le sens où il permet de ne s'intéresser qu'à un ensemble de problèmes clairement définis

    Dans ce cadre particulier, la question n'est donc sans doute pas de savoir si évolution vers l'utilisation d'une bibliothèque il y aura, car on peut être quasiment sur qu'évolution il y aura, mais quand cette évolution fera partie des priorité du PO et... quelle bibliothèque le PO décidera d'utiliser.

    Et tout le problème vient de là :

    Si l'on peut s'attendre à ce qu'il y ait une évolution majeure, on n'a, actuellement, aucune possibilité de prévoir dans quelle direction elle nous poussera en terme d'adaptation de notre structure simple.

    Peut etre ne nous donnera-t-elle que d'avantage de raisons d'accéder aux différentes valeurs, mais peut etre mettra-t-elle en avant la nécessité de modifications plus importantes (la possibilité d'obtenir un pointeur sur un array de deux entiers, par exemple)

    Dans le premier cas, on ne pourrait sans doute que se féliciter d'avoir "gardé la structure aussi simple que possible", mais, dans le second cas, les modifications d'implémentation qu'il faudra mettre en oeuvre nous forceront quasiment à revoir l'ensemble du code.

    Bien sur, il reste toujours la possibilité de respecter scrupuleusement l' OCP en fournissant un moyen "externe" de convertir notre position en pointeur sur array de deux entiers, mais cela signifie que nous nous retrouveront avec une multitude d'appels à ce moyen externe qui ne pourront que nuire à l'ensemble du projet (en terme de performances, entre autres), car ce sera, typiquement, le genre de conversion que nous ferons un nombre incalculable de fois

    Personnellement, aucune de ces options ne me semble particulièrement alléchante. Et à toi (vous), qui prêche(z) l'utilisation d'un POD
    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

  12. #32
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Si l'on peut s'attendre à ce qu'il y ait une évolution majeure, on n'a, actuellement, aucune possibilité de prévoir dans quelle direction elle nous poussera en terme d'adaptation de notre structure simple.

    Peut etre ne nous donnera-t-elle que d'avantage de raisons d'accéder aux différentes valeurs, mais peut etre mettra-t-elle en avant la nécessité de modifications plus importantes (la possibilité d'obtenir un pointeur sur un array de deux entiers, par exemple)

    Dans le premier cas, on ne pourrait sans doute que se féliciter d'avoir "gardé la structure aussi simple que possible", mais, dans le second cas, les modifications d'implémentation qu'il faudra mettre en oeuvre nous forceront quasiment à revoir l'ensemble du code.

    Bien sur, il reste toujours la possibilité de respecter scrupuleusement l' OCP en fournissant un moyen "externe" de convertir notre position en pointeur sur array de deux entiers, mais cela signifie que nous nous retrouveront avec une multitude d'appels à ce moyen externe qui ne pourront que nuire à l'ensemble du projet (en terme de performances, entre autres), car ce sera, typiquement, le genre de conversion que nous ferons un nombre incalculable de fois

    Personnellement, aucune de ces options ne me semble particulièrement alléchante. Et à toi (vous), qui prêche(z) l'utilisation d'un POD
    Ma réponse est la suivante : on crée des types à utiliser dans le contexte. Trop de générique tue le générique (et pourtant je suis farouchement pour le DNRY !).

    (Attention, philosophie en approche)
    Et le code est en perpétuel mouvement, remodelage, il ne faut pas avoir peur du code qu'on a écrit, ni avoir peur de devoir le modifier quand besoin est. Si l'on en vient à redouter la réécriture d'un morceau de code, alors c'est que déjà notre inconscient est conscient () qu'il faut le réécrire.

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

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Je pense que le service rendu par une classe aussi simple ne peut être que bien définit dès le départ, et n'aura jamais à changer. Qui plus est, c'est le genre de variable qu'on retrouve partout dans le code. Ce serait dommage d'alourdir systématiquement l'écriture juste "au cas où".
    Tout dépend du "au cas où" plausible... Quand à alourdir l'écriture, entre pos.x et pos.x(), il ne faut pas déconner...

    L'encapsulation, c'est bien, mais dans le domaine du calcul, on enleve tout cet enrobage afin de simplifier la vie au compilateur et au lecteur. Et pourtant on arrive encore a utiliser des templates, des methodes statiques... Mais on est en imperatif.
    CGAL et sa classe Point_2, c'est peut-être pas du calcul où l'évaluation intelligente des coordonnées des points apporte plus qu'un vieux double en public?

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

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    (Attention, philosophie en approche)
    Et le code est en perpétuel mouvement, remodelage, il ne faut pas avoir peur du code qu'on a écrit, ni avoir peur de devoir le modifier quand besoin est. Si l'on en vient à redouter la réécriture d'un morceau de code, alors c'est que déjà notre inconscient est conscient () qu'il faut le réécrire.
    Ça, ça ne dépend pas forcément que de toi, mais aussi des utilisateurs de tes codes si tu en as.

    En d'autre terme, ça dépend du besoin d'avoir du code réutilisable dans divers contexte ou du luxe de le réserver à une application précise.

  15. #35
    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
    Citation Envoyé par germinolegrand Voir le message
    Ma réponse est la suivante : on crée des types à utiliser dans le contexte. Trop de générique tue le générique (et pourtant je suis farouchement pour le DNRY !).

    (Attention, philosophie en approche)
    Et le code est en perpétuel mouvement, remodelage, il ne faut pas avoir peur du code qu'on a écrit, ni avoir peur de devoir le modifier quand besoin est. Si l'on en vient à redouter la réécriture d'un morceau de code, alors c'est que déjà notre inconscient est conscient () qu'il faut le réécrire.
    I n'est pas question ici d'avoir peur de devoir réécrire du code, qu'il s'agisse du mien ou de celui d'un autre.

    Je l'ai déjà assez fait pour envisager le plus sereinement du monde d'avoir à le refaire

    Par contre, je l'ai aussi assez fait pour avoir pu me rendre compte que c'est systématiquement une plaie d'avoir à le faire, car il y a toujours "un point du code" que l'on aura oublié.

    Et c'est de là que vient ma philosophie de systématiquement tout encapsuler malgré l'apparente futilité de la chose:

    Quand, pour les besoins d'une évolution qui était jugée simple, tu te rends compte que tu passes plusieurs heures à te faire insulter par le compilateur pour code que tu n'aurais jamais du modifier si la donnée avait été correctement encapsulée, tu finis par te dire qu'il est "tellement simple" de l'encapsuler correctement dés le départ
    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

  16. #36
    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
    Citation Envoyé par bretus Voir le message
    Ça, ça ne dépend pas forcément que de toi, mais aussi des utilisateurs de tes codes si tu en as.

    En d'autre terme, ça dépend du besoin d'avoir du code réutilisable dans divers contexte ou du luxe de le réserver à une application précise.
    Et, même quand tu te payes le luxe de le réserver à une application précise, quand le projet devient tellement important qu'il faut commencer à le diviser en différents modules, bien que toi et ton équipe soyez le seul utilisateur du code, on apprécie vraiment quand une modification quelconque dans un des modules de base n'implique pas des changements en cascade dans les modules qui en dépendent
    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

  17. #37
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Citation Envoyé par Kalith Voir le message
    À mon sens ce n'est clairement pas à Position de se soucier de ça. Ça dépend complètement du contexte dans lequel elle est utilisée (et tu peux vouloir, dans un même programme, implémenter des limites différentes à des positions différentes : la position d'un personnage sur une planète, et la position d'un vaisseau en orbite par exemple).

    Le seul argument qui était valable en C++03 pour justifier l'abstraction des services x() et y() c'était la possible nécessité de passer à un tableau de deux valeurs plutôt qu'au couple x et y. Mais depuis le C++11 on peut gérer manuellement l'alignement des variables, et on peut donc faire un changement totalement transparent pour l'utilisateur même en utilisant une bête structure.

    Je pense que le service rendu par une classe aussi simple ne peut être que bien définit dès le départ, et n'aura jamais à changer. Qui plus est, c'est le genre de variable qu'on retrouve partout dans le code. Ce serait dommage d'alourdir systématiquement l'écriture juste "au cas où". Sinon, pourquoi ne pas pousser la logique jusqu'au bout et écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class MonEntier
    {
        int valeur;
     
        public :
            MonEntier();
            // tous les constructeurs imaginables ...
     
            int i()
            {
                return valeur;
            }
    };
     
    for (MonEntier i = 0; i.i() < 10; ++i)
        // Ah... je vais peut être modifier i() pour lancer une exception si 'valeur' atteint 10 !
    N'importe quoi. "Le seul changement qui me parait valable est celui que je connais, et il n'est plus valable, donc plus de raison de prévoir". Je trouve que se satisfaire à ce point de ce qu'on sait est vraiment irritant au plus haut point.

    Il suffit - encore une fois : comme l'a souligné Koala01 - de se placer dans le contexte de l'OP pour avoir un joli exemple que la théorie du chaos s'applique toujours (aka trop de variables pour que l'on puisse tout prévoir).

    Il réalise un RPG console, avec l'intention de passer à la SFML dans quelque temps (je le sais j'ai passé la soirée d'hier à l'aider à l'installer). avec la SFML, les coordonnées que vous manipulée sur un objet graphique, doivent être mappées avec les coordonnées du sprite de l'objet graphique. Et c'est très bien de conserver les deux version de coordonnée, une servant au calcul et aux anticipations de trajectoire, les autres renseignant de la position courante de l'objet dans la fenêtre !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    class Tidus //Héros FF10 que l'OP va devoir créer
    {
       Position pos;
       sf::Sprite spTidus; 
     
       public :
           Tidus();
           const int x() { return Position((const int)spTidus().pos().x, (const int)spTidus.pos().y) }
     
           void setX(const int x) { pos = Position(x, (const int)spTidus.pos().y) }
     
           bool modifierTrajectoire() { int monXdeTravail = x(); /*calcul...si tout est ok, return true et setX(), sinon false*/ }
     
           void draw(sf::RenderTarget& target) { if (modifierTrajectoire) target.draw(spTidus); }
    }
     
    //Bon c'es un exemple très schématique mais l'idée est là !

    Vous voyez tous les calculs que je fais, imaginez maintenant que je doive faire ça directement dans mon code partout où je vais appliquer ces changements...

    Donc il faut arrêter de croire savoir, et appliquer, amha, la règle suivante : "Je sais que je ne sais rien. Je fais tout ce que je peux pour prévoir/me préparer à l'imprévisible. Si vraiment je ne peux pas faire autrement pour des raisons de contraintes incontournables (embedeed system), je fais des sacrifices, mais SEULEMENT dans ce cas là."
    Nullius in verba

  18. #38
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    C'est marrant que tu mettes en avant la SFML de cette manière, et la façon dont tu l'utilises me parais... anormale s'il en est.

    Tu prends la classe Sprite de la SFML, elle a une simple méthode setPosition(float x, float y).
    Tu as également une autre option avec setPosition(const Vector2f& v).
    Vector2f qui est... un POD x, y.

    D'ailleurs, depuis que j'utilise la SFML, le besoin d'une structure Position a quasiment disparu de mon code : j'utilise directement celle de la SFML.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Perso
    {
     public:
     const Vector2f& getPosition() const { return m_sprite.getPosition(); }
     void setPosition(float x, float y) { m_sprite.setPosition(x, y); }
    };
    Une autre approche sur un autre projet, où j'avais déjà ma Position et ai switché de la SDL vers SFML pour le rendu, et ça donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    struct Position { int x, y; };
    class Perso
    {
     Position m_pos;
     sf::Sprite m_sprite;
     public:
     const Position& getPosition() const { return m_pos; }
     const setPosition(int x, int y) { m_pos.x = x; m_pos.y = y; }
     bool Update(u32 dt) { m_sprite.setPosition(m_pos.x, m_pos.y); return true; }
    };
    La méthode update existe chez moi, mais puisque tu as une méthode Draw non const, tu peux inclure son code dans le Draw.

    Le même résultat en... 3 lignes ? Alors explique-nous comment toi tu as besoin de 10 lignes pour cela ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  19. #39
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Il réalise un RPG console, avec l'intention de passer à la SFML dans quelque temps (je le sais j'ai passé la soirée d'hier à l'aider à l'installer). avec la SFML, les coordonnées que vous manipulée sur un objet graphique, doivent être mappées avec les coordonnées du sprite de l'objet graphique. Et c'est très bien de conserver les deux version de coordonnée, une servant au calcul et aux anticipations de trajectoire, les autres renseignant de la position courante de l'objet dans la fenêtre !

    Vous voyez tous les calculs que je fais, imaginez maintenant que je doive faire ça directement dans mon code partout où je vais appliquer ces changements...
    Justement il n'y a pas de modification du code pour l'utilisation de Position, on à seulement la fonction draw() qui va calculer les coordonnées écrans à partir de la Position de l'objet ?

    (Utilisation d'une matrice de vue - projection ? Si c'est le cas, il est limite préférable de remplacer la classe Position par un typedef sur une classe vec2 toute faite pour pas s’embêter avec les multiplications vecteur / matrice).

  20. #40
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Citation Envoyé par Bousk Voir le message
    C'est marrant que tu mettes en avant la SFML de cette manière, et la façon dont tu l'utilises me parais... anormale s'il en est.

    Tu prends la classe Sprite de la SFML, elle a une simple méthode setPosition(float x, float y).
    Tu as également une autre option avec setPosition(const Vector2f& v).
    Vector2f qui est... un POD x, y.

    D'ailleurs, depuis que j'utilise la SFML, le besoin d'une structure Position a quasiment disparu de mon code : j'utilise directement celle de la SFML.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Perso
    {
     public:
     const Vector2f& getPosition() const { return m_sprite.getPosition(); }
     void setPosition(float x, float y) { m_sprite.setPosition(x, y); }
    };
    Une autre approche sur un autre projet, où j'avais déjà ma Position et ai switché de la SDL vers SFML pour le rendu, et ça donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    struct Position { int x, y; };
    class Perso
    {
     Position m_pos;
     sf::Sprite m_sprite;
     public:
     const Position& getPosition() const { return m_pos; }
     const setPosition(int x, int y) { m_pos.x = x; m_pos.y = y; }
     bool Update(u32 dt) { m_sprite.setPosition(m_pos.x, m_pos.y); return true; }
    };
    La méthode update existe chez moi, mais puisque tu as une méthode Draw non const, tu peux inclure son code dans le Draw.

    Le même résultat en... 3 lignes ? Alors explique-nous comment toi tu as besoin de 10 lignes pour cela ?
    C'était un exemple. Entre parenthèses, tu fourni un exemple de doc de la 1.6 alors que cette version est obsolète.
    Et dans mon exemple, je partais du postulat qu'on ai besoin de travailler sur la position de l'objet sans que cela impacte immédiatement ou obligatoirement l'objet graphique. Par exemple, dans FF10, des qu'un combat se déclenche, le sprite sera placé différemment, mais la position de l'objet restera le même sur la carte.
    Nullius in verba

Discussions similaires

  1. service IIS not installed in u computer
    Par elgafsi86 dans le forum IIS
    Réponses: 0
    Dernier message: 09/03/2010, 15h08
  2. Le plus simple pour créer un service web ?
    Par goeland444 dans le forum Services Web
    Réponses: 0
    Dernier message: 22/07/2008, 15h43
  3. Structure d'une table pour service production
    Par lg022 dans le forum Schéma
    Réponses: 2
    Dernier message: 24/04/2008, 10h27
  4. Réponses: 8
    Dernier message: 22/11/2006, 08h54
  5. Problème "The specified service does not exist as an ..
    Par Rimak2 dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 23/05/2005, 21h24

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