Partage
  • Partager sur Facebook
  • Partager sur Twitter

Petite réflexion classe - instance entité - valeur

    14 juin 2019 à 17:17:35

    Bonjour,

    peut être que ça va paraître évident à certains, mais j'ai réalisé que les notions de classe/instance et de entité/valeur sont identiques à un niveau différent d'abstraction.

    Une classe est une définition, il n'en existe qu'une seule. Par contre l'application de cette définition donne des instances qui peuvent être nombreuses. Donc une classe est un peu comme une valeur, et ces instances sont un peu comme des entités. 

    Pour pousser un peu le truc, les différentes "valeurs" de classes sont les différentes classes possibles. Mais en principe on a pas le droit de définir deux fois la même classe. Et chaque entité / instance possède une adresse en ram qui lui est unique même si son état est identique à une autre.

    Bref, je sais pas s'il y a vraiment matière à discuter la dessus, mais je trouvais ça intéressant de partager cette réflexion des fois que je ne sois pas le seul à avoir mis le temps de comprendre. :) 

    • Partager sur Facebook
    • Partager sur Twitter
      14 juin 2019 à 17:29:24

      Mouais, bof.

      Tu peux avoir plusieurs instances d'une classe a semantique de valeur et plusieurs instances d'une classe a semantique d'entite. Et toutes ces instances ont des addresses en memoire qui seront differentes, meme pour les valeurs.

      int i{123};
      int j{123}; // valeur, qui a une adresse differente de i
      
      Entity e1;
      Entity e2; // entity qui a une valeur differente de e1

      La difference est avant tout conceptuelle. foo(i) et foo(j) doivent donner le meme resultat alors que foo(e1) et foo(e2) peuvent donner des resultats differents.

      • Partager sur Facebook
      • Partager sur Twitter
        14 juin 2019 à 22:09:06

        Salut,

        La notion de classe représente la notion de "type de donnée".  Pour être précis, elle entre dans la catégorie de ce que l'on appelle couramment les "types définis par l'utilisateur" ;)

        La notion d'instance représente, quant à elle une donnée bien spécifique qui est du type indiqué.  Pour faire simple, une instance représente une variable du type indiqué.

        Quant aux notions de "valeurs" vs "entité", elles représentent d'avantage un aspect sémantique du problème, à  savoir : les risques que l'on court (ou non) si, à  un instant T de l'exécution du programme, on venait à se retrouver avec deux instances (du même type, forcément) qui présenteraient exactement les mêmes valeurs.

        Pourquoi y aurait-il le moindre risque, pourrais tu me demander.  Hé bien, simplement parce qu'il arrive parfois que l'on souhaite déterminer sur quelle instance de la classe on souhaite travailler sur base ... d'une des données qui la composent.

        Pour certains types de données (les classes ayant "sémantique de valeur"), cela ne posera aucun problème car c'est l'ensemble des données qui la composent qui définissent une valeur bien particulière.

        Par exemple, la notion de couleur est souvent définie en informatique comme un mélange de rouge, de vert et de bleu dans certaines proportions prenant une forme proche de

        /* class et struct, c'est du pareil au même en C++  */
        struct Color{
           int red;
           int green;
           int blue;
        };

        Mais il existe d'autres possibilités de représenter la notion de couleur, telle que à la manière des imprimeries, avec les couleur Cyan, Magenta, Jaune (et Noire) ou en dégradé de gris...

        Chaque valeur de colorimétrie peut être représentée sous les différentes formes, mais, il faudra passer par une étape de conversion si tu veux passer d'une forme à l'autre ;)

        Il n'y a rien qui t'empêche, si tu as encore de la peinture après avoir repeint ta chambre, de décider de repeindre le hall d'entrée dans la même couleur; ce qui se traduirait, en informatique, par deux variables (que nous nommerions hall et bedroom) de type Color présentant exactement les mêmes valeurs pour red, green et blue, mais pouvant exister "au même moment" en mémoire ;)

        Et il n'y a absolument rien qui t'interdit, si tu aimes vraiment très fort cette couleur et que tu n'en as plus, d'aller en racheter la même couleur pour repeindre une autre pièce encore :D

        C'est la raison pour laquelle on dit généralement que les classes ayant sémantique de valeur sont

        • copiable (on peut copier les valeurs qui composent une instance particulière pour en créer une nouvelle-
        • assignable (on peut, à  n'importe quel moment, assigner les valeurs qui composent une instance particulière à une autre instance de la classe)
        • comparable (à tout le moins par égalité) dans son ensemble (c'est la comparaison de chacune des valeurs qui composent la donnée qui permet de s'assurer que la valeur de la donnée est identique)
        • généralement constante (si tu modifies un tant soit peu les proportion de rouge, de vert ou de bleu, tu obtiens ... une couleur différente, même si la différence n'est pas forcément visible à  l'oeil nu :D )
        • convertible dans un type de donnée représentant la même notion
        • peu susceptible d'intervenir dans une hiérarchie de classes

        Par contre, il y a "toute une catégorie" de classes (les classes ayant "sémantique d'entité) pour lesquelles cela poserait de très sérieux problèmes, parce que, lorsque l'on décide d'apporter une modification sur une instance bien particulière, on veut pouvoir garantir que la modification sera bel et bien appliquée sur l'instance de la classe en question, et non sur "une vague copie" de celle-ci.

        Un exemple classique de classe présentant une sémantique d'entité serait la notion de compte bancaire qui, dans sa plus simple expression pourrait ressembler à quelque chose comme

        struct BankAccount{
            size_t accountNumber;
            float balance;
        };

        Tu serais très embêté si ton compte et le mien présentaient le même numéro de compte parce que le risque serait alors très gros que ton salaire arrive sur mon compte et que le payement de ma facture d'électricité parte du tien!

        On ne veut donc surtout pas qu'il puisse exister, à un instant T de l'exécution du programme, deux instances de BankAccount dont la valeur de accountNumber soit identique (que la valeur de balance soit la même ou non n'aurait aucune espèce d'intérêt dans le cas présent :D )

        Pire encore : il faut absolument que la valeur de balance pour l'instance qui représente mon compte bancaire soit systématiquement mise à jour à chaque fois qu'une opération est effectuée sur mon compte.

        Il est donc absolument hors de question d'accepter qu'une copie de l'instance qui représente mon numéro de compte soit créée à l'occasion de l'appel de la moindre fonction ;)

        Et, de plus :

        • Il y aura au moins une donnée-- que l'on appelle identifiant -- dans la classe (bankAccount) dont la valeur ne pourra jamais changer : si je change cette valeur, je change de numéro de compte
        • la valeur des autres données (celle de balance, dans mon exemple) peut quant à elle parfaitement changer sans, pour autant mener à la création d'une nouvelle instance ;)

        Par contre, on peut imposer des règles différentes pour différents types de compte bancaire (compte "normal", "d'épargne", "d'entreprise" ou autres ;) ), mais tous devraient pouvoir réagir "comme s'il s'agissait" d'un compte bancaire "sans autre précision" (on parle de substituabilité)

        C'est la raison pour laquelle on dit que les classes qui présentent une sémantique d'entité sont:

        • non copiable (on ne veut pas pouvoir créer une copie de l'instance de mon compte bancaire)
        • non assignable (mon compte bancaire est ... à moi et à moi seul : je ne veux pas que Martin puisse disposer d'un compte bancaire dont la valeur de accountNumber serait identique)
        • non comparable : on peut comparer "séparément" chacune des valeurs qui composent la donnée, mais il ne sert à rien de permettre la comparaison de toutes les valeurs ensembles.
        • généralement mutables : si j'ajoute ou que je retire des sous de mon compte, je fais varier la donnée balance, mais... ca reste malgré tout mon compte en banque :D
        • impossible à convertir en un type de donnée différent
        • particulièrement susceptible d'intervenir dans une hiérarchie de classes

        Au final, il faut bien comprendre que, même si différents termes servent -- parfois -- à désigner des notions très similaires, il reste toujours certaines "variations" dans les termes qui les rendent parfaitement adaptés à certaines situation et complétement inaptes à d'autres.

        Le choix d'un terme particulier pour désigner une notion n'est donc jamais fait selon "l'humeur du moment", mais découle du besoin de désigner très précisément la notion dont on parle à un moment donné ;)

        -
        Edité par koala01 16 juin 2019 à 15:24:45

        • Partager sur Facebook
        • Partager sur Twitter
        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
          14 juin 2019 à 23:18:56

          Hello,

          koala01 a écrit:

          C'est la raison pour laquelle on dit généralement que les classes ayant sémantique d'entité sont

          • copiable (on peut copier les valeurs qui composent une instance particulière pour en créer une nouvelle
          • ...

          Ce ne serait pas plutôt sémantique de valeur ? ^^

          -
          Edité par Guit0Xx 14 juin 2019 à 23:32:56

          • Partager sur Facebook
          • Partager sur Twitter

          ...

            15 juin 2019 à 3:32:00

            Au temps pour moi, mes doigts se sont emmelés :'(  J'ai corrigé :D

            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
              16 juin 2019 à 6:46:38

              Grosse fatigue, tu manques d'eucalyptus mon cher Koala ;) 

              Au PO: Un autre exemple d'entité, c'est toi. Même en faisant tous les efforts du monde, je ne peux pas devenir toi (non assignable), et quand bien même j'arriverai à faire un clone parfait de toi (avec tes souvenirs, et tout...), ta vie et celle du clone que j'aurais "fabriqué" seraient forcément différentes ne serait ce que parce que physiquement, il est impossible que toi est ton clone se trouvent exactement au même endroit en même temps (non copiable). Toi et moi sommes des êtres humains (du mêmes type donc), mais nous ne sommes ni substituables, ni comparable, tu es toi, et je suis moi, même si nous serons peut être d'accord sur des tas de choses, nous ne seront jamais d'accord sur tout. Ce que je peux faire est différent de ce que tu peux faire même si il y a un très grand nombre de choses que nous pouvons faire tous les deux... Nous sommes (en tant qu'être humain), l'archétype de la notion d'entité.

              -
              Edité par int21h 16 juin 2019 à 7:20:56

              • Partager sur Facebook
              • Partager sur Twitter
              Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                9 juillet 2019 à 15:21:08

                Ce que vous dites n'est pas incompatible avec ce que j'exprimais ^^

                gbdivers :

                Tu peux avoir plusieurs instances d'une classe a sémantique de valeur et plusieurs instances d'une classe a sémantique d’entité.

                Certes, mais c'est pour une raison pratique. (Ce qui revient effectivement à dire que la différence est conceptuel) En soit, ça n'as pas trop de sens de faire exister deux instances de "123" à sémantique de valeur. D’ailleurs il me semble qu'en python, ils pointent justement vers la même adresse. 

                koala01 :

                On est bien d'accords, qu'en terme de programmation, tout ça n'est qu'une représentation. Il y a un aspect pratique à considérer qui nous détourne du sens réel de la chose. De la sémantique. Pour ton example du hall d'entré et de la chambre tout les deux peints de la même couleur, si on voulais être exact, il ne faudrait pas un type "Color" mais un type "Color* " qui pointerait vers "Color::bleu" par exemple. Mais question pratique c'est plus simple un type "plein".

                Je ne vois pas comment exprimer différemment tout ça "les notions de classe/instance et de entité/valeur sont identiques à un niveau différent d'abstraction." Je parle bien des concepts, pas de la façon dont on va implémenter ces concepts. 

                Dans le sens ou ce sont des concepts, on peut les appliquer à pleins de choses, et sous différents angles. Par exemple, une entité pourrait être définie comme une "valeur" "identifiable". Donc une partie donnée / attributs, et la définition des operateurs == / != sur leur partie entité. Généralement, on implémente ça avec un ID. Mais on pourrait le faire en interdisant les doublons et en définissant l'operateur == / != sur tout les membres d'une instance.

                Très basiquement, une valeur (ou une class) correspond au concept même de définition. Unique, général. Si on modifie la définition, on modifie tout les comportements associés. La définition n'as pas à exister 2 fois. Le concept d'entité (ou instance) lui, correspond à l'application d'une définition. Une entité peut donc exister de façon similaire (ou non) plusieurs fois. 

                Qu'en pensez vous ?

                -
                Edité par Noctelupus 9 juillet 2019 à 15:25:57

                • Partager sur Facebook
                • Partager sur Twitter
                  9 juillet 2019 à 17:02:01

                  Mouais, bof toujours. J'ai l'impression que tu essaies de forcer cette similarité, en te focalisant sur les points qui confirment ce que tu penses. C'est un peu comme si tu me disais que les concepts de voiture et d'avion sont identiques, puisqu'ils ont des roues tous les 2.

                  Mais bon ok, peut être que je ne vois pas ou tu veux en venir. Supposons que ton idée est correcte. Cela permet de déduire quoi ou de comprendre quoi ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 juillet 2019 à 17:03:53

                    J'en pense que la finalité est importante.

                    Le but ultime est de nous simplifier la vie en appliquant des recettes de cuisine et en prenant conscience que des choses ne sont pas applicables à tout type de données.
                    - valeurs: copie et affectation doivent être supportées ; suivant la définition exacte de sémantique de valeur que l'on prend (il y a des nuances qui évoluent dans le temps et entre les auteurs quand on commence à parler de types réguliers), on peut aussi avoir une comparaison d'égalité, voire,  un ordre. Dans tous les cas, pas d'héritage public sans sacrifier des choses. La notion d'identité est non pertinente sur des valeurs.

                    - entités: OSEF de la comparaison de valeur (même si on peut comparer des sous-ensembles des entités), copie et affectations ne peuvent pas fonctionner sans induire des problème potentiels. Rien de tout cela ne sens sur des entités. Techniquement on peut bidouiller des solutions bancales, et totalement inutiles car on n'en n'a pas besoin. Sinon, parfaitement compatible avec l'héritage public. La notion d'identité est omniprésente sur des entités. On retrouve la notion de clé primaire des bases de données.

                    Cela n'empêche pas une entité de contenir des valeurs: "relevé de température au 29juin: 40°C". J'ai une entité avec sa clé primaire pour l'identifier, et sa valeur associée. Je peux trier/comparer les clés ou les valeurs. Sur les entités, au sens global cela n'a aucun sens. Cela n'a de sens que relativement aux informations de nature valeurs qui sont contenues/portées par l'entité.

                    -----

                    Bref, dès que l'on arrive à identifier la sémantique de l'on va donner à une information (! un type n'est pas une information que nous allons manipuler dynamiquement en C++), en découle très rapidement des recettes de cuisines que l'on peut appliquer sans plus réfléchir -- la réflexion théorique ayant été faite en amont.

                    PS: intrinsèquement une valeur n'est pas une classe, et vice-versa. C'est une valeur. Elle existe. Une classe est un modèle de type, et comme tout type, il permet de dire comment une séquence de bytes devra être interprétée par le compilateur/quelles opérations sont réalisables dessus.

                    PPS: Certains vont jusqu'à dire que 12 et "douze" représentent la même valeur et que donc ils sont égaux -- cf je ne sais plus qu'elle conf de John Lakos sur la sémantique de valeur.

                    PPPS: Element Of Programming a été "libéré", c'est un des documents quasi-fondateurs  sur la sémantique de valeur en C++ http://elementsofprogramming.com/
                    (J'avais un autre doc fondateur très sympa, mais que je ne retrouve pas :()

                    • Partager sur Facebook
                    • Partager sur Twitter
                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                      9 juillet 2019 à 20:03:14

                      Noctelupus a écrit:

                      On est bien d'accords, qu'en terme de programmation, tout ça n'est qu'une représentation. Il y a un aspect pratique à considérer qui nous détourne du sens réel de la chose. De la sémantique. Pour ton example du hall d'entré et de la chambre tout les deux peints de la même couleur, si on voulais être exact, il ne faudrait pas un type "Color" mais un type "Color* " qui pointerait vers "Color::bleu" par exemple. Mais question pratique c'est plus simple un type "plein".

                      Cela va même beaucoup plus loin que cela!!!

                      Vas dans n'importe quelle grande surface, et trouve le rayon des boites de conserve.

                      Dans le rayon des boites de conserves, essaye de trouver la partie réservée au haricots.  Tu y verras sans doute des boites de différentes marques en différentes tailles.  Mais pour une marque et une taille donnée, tu y trouveras sans doute... plusieurs boites identiques.

                      Mais le contenu de ces boites n'est pas partagé entre les différentes boites: si tu décide d'emporter une boite de haricots, et que je passe juste après toi et que je prend la même décision, il n'y aura aucune compétition entre nous pour savoir qui pourra profiter du contenu de la boîte : Ce  ne sera pas "le premier qui ouvre sa boite et en prend le contenu mange des haricots, les autres mangent des cailloux" ;)

                      Il en va de même avec les couleurs; en voici la preuve:

                      Mettons que tu aies décidé de repeindre ta chambre.  Tu vas chez le marchand de peinture, mais tu n'y trouve aucune teinte qui te plaise réellement.

                      Tout dépité, tu vas dans ton atelier, et tu te rends compte que tu as tout un stock de pots de couleur -- différentes -- suffisant pour repeindre trois fois tous les murs de ta maison, mais dont aucune couleur ne t'inspire réellement.

                      Tu décides donc de mélanger 'un peu de ceci, un peu de cela, une pointe de l'autre" pour créer la teinte qui te fait rêver.

                      "Manque de bol", la quantité de peinture que tu obtiens est ... tout juste suffisante pour peindre la moitié du mur.  "Par chance", tu as pris très rigoureusement note des proportion des différentes couleurs que tu as utilisées, et, surtout, il te reste assez des couleurs d'origine que pour refaire exactement le même mélange (et donc, obtenir exactement la même teinte au final).

                      Il n'y a donc aucun problème (sans solution), car "il te suffit" de redescendre dans ton atelier et ... de refaire exactement le même mélange (avec exactement les mêmes proportions) pour pouvoir terminer de peindre ton mur.

                      Et, si, six mois plus tard, tu décide de repeindre ton hall d'entrée, et que tu es décidément tombé amoureux de la teinte que tu as utilisée pour ta chambre, il n'y a -- a priori -- absolument aucun problème sans solution : tu ressors la "formule" (les proportions) qui t'a permis d'obtenir la teinte, et tu recrées de nouveau le même mélange.

                      "Re manque de bol": la quantité de peinture qui reste dans l'un des pots de couleur utilisé est insuffisante pour respecter les proportions indiquée.  C'est vachement embêtant, mais c'est un problème qui a sa solution : tu cours chez le marchand de peinture acheter un nouveau pot de la couleur dont tu as besoin, et le "tour est joué" ;). 

                      Mais tu peux aussi décider de modifier un tout petit peu les proportions, et donc de créer une nouvelle teinte, très proche de celle de ta chambre, mais avec "une petite différence", sans pour autant changer la teinte ... des murs de ta chambre.

                      Tout cela pour te dire que ce n'est pas uniquement par facilité que l'on décide d'utiliser des types pleins au lieu de pointeurs:  C'est pour pouvoir copier la donnée à loisir et, le cas échéant, décider de modifier une des instances sans risquer d'aller modifier les autres ;)

                      Noctelupus a écrit:

                      Je ne vois pas comment exprimer différemment tout ça "les notions de classe/instance et de entité/valeur sont identiques à un niveau différent d'abstraction." Je parle bien des concepts, pas de la façon dont on va implémenter ces concepts.

                      Absolument pas!!!

                      La notion de classe, pour faire simple, c'est le terme que l'on utilise pour désigner "quelque chose": "couteau", "cuiller", "maison", "voiture", ...

                      La notion d'instance, pour faire tout aussi simple, c'est la donnée à laquelle on peut accéder au travers d'un identifiant qui lui est propre: "le couteau à  pain à la lame ébrêchée", "la cuiller utilisée par Antoine pour son café", "la maison bleue du bout de la rue", "la voiture de Jim", ....

                      la notion (de sémantique) de valeur représente certaines propriétés intrinsèques d'une classe (copiable et assignable); la notion (de sémantique) d'entité représente d'autres propriétés intrinsèques d'une classe, qui sont totalement incompatibles avec la sémantique de valeur.

                      D'ailleurs, les propriétés des deux sémantique sont à ce point incompatible que l'on pourrait presque dire que la sémantique de valeur est l'exact opposé de la sémantique d'entité  ;)

                      Noctelupus a écrit:

                      Je parle bien des concepts, pas de la façon dont on va implémenter ces concepts. 

                      Et, justement, je viens de te démontrer que je parle de concepts, et non de la manière dont on les implémente ;). Si je devais m'intéresser à la manière de les implémenter, je te tracerais les associations suivantes:

                      • instance : variables (Type unNom) et constantes (Type const unNom)
                      • classe : définition de classe (class MaClasse{/* ... */ }; ) et de structures (struct{/* ... */};
                      • valeur : forme canonique de coplien au complet ( constructeur, constructeur de copie, opérateur d'affectation, destructeur), quitte à ce que certaines parties soient implicites (automatiquement ajoutées par le compilateur), aucune fonction virtuelle
                      • entité : non copiable, non assignable, destructeur virtuel, "un certain nombre" de fonctions virutelles possibles

                      Noctelupus a écrit:

                      Dans le sens ou ce sont des concepts, on peut les appliquer à pleins de choses, et sous différents angles.

                      Non, justement! Nous sommes très loin des concepts de pile, de file, de liste ou d'arbres binaires qui entre tous dans le concept de "collection d'objets", ou des concept de "boucles 'pour'", de "boucle 'tant que'" et de "boucle 'jusqu'à'" qui entre tous dans le concept de "boucle".

                      Le concept de classe entre dans le catégorie du concept de type (un certain nombre de byte pour le représenter en mémoire, un certain nombre d'actions susceptible d'être appliquées), dont dépend le concept d'instance.

                      Quant aux concepts d'entité de valeur, ils entre dans la catégorie des concepts "de sémantique", et sont à ce point antinomiques que l'on ne peut absolument pas utiliser l'un à la place de l'autre.

                      Noctelupus a écrit:

                      Ce que vous dites n'est pas incompatible avec ce que j'exprimais ^^

                      gbdivers :

                      Tu peux avoir plusieurs instances d'une classe a sémantique de valeur et plusieurs instances d'une classe a sémantique d’entité.

                      Certes, mais c'est pour une raison pratique. (Ce qui revient effectivement à dire que la différence est conceptuel) En soit, ça n'as pas trop de sens de faire exister deux instances de "123" à sémantique de valeur. D’ailleurs il me semble qu'en python, ils pointent justement vers la même adresse. 

                      koala01 :

                      Par exemple, une entité pourrait être définie comme une "valeur" "identifiable".

                      Non!!! Ce serait beaucoup trop facile! Parce que u peux déjà identifier n'importe quelle instance au travers de l'identifiant que tu lui a donné ou de l'adresse mémoire à laquelle elle se trouve.  Si on suit ton raisonnement, la sémantique de valeur n'a aucune raison d'être, vu que, par nature, n'importe quelle donnée est identifiable de manière strictement unique et non ambigüe.

                      La distinction entre valeur et entité porte exclusivement sur la réponse à une question simple:

                      Puis-je avoir sans risque, à un instant T de l'exécution, deux instances présentant exactement les même valsurs?

                      Pour une donnée de type couleur, il n'y a pas de problème.  Mais, si on parle de la "voiture de Jim" ou de "la maison bleue du bout de la rue", c'est beaucoup plus problématique

                      Noctelupus a écrit:

                      Donc une partie donnée / attributs, et la définition des operateurs == / != sur leur partie entité.

                      C'est justement là le problème: pour une valeur, les opérateurs == et != portent sur l'ensemble des parties qui composent une donnée :

                      Tu peux vérifier si une couleur est identique à une autre en vérifiant respectivement les proportions de rouge, de vert et de bleu, sous une forme proche de

                      /* j'utilise une structure par simplicité */
                      struct Color{
                          int red;
                          int green;
                          int blue;
                      }
                      bool operator ==(Color const & a, Color const & b){
                          return a.red == b.red &&
                                 a.green == b.green &&
                                 a.blue == b.blue;
                      }
                      bool operator != (Color const & a, Color const & b){
                          return !(a==b);
                      }

                      Pour une entité, voyons voir un peu ce qui se passe:

                      struct Voiture{
                          Immatriculation imat;
                          Marque marque;
                          Modele modele;
                          Cylyndree cyl;
                          Carburant carbu;
                          Annee annee;
                          Couleur couleur;
                          Km kilometrage;
                          Km entretien_precedent;
                      };
                      /** avec une instance qui correspond à la voiture de Jim :
                       **/
                      Voiture aJim{"64 - JIM - 001","Citroen","Saxo","1800",diesel, 2008, antracite};

                      Crois tu vraiment, que l'on puisse trouver "quelque part":

                      1. deux instances de Voiture qui présentent exactement les même valeur
                      2. deux instances de Voiture dont l'immatriculation est "64 - JIM - 001" mais dont l'une serait une citroen et l'autre une peugeot
                      3. plusieurs instances de citroen saxo 1800 diesel de couleur antracite, mais dont l'immatriculation n'est forcément pas "64 - JIM - 001"
                      4. d'autres instances de voitures 1800 diesel de 2008, de couleur entracite, qui ne soient pas des citroen saxo (et dont la plaque n'est pas "64 - JIM - 001"

                      pour (1) : surement pas!!! Cela mènerait à des catastrophes : comment pourrait on savoir sur quelle instance de la voiture de Jim on travaille lorsqu'elle est transmise en paramètre ?

                      Pour (2) : j'espère bien pour Jim que non, car je le plaindrait de tout mon coeur le jour où il recevrait un PV destiné au conducteur de la peugeot

                       Pour (3) et (4) : cela ne présente aucun problème : le 1800 diesel est un moteur (quelle que soit la marque) relativement robuste, l'antracite est une couleur assez sympa ;)

                      On se rend donc bien compte qu'il n'y a absolument aucun sens à vérifier l'égalité de l'ensemble des composant de la classe voiture, vu que ce qui importe, c'est son immatriculation.

                      Par contre, il n'y a absolument rien qui nous empêche de comparer la marque, le modèle, la cylindrée, le carburant utilisé ou la couleur de deux voitures, sans tenir compte de l'immatriculation ;)

                      Mais ca, c'est secondaire!  Car notre principal problème n'est pas de savoir ce que l'on peut comparer avec une entité ou avec une valeur (note, d'ailleurs, qu'il n'y a rien qui nous empêche d'envisager la comparaison de certains éléments constitutifs de la valeur).

                      Notre véritable problème est que l'on ne veut surtout pas risquer de se retrouver, à un moment donné de l'exécution, avec deux instances différentes (par leur adresse mémoire) de la "voiture de Jim".

                      A l'inverse, il n'y a rien qui nous empêche d'avoir plusieurs instance de la couleur antracite.  D'ailleurs, il se peut tout à fait que la teinte utilisée chez peugeot soit un tout  petit peu différente de celle utilisée chez citroen, malgré le fait qu'elles portent le même nom :-°

                      Noctelupus a écrit:

                      Mais on pourrait le faire en interdisant les doublons

                      Et, dis moi, comment comptes-tu t'y prendre pour interdire les doublons???

                      1. en utilisant un std::/*multi*/set ou une std::/*unordered_*/map, peut être
                      2. Ou, peut-être, en comparant les différentes données / attributs / membres (*) de l'instance que tu veux ajouter à ta collection?

                      (1) c'est vraiment pas le plus efficace que l'on puisse trouver, en fonction des besoin spécifique de la collection

                      (2) Et, quand tu te retrouve avec différentes données qui viennent de gauche ou de droite, tu fais comment ?

                      Et, surtout, dans la fonction qui devra mettre le kilométrage de la voiture de Jim à jour (après qu'il ait parcouru 2000 km pendant ses vacances) ou tenir compte de l'entretien qui a été fait aujourd'hui, comment vas tu t'assurer de réellement travailler sur la voiture de Jim, et non sur une "pale copie" de celle-ci, simplement parce que tu auras oublié une esperluette?

                      La propriété essentielle de la notion d'entité résoud tous ces problèmes, et bien d'autres d'ailleurs, en interdisant purement et simplement la copie et l'assignation (et en demandant au compilateur de veiller à faire respecter ces interdictions); et c'est ce qui fait toute la différence entre la sémantique de valeur (qui n'a pas vraiment de raison de les interdire) et la sémantique d'entité ;)

                      (*) Toi qui essaye désepérément de trouver des concept identiques là où il n'y en a pas, voici de quoi te satisfaire :D les concepts de données, d'attributs et de membres sont suffisamment proches les uns des autres (surtout attribut et membres, d'ailleurs) pour que l'on puisse envisager de les utiliser comme sinonymes ;)

                      Il n'y a qu'une légère contrainte qui existe pour les concepts d'attributs et de membres qui est absente du concept de donnée : attributs et membres font forcément partie d'un type de donnée "complexe" car composé de ... plusieurs données, alors qu'une donnée ne présente pas forcément cette spécificité ;)

                      Noctelupus a écrit:

                      Très basiquement, une valeur (ou une class) correspond au concept même de définition.

                      Non, c'est toute la différence entre le verbe "être", le verbe "avoir" et surtout le vers "s'appliquer à" !!!

                      une valeur EST (enfin, potentiellement) une classe. Entité EST (enfin, généalement) une classe.

                      Ou, plutôt, la sémantique de valeur s'applique (potentiellement) à  une classe: Après tout, le type int n'est pas une classe (ni une structure), mais la sémantique de valeur s'applique parfaitement à ce type de donnée.

                      De son côté, la sémantique s'applique généralement à une classe (ou à une structure), à l'exclusion de tout autre manière dont on peut disposer pour définir la notion de type ;)

                      Dans l'autre sens,  une classe (ou une structure), ou même n'importe quel genre de type de donnée, A forcémentune sémantique particulière qui ne pourra être que sémantique de valeur OU sémantique d'entité (mais en aucun cas les deux).

                      Noctelupus a écrit:

                      Si on modifie la définition, on modifie tout les comportements associés.

                      Mais, justement, on ne modifie absolument pas la définition des concepts!!!

                      Noctelupus a écrit:

                      La définition n'as pas à exister 2 fois.

                      Tu as tout à fait raison... quand il s'agit d'un seul et même concept!

                      Mais, dans le cas présent, nous sommes face, non pas à un concept unique, mais bien à quatre concepts différents et totalement indépendants les uns des autres!

                      Il est donc tout à fait normal d'avoir quatre définitions totalement différentes, avec des comportements associés différents, tu ne crois pas ?

                      Noctelupus a écrit:

                      Le concept d'entité (ou instance) lui, correspond à l'application d'une définition. Une entité peut donc exister de façon similaire (ou non) plusieurs fois.

                      Je crois, en arrivant à ce point de la sitation, que le gros problème est le genre d'association que tu crois voir...

                      Je peux me tromper, mais il semble ressortir de ce que tu lis que, pour toi, on a deux associations du genre de

                      classe < == > valeur<
                      /* ET */
                      instance < == > entité

                      Tu te trompes très lourdement dans tes associations, car, si associations il doit y avoir, elles sont du genre de

                      classe < == >type
                      type --> instance
                      valeur < != > entité

                      (avec < == > représentant la relation "EST UN", --> représentant la relation "Mène à " et < != > représentant la relation "est opposé à")  Je m'explique:

                      la notion de classe est "une représentation parmis d'autres" du concept de "type de donnée défini par l'utilisateur" et qui s'apparente par conséquent à la notion de "type de donnée"

                      Un type de donnée, c'est quoi? c'est le moyen dont le développeur dispose pour décrire de manière très précise la manière dont il souhaite que le compilateur représente "certaine notions" (par exemple, la notion de voiture ou de couleur) ainsi que les différentes manipulations que le compilateur devra accepter.

                      Autrement dit, la notion de type est une abstraction qui n'intéresse que le développeur et le compilateur.

                      Et, pour être complet, cette abstraction ne descendra jamais plus bas que le compilateur: si tu regarde le code binaire exécutable par le processeur généré par le compilateur, tout ce que tu verras, ce sont des successions de byte et des tailles à utiliser (ou, plus souvent, des additions pour obtenir une adresse mémoire)

                      La notion de type nous mène tout droit à la notion d'instance. Une instance, c'est le moyen par lequel le développeur demande au compilateur de mettre "tout ce qu'il faut" en place, au niveau du code binaire qui sera exécuté par le processeur -- pour pouvoir représenter et manipuler une donnée du type indiqué.

                      En terme d'abstraction, nous sommes donc "un niveau plus bas", car, même si le développeur passe par le compilateur, la "destination finale" reste ... le code binaire exécutable par le processeur.

                      Les notions d'entité et de valeur (en réalité, les notions de "sémantique d'entité" et de "sémantique de valeur") n'ont absolument rien à voir avec les quatre notions dont je viens de parler (respectivement "classe", "type définis par l'utilisateur", "type" et "instance").

                      Ces notions nous permettent de classer les types de données que nous voudrons décrire pour le compilateur en deux grandes catégories d'un point de vue purement conceptuel:

                      • les type de données qui peuvent être copiés et qui peuvent être assignés (mais qui n'interviendront jamais dans une hiérarchie de classe) et
                      • les type de données qui ne peuvent pas être copiés et qui ne peuvent pas être assignés (mais qui pourraient éventuellement intervenir dans une hiérarchie de classes)

                      En terme d'abstraction, nous nous arrêtons déjà "un cran au dessus" du compilateur, car ces notions se sont réellement que "de pures vues de l'esprit" de la part du développeur, et rien d'autre.

                      Alors, bien sur, les sociétés qui développent les compilateurs les ont un "tout petit peu" modifiés depuis C++11 à l'instigation du comité de standardisation, pour qu'ils puissent nous aider garantir ces "vues de l'esprit".

                      Mais cela n'empêche que, même si le développeur est désormais en mesure d'indiquer explicitement au compilateur que "tel type de donnée a sémantique d'entité" (étant sous entendu, s'il ne dit rien, concernant un type défini par l'utilisateur, qu'il a sémantique de valeur), cette information ne sera utilisée par le compilateur que dans sa phase de vérification ;)

                      Pour shématiser un peu les choses, le développeur se balade allègrement entre cinq niveaux d'abstractions strictement indépendants que l'on pourrait désigner  sous la forme de:

                      • niveau 0 : les bits et les bytes tels que le processeur est en mesure de les manipuler
                      • niveau 1 : les informations (fournies par le développeur) utilisées par le compilateur pour générer le code de niveau 0
                      • niveau 2 : les informations (fournies par le développeur) utilisées par le compilateur pour ... s'assurer que le développeur n'a pas fait de conneries
                      • niveau 3 : l'expression, compréhensible par le compilateur, de la "vue de l'esprit" du développeur
                      • niveau 4 : la "vue de l'esprit" du développeur dans toute sa splendeur conceptuelle (et indépendante du langage utilisé")

                      Et nous pourrions donc assez facilement dresser un tableau représentant les différents niveaux d'abstractions par lesquels les différentes notions vont passer (et, par conséquent : le niveau d'abstraction au delà duquel elles ne vont pas) sous une forme proche de

                      notion        | niv 4 | niv 3 | niv 2 | niv 1 | niv 0|niveau final
                      --------------+-------+-------+-------+-------+------+-------------
                      instance      |   v   |   v   |   v   |   v   |   v  | 0
                      --------------+-------+-------+-------+-------+------+------------
                      type /        |   v   |   v   |   v   |   v   |      | 1
                      classe        |       |       |       |       |      |
                      --------------+-------+-------+-------+-------+------+------------
                      valeur        |   v   |   v   |       |       |      | 3
                      --------------+-------+-------+-------+-------+------+------------
                      entité        |   v   |   v   |       |       |      | 3
                      --------------+-------+-------+-------+-------+------+------------
                      copie ou non? |   v   |       |       |       |      | 4
                      --------------+-------+-------+-------+-------+------+------------

                       Pour que ce tableau prenne réellement tout son sens, il ne me reste plus qu'une chose à expliquer:

                      Peu importe que toutes ces notions trouvent leur origine au niveau de "la pure vue de l'esprit" du développeur.  Comment pourrait-il en être autrement?

                      Peu importe aussi les différents niveaux qui ne sont que "traversés" par les différentes notions, car il ne font que permettre (ou non) à la notion en question de "passer vers le niveau suivant".

                      Ce qui importe, c'est le niveau d'abstraction à partir duquel une notion est littéralement bloquée; le dernier niveau d'abstraction au delà duquel la notion perd "tout son sens".

                      Si tu veux créer une relations entre deux notions, il y a des règles à accepter:

                      • Les relations que j'ai représentée plus haut par  < == >et < != > ne peuvent exister qu'entre deux notions qui s'arrêtent (*) au même niveau d'abstraction
                      • les relations que j'ai représentée  plus haut par --> ne peuvent exister entre deux notion que si celle de droite s'arrête à un niveau d'abstraction inférieur à celui à auquel s'arrête la notion de gauche
                      • dans l'idéal, on limite la relation --> au premier niveau inférieur qui sert de point d'arrêt

                      Pour donner bien fixer ces règles, nous pouvons créer les relations

                      • copie ou non? --> entité / valeur
                      • entité / valeur --> classes / types
                      • classes / type --> instances
                      • entité < != > valeur

                      Le reste, ce sont des relations indirectes, comme par exemple:

                      • copie ou non ? --> valeur --> type --> instance

                      Mais de là à dire que la notion de sémantique mène "tout droit à la notion d'instance, il y a de la marge ;)

                      (*) Et encore, à condition qu'elles entre dans exactement dans les mêmes catégories, car le concept de test et le concept de boucle sont tous les deux des concepts algorithmiques, dont la réalité se retrouve au niveau d'abstraction le plus bas (le code binaire exécutable), mais, comme le concept de boucles dépend du concept de test, il se trouve en réalité "un petit cran plus haut", ce qui nous empêche de les comparer effectivement:

                      l'objectif recherché par ces deux concepts et leurs cas d'utilisation sont en effet totalement différents, et, s'il peut arriver que l'on fasse appel à une boucle pour effectuer un test, ce n'est jamais qu'un cas d'utilisation totalement dégradé des boucles ;)

                      Bien sur, tout cela est simplifié à l'extrême, car j'aurais sans doute pu trouver une bonne dizaine de niveaux d'abstractions intermédiaire supplémentaire ;)

                      -
                      Edité par koala01 9 juillet 2019 à 21:36:09

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait

                      Petite réflexion classe - instance entité - valeur

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown