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. #1
    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 structures simples : services or not services
    [EDIT] Cette discussion est un fork de Relecture de code d'un jeu RPG afin d'éviter le mélange de débats tous deux intéressants. N'hésitez pas à continuer à répondre aux deux discussions séparément

    Mais pourquoi diantre cacher (et non encapsuler parce que c'est une notion qui n'a rien à voir ici) les attributs d'une classe Position ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Postition {
    public:
        Postition( const int x, const int y );
        const int PosX() const { return m_x; }
        const int PosY() const { return m_y; }
    private:
        const int m_x;
        const int m_y;
    };
    Cette classe est absurde... je crois que ça s'appelle la maladie des getters...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct Position
    {
        int x, y;
    };
    Ce code est à la fois plus simple, plus concis, plus maniable, et offre plus de possibilités.

    Un simple const Position suffit à avoir la même chose que ce que tu fais, sans nécessiter de modification de Position :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    const Position b {3, 3};
    Position a {1, 1};
    a = b;
    b = a;//! interdit par choix du programmeur, s'il fait ceci c'est une erreur d'inatention le compilo va le lui signaler.

  2. #2
    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 germinolegrand Voir le message
    Mais pourquoi diantre cacher (et non encapsuler parce que c'est une notion qui n'a rien à voir ici) les attributs d'une classe Position ???
    Il y à 2 (ok, 3) solutions :
    - soit mettre les attributs public et const (-> respect de la sémantique de valeur)
    - soit mettre les attributs privés et mettre des getters (pas besoin de const ici car pas de setters, -> respect de la sémantique de valeur, et homogénéisation du code avec l'utilisation de fonctions)
    - attributs public et non const (-> pas de respect de la sémantique de valeur car valeurs modifiables, mais code plus court)

    Pour le 3eme cas, il est toujours possible d'utiliser des const Position comme tu dis, mais on offre la possibilité de faire autrement.

  3. #3
    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,
    Citation Envoyé par germinolegrand Voir le message
    Mais pourquoi diantre cacher (et non encapsuler parce que c'est une notion qui n'a rien à voir ici) les attributs d'une classe Position ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Postition {
    public:
        Postition( const int x, const int y );
        const int PosX() const { return m_x; }
        const int PosY() const { return m_y; }
    private:
        const int m_x;
        const int m_y;
    };
    Cette classe est absurde... je crois que ça s'appelle la maladie des getters...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct Position
    {
        int x, y;
    };
    Ce code est à la fois plus simple, plus concis, plus maniable, et offre plus de possibilités.

    Un simple const Position suffit à avoir la même chose que ce que tu fais, sans nécessiter de modification de Position :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    const Position b {3, 3};
    Position a {1, 1};
    a = b;
    b = a;//! interdit par choix du programmeur, s'il fait ceci c'est une erreur d'inatention le compilo va le lui signaler.
    Pour le coup, je ne peux vraiment pas être d'accord avec toi (et pour cause: c'est moi qui ait conseillé de le faire de la sorte )

    Le fait est qu'une position a, typiquement, sémantique de valeur car:
    • il peut exister plusieurs instances de position présentant exactement les même valeurs.
    • une position est d'office constante: si tu fait varier la valeur de l'abscisse ou de l'ordonnée en quoi que ce soit, tu obtiens... une autre position.
    En outre, les fonctions (que j'avais simplement nommées x et y à la base) correspondent bel et bien à des services que l'on est en droit d'attendre de la part de cette classe.

    Se contenter d'une structure avec des membres non constants mettrait à mal le principe même de la notion de sémantique de valeur, en permettant les modifications si l'on oublie de déclarer la valeur (ou l'argument) comme constant.

    Nous aurions, en effet, pu créer une structure exposant publiquement les valeurs x et y sous la forme de constantes, mais cela aurait nuit à la cohérence du code car il s'agit d'une classe qui est destinée à permettre, peu ou prou, à n'importe quoi de se situer sur la carte.

    Or, il y a deux solutions pour que "tout ce qui peut se situer sur la carte" soit en mesure de rendre ce service à l'utilisateur.

    La première est de jeter la loi de déméter aux orties et de renvoyer une position, avec, comme résultat, un code qui ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int abscisse = monObjet.position().x;
    la deuxième (et ma préférée) étant de respecter déméter et de se dire que l'utilisateur de l'objet ne devrait pas avoir connaitre la classe position pour pouvoir utiliser son objet, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int abscisse = monObjet.x();
    Le problème, si l'on présente position comme une structure exposant ses champs constants, c'est que nous pourrions parfaitement nous retrouver avec du code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void MaClassDerivee::foo(Position const & param)
    {
        int abscisseParam = param.x;
        int actualAbcsisse = x(); // la position est un membre privé de la classe de
                                  // base, uniquement accessible au travers de l'interface ;)
        /* ... */
    }
    et que l'on peut donc très facilement en arriver à ne plus savoir s'il faut ou non mettre les parenthèse pour obtenir la valeur souhaitée.

    Alors, bien sur, tu me diras que ce n'est pas bien grave, que le compilateur nous indiquera bien si l'on a appelé la fonction au lieu du champs (ou l'inverse), mais il n'empêche qu'il est quand même beaucoup plus facile, à mon sens, de partir du principe que tout service rendu par une classe est représenté par une fonction
    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

  4. #4
    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 germinolegrand Voir le message
    Mais pourquoi diantre cacher (et non encapsuler parce que c'est une notion qui n'a rien à voir ici) les attributs d'une classe Position ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Postition {
    public:
        Postition( const int x, const int y );
        const int PosX() const { return m_x; }
        const int PosY() const { return m_y; }
    private:
        const int m_x;
        const int m_y;
    };
    Cette classe est absurde... je crois que ça s'appelle la maladie des getters...
    Le principe de l'encapsulation c'est exactement ce que fait cette classe : protéger l'information contenue par un objet en contrôlant tous les moyens d'accès à cette dernière : c'est tout sauf absurde, c'est un des fondements d'un code bien sécurisé, et donc robuste. Ainsi, je peux te passer mon Position.dll ou .lib ou .a avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Postition {
    public:
        Postition( const int x, const int y );
        const int X() const { return m_x; }
        const int Y() const { return m_y; }
    };
    Et ainsi je suis sur que tu ne feras rien que je n'ai pas prévu avec cette classe.

    Moi je trouve au contraire que beaucoup de personnes on la maladie des struct, surtout les personnes qui ont un niveau appréciable : je trouve cela étrange et j'aimerais apprendre pourquoi cette utilisation intense des structures est présente chez autant de personnes ?
    Nullius in verba

  5. #5
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = 3;
    i += 4;
    i = 5;
    Il a quoi comme sémantique ce i ? C'est pas une entité quand même... si ? Si vous me dites que les int ont pas une sémantique de valeur... je mange mon chapeau na ! (Gare à celui qui me souhaitera un bon appétit... ) Sinon ça veut dire que le CPU ne connait que des entités (les opérations ci-dessus il n'arrête pas de les faire) et ne sait pas de base faire des valeurs, ce qui est vraisemblablement paradoxal avec tous les artifices qu'il faut déployer pour arriver à manipuler des entités (oui c'est à ça que sert la move-sémantique quand même).

    Personnellement je pense que la seule caractéristique d'un objet à sémantique de valeur est d'être copiable.

    Si je m'amusais à copier la totalité d'une matrice à chaque fois que je veux faire une opération dessus, n'importe qui crierait au scandale, et ce avec raison (il me souhaiterait même de ne jamais faire de calculs scientifiques *).

    Les règles abstraites, c'est bien, mais il ne faut pas que ça devienne absurde.

    Citation Envoyé par Koala01
    partir du principe que tout service rendu par une classe est représenté par une fonction
    Sauf que ce n'est pas un service, ce getter ne fait que rajouter de la verbosité inutile au code d'une structure de donnée simple.

    Citation Envoyé par Kaamui
    Le principe de l'encapsulation c'est exactement ce que fait cette classe : protéger l'information contenue par un objet en contrôlant tous les moyens d'accès à cette dernière
    L'encapsulation concerne des services, non des données. Le but de l'encapsulation n'est pas de cacher des données, mais de donner une interface claire pour les services présentés (c'est en ce sens qu'on encapsule les attributs privés permettant de rendre ce service, la valeur de ces attributs ne constituant nullement un service).

    Citation Envoyé par Kaamui
    Et ainsi je suis sur que tu ne feras rien que je n'ai pas prévu avec cette classe.
    Le créateur d'une classe se bat contre Murphy, non contre Machiavel. Autrement dit, cherchez toujours à ce que votre classe se comporte comme attendue intuitivement lors de son utilisation normale, mais ne cherchez pas à prévenir les détournements qu'on peut en faire, c'est à la fois peine et temps perdu.

    Citation Envoyé par Kaamui
    Moi je trouve au contraire que beaucoup de personnes on la maladie des struct, surtout les personnes qui ont un niveau appréciable : je trouve cela étrange et j'aimerais apprendre pourquoi cette utilisation intense des structures est présente chez autant de personnes ?
    Je pense que j'ai donné la moitié de la réponse un peu plus haut, les classes pour les services, les structures pour les données. Le move pour les classes de service, la copie pour les structures de données. A noter que classe et structure n'ont pas de rapport direct avec les mot-clés class et struct qui sont de toute façon interchangeables, bien que pour une question de logique pure de clarté sémantique du code on évite d'inverser .

    * histoire vraie, l'auteur se reconnaîtra .

  6. #6
    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
    Je suis complètement d'accord avec germinolegrand, je trouve stupide de camoufler autant l'information.
    Position, Point etc ont tout à fait leur place en tant que "simple" POD.

    Une structure Position, on attend à ce qu'elle ait un x et un y (voire un z), mais il n'y a aucune raison pour moi de totalement camoufler ça derrière des getter absurdes qui n'apportent strictement rien.
    Si la position ne doit pas être modifiée, elle doit être passée en const référence et c'est tout.
    Forcer la constance de la position en cachant son contenu et en ne fournissant que des getter constant c'est un cache-misère qui laisse l'utilisateur la possibilité de mentir à son application : on se moque de passer sa position en const& puisque de toutes façons les seuls membres sont des getter const.
    La bonne solution qui doit être adoptée c'est le passage en paramètre constant.
    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.

  7. #7
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = 3;
    i += 4;
    i = 5;
    Il a quoi comme sémantique ce i ? C'est pas une entité quand même... si ? Si vous me dites que les int ont pas une sémantique de valeur... je mange mon chapeau na ! (Gare à celui qui me souhaitera un bon appétit... )
    On ne dira jamais une chose pareille, rassures toi... Mais:
    3 est différent de 4, de 7 et de 5.

    Tu obtiens bel et bien... une valeur différente, non

    S'il se fait que la nouvelle valeur échoit à i, ce n'est que pour une raison bien simple: l'une des caractéristiques des sémantiques de valeurs est... d'être assignable
    Personnellement je pense que la seule caractéristique d'un objet à sémantique de valeur est d'être copiable.
    Copiable ET assignable (en plus d'être constante et comparable, au moins par égalité)
    Si je m'amusais à copier la totalité d'une matrice à chaque fois que je veux faire une opération dessus, n'importe qui crierait au scandale, et ce avec raison (il me souhaiterait même de ne jamais faire de calculs scientifiques *).
    Oh, mais une matrice, c'est une collection, et la sémantique des collections est effectivement à mi chemin entre les deux, en plus de dépendre de la sémantique des objets qu'elles doivent contenir.

    Déjà, le seul moyen de contenir un objet non copiable (AKA ayant sémantique d'entité) est... de passer par un pointeur sur cet objet, et cela rend la collection non copiable, à moins de prendre des précautions particulières
    Sauf que ce n'est pas un service, ce getter ne fait que rajouter de la verbosité inutile au code d'une structure de donnée simple.
    Pas si sur...
    L'encapsulation concerne des services, non des données. Le but de l'encapsulation n'est pas de cacher des données, mais de donner une interface claire pour les services présentés (c'est en ce sens qu'on encapsule les attributs privés permettant de rendre ce service, la valeur de ces attributs ne constituant nullement un service).
    Même sur des choses aussi simple, l'encapsulation présente de sérieux avantages, dont celui de rendre le code de l'utilisateur indépendant de l'implémentation.

    Car, imaginons trente secondes que, bien après avoir créé ta classe (structure) point, tu aies besoin, pour complaire à une bibliothèque externe, de disposer d'un pointeur sur un array de deux entiers.

    Si, pour une raison ou une autre, tu n'as pas la certitude que les règles d'alignement sont respectée, tu devras transformer tes deux entiers nommés respectivement x et y en un tableau de deux entiers (faisons simple: en int coordinate[2] ).

    Si tu effectues ce changement (qui n'est qu'un changement d'implémentation, nous sommes bien d'accord ) mais que le code utilisateur avait la possibilité d'accéder directement à x et / ou à y, ce simple changement est de nature à casser tout le code utilisateur précédant ce changement.

    Alors que, si tu as, dés le départ, encapsulé tes données et que tu n'y a donné accès qu'au travers d'accesseurs (qui, en plus, représentent un service que tu es en droit d'attendre), tu pourras sans problème remplacer tes deux int par un array de deux entiers et rajouter une fonction data() (par exemple) renvoyant un pointeur sur cet array sans que cela ne nuise en quoi que ce soit au code existant (outre le besoin de recompiler le code afin de respecter la nouvelle ABI )
    Le créateur d'une classe se bat contre Murphy, non contre Machiavel. Autrement dit, cherchez toujours à ce que votre classe se comporte comme attendue intuitivement lors de son utilisation normale, mais ne cherchez pas à prévenir les détournements qu'on peut en faire, c'est à la fois peine et temps perdu.
    Mais l'encapsulation, aussi futile puisse-t-elle paraître, ne fait jamais que renvoyer murphy et son corolaire fingale dans leur pénates
    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

  8. #8
    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 koala01 Voir le message
    Si, pour une raison ou une autre, tu n'as pas la certitude que les règles d'alignement sont respectée, tu devras transformer tes deux entiers nommés respectivement x et y en un tableau de deux entiers (faisons simple: en int coordinate[2] ).

    Si tu effectues ce changement (qui n'est qu'un changement d'implémentation, nous sommes bien d'accord ) mais que le code utilisateur avait la possibilité d'accéder directement à x et / ou à y, ce simple changement est de nature à casser tout le code utilisateur précédant ce changement.

    Alors que, si tu as, dés le départ, encapsulé tes données et que tu n'y a donné accès qu'au travers d'accesseurs (qui, en plus, représentent un service que tu es en droit d'attendre), tu pourras sans problème remplacer tes deux int par un array de deux entiers et rajouter une fonction data() (par exemple) renvoyant un pointeur sur cet array sans que cela ne nuise en quoi que ce soit au code existant (outre le besoin de recompiler le code afin de respecter la nouvelle ABI )

    Mais l'encapsulation, aussi futile puisse-t-elle paraître, ne fait jamais que renvoyer murphy et son corolaire fingale dans leur pénates
    C'est le type d'exemple que j'étais en train de chercher^^. Entièrement d'accord.

    L'encapsulation concerne des services, non des données.
    Alors je reprends ma phrase :

    Le principe de l'encapsulation c'est exactement ce que fait cette classe : protéger l'information contenue par un objet en contrôlant tous les moyens d'accès à cette dernière par le biais des services proposés à l'utilisateur.
    Nullius in verba

  9. #9
    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
    Ces "services" font-ils le moindre contrôle ? Ils ne protègent strictement rien.

  10. #10
    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
    Ces "services" font-ils le moindre contrôle ? Ils ne protègent strictement rien.
    Il n'ont pas forcément le moindre contrôle à faire... ou non

    Tout ce qu'on leur demande, c'est:
    • d'assurer la stabilité du code antérieur à un changement d'implémentation éventuel
    • de s'assurer que, si modification de l'état il y a, selon une procédure clairement établie
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    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
    Tous les états possibles pour la structure de donnée sans fioriture sont des états valides, et toutes les transitions sont sans effet de bord aucun. De là, les fioritures en question sont inutiles.

  12. #12
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Du coup, classe ou structure ?!

    De toute manière, les seuls objet pouvant être des structures seront des objets à sémantique de valeur ne contenant pas d'autres objets ?!

    Ou par soucis de lisibilité les objets seront tous des classes ?!

    Les classes ne font qu'un peut plus de lignes pour le concepteur ou bien elle change la façon dont sera compilé le programme ?

  13. #13
    Expert éminent sénior

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    pour le compilateur c'est quasi transparent.

    en fait, tu peux remplacer chaque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct blablabla {
    blablabla2
    };
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class blablabla {
    public:
    blablabla2
    };
    cela aurait le même effet (sauf pour le problème de la visibilité par défaut de l'héritage)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  14. #14
    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 PilloBuenaGente Voir le message
    Du coup, classe ou structure ?!

    De toute manière, les seuls objet pouvant être des structures seront des objets à sémantique de valeur ne contenant pas d'autres objets ?!

    Ou par soucis de lisibilité les objets seront tous des classes ?!

    Les classes ne font qu'un peut plus de lignes pour le concepteur ou bien elle change la façon dont sera compilé le programme ?
    Faire une classe Position, comme l'a souligné Koala01, en plus des arguments déjà mis en avant en faveur de l'encapsulation de cette classe, permettra d'améliorer la maintenabilité de n'importe quel programme qui l'utilise. Un exemple d'application :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    Struct SPosition
    {
       int x,y;
    }
     
    class CPosition
    {
       int x;
       int y;
     
       public :
          CPosition(const int x, const int y);
          const int x() const { return x; }
          const int y() const { return y; }
    }
     
     
    //des appels un peu partout dans un programme qui utilise SPosition
    SPosition spos;
    spos.x = 3;
    spos.y = 2;
     
    ///...plein de manipulations un peu partout du genre 
    int result = sqrt(spos.x*s.pos.x + spos.y*spos.y);
     
    //..plus loin (bon je met n'importe quoi hein c'est pour l'exemple
    float result2 = (float)spos.x;
    result2 = ...
     
    //et maintenant la même chose avec la classe Cposition
    CPosition cpos(3,2);
    int result = sqrt(cpos.x()*cpos.x() + cpos.y() + cpos.y());
     
    //...
    int result2 = (float)cpos.x();

    Jusqu'ici on se demande pourquoi on a codé une classe...la couche qui sépare l'utilisation des membres privés n'a pas l'air de vraiment servir...

    Maintenant, imaginons, que pour une raison ou pour une autre, je décide que ma position ne doit plus se comporter comme cela. Pour une raison ou pour une autre, j'ai besoin de vérifier quelque chose avant de transmettre x ou y :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    Struct SPosition
    {
       int x,y; 
       bool maConditionAVerifier = true;
    }
     
    class CPosition
    {
       int x;
       int y;
       bool maConditionAVerfier;
     
       public :
          CPosition(const int x, const int y, const bool maConditionAVerfier = true; );
          const int x() const { if (maConditionAVerfier) return x; else return -1; //pour l'exemple }
          const int y() const { if (maConditionAVerifier) return y; else return -1;}
    }
     
    //des appels un peu partout dans un programme qui utilise SPosition
    SPosition spos;
    spos.x = 3;
    spos.y = 2;
    spos.maConditionAVerfier = (result0 == 42);
     
     
    //...plein de manipulations un peu partout du genre 
    //je dois maintenant vérifier ma condition
    int result = 0;
    if (spos.maConditionAVerfier)
       result = sqrt(spos.x*s.pos.x + spos.y*spos.y);
    else
       result = sqrt(2);
     
    //..plus loin (bon je met n'importe quoi hein c'est pour l'exemple
    float result2 = spos.maConditionAVerfier ? (float)spos.x : -1.f;
    result2 = ...
     
    //Et ainsi de suit sur tout mon code (imaginons sur des centaines d'utilisation de la structure, autant de changement à prévoir)
     
    //et maintenant la même chose avec la classe Cposition
    CPosition cpos(3,2, result0 == 42); //voilà le seul changement à effectuer dans mon code, après avoir modifié ma classe plus haut..
    int result = sqrt(cpos.x()*cpos.x() + cpos.y() + cpos.y());
     
    //...
    int result2 = (float)cpos.x();
    Donc moi je dis classe sans hésiter, même pour un code aussi basique. Il faut pas hésiter à faire du code réutilisable. Imagine que tu ai fait ceci en header-only, tu ouvre un nouveau projet, tu copie ton fichier dans ton projet, et tu as la même maintenabilité d'assurée... et tu gagnes du temps...

    Après chacun ses gouts mais pour répondre à ta question : qu'est-ce que ça change ? En voilà un exemple.
    Nullius in verba

  15. #15
    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
    Faut voir si c'est bien inline par le compilateur. De mon point de vue, l'implementation ne devra jamais etre dans un cpp pour les accesseurs comme celui-la.

  16. #16
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Faire une classe Position, comme l'a souligné Koala01, en plus des arguments déjà mis en avant en faveur de l'encapsulation de cette classe, permettra d'améliorer la maintenabilité de n'importe quel programme qui l'utilise.
    Ça je suis ok.
    Maintenant, imaginons, que pour une raison ou pour une autre, je décide que ma position ne doit plus se comporter comme cela. Pour une raison ou pour une autre, j'ai besoin de vérifier quelque chose avant de transmettre x ou y
    Je ne suis pas allé très loin dans la conception, mais, les vérifications n'auraient-elles pas tendance à ce faire, soit en amont (Lors de l’instanciation, on est déjà censé lui apporter des valeurs juste !), ou en aval ?! Sinon il faudrait recourir à une variable static ou bien donner des précisions à la création ?!

  17. #17
    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
    Maintenant, imaginons, que pour une raison ou pour une autre, je décide que ma position ne doit plus se comporter comme cela.
    Entièrement d'accord avec ça, mais l'utilisation de structures (avec membres publics non constants) est, imo, très lié à l’optimisation (bien que souvent "ce ne soit pas utile", comprendre fait avant de voir ou est le goulot d'étranglement des performances).
    Entre avoir un appel de fonction qui sera peut-être inline (au bon vouloir du compilo), et un membre public (non constant pour éviter les copies d'objets à chaque modification), le choix est vite fait si on vise les performances.

    Et c'est le principal avantage des structures: ça reste un héritage du C.

    C'est moins maintenable, c'est sur, mais... derrière le C++, il y a toujours un notion de performance sinon on coderait en Java un autre langage

  18. #18
    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
    Tous les états possibles pour la structure de donnée sans fioriture sont des états valides, et toutes les transitions sont sans effet de bord aucun. De là, les fioritures en question sont inutiles.
    Pas forcément...

    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.

    De plus, l'inlining aidant (à l'origine, les fonctions étaient prévues pour être inline ), tu n'as normalement aucun overhead lié à l'utilisation de ces fonctions.

    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
    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

  19. #19
    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
    Citation Envoyé par koala01 Voir le message
    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
    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à.

    J'imagine aussi qu'aucun de vous n'utilise jamais de POD alors.
    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.

  20. #20
    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
    C'est vrai que dans le monde de la perf, on utilise du POD a 90% !

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