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 :

Les accesseurs et les détails d'implémentation [Tutoriel]


Sujet :

C++

  1. #41
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    [...]
    Cette solution me semble préférable, puisque l'on ne pollue pas l'interface des classes avec une fonction qui n'ont rien à voir avec la sémantique de l'objet manipulé (quand on fait des manipulations géométrique sur un triangle en 3D, on se moque un peu que ce triangle soit affichable, qu'il soit lisible et enregistrable sur un fichier, sérialisable sur le réseaux, etc.)
    [...]
    Selon je-ne-sais-plus-qui (Meyers ?), une fonction F (ou classe) déclarée comme amie d'une classe C fera partie de son interface. L'interface se définissant comme le nombre de fonctions / membres publiquement accessibles qui fournissent un service en rapport à une donnée stockée dans la classe. (Peu claire, mon histoire.)

    En gros, un membre public ne brise pas plus l'encapsulation qu'un couple de getters/setters. Enfin, sauf si le setter n'est pas idiot (i.e. vérification de bornes ou autre). Mais, dans ce cas, ce n'est plus vraiment un setter.

  2. #42
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 Ekleog Voir le message
    Selon je-ne-sais-plus-qui (Meyers ?), une fonction F (ou classe) déclarée comme amie d'une classe C fera partie de son interface. L'interface se définissant comme le nombre de fonctions / membres publiquement accessibles qui fournissent un service en rapport à une donnée stockée dans la classe. (Peu claire, mon histoire.)
    Je suis pas mal d'accord sur les fonctions (hors problème de conception (qui peut toujours être discuté dans ce cas précis) une fonction F amie d'une classe C fait partie de l'interface de cette classe C). Je suis moins d'accord sur le fait qu'une classe amie A d'une classe C fasse partie de l'interface de C. Je vais essayer de mettre mes idées au clair sur ce sujet.

    Citation Envoyé par Ekleog Voir le message
    En gros, un membre public ne brise pas plus l'encapsulation qu'un couple de getters/setters. Enfin, sauf si le setter n'est pas idiot (i.e. vérification de bornes ou autre). Mais, dans ce cas, ce n'est plus vraiment un setter.
    Tout juste. Dès lors qu'on commence à implémenter des setters qui font autre chose qu'une initialisation, on introduit dans le design un problème de sémantique - la fonction n'est plus nommé en fonction de son comportement visible, mais en fonction du courage du programmeur, ce qui n'as pas vraiment de sens

    Par exemple, la méthode suivante :

    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
     
    class point
    {
    private:
      float x_, y_, z_;
      boundary_box *bbox_;
    public:
      void set(float nx, float ny, float nz)
      {
        if (bbox_) {
          if (bbox_->contains(nx,ny,nz)) {
            *this = point(nx, ny, nz);
          } else {
            *this = bbox->intersect(segment(*this, point(nx,ny,nz));
          }
        } else {
          *this = point(nx, ny, nz);
        }
      }
    };
    pose un petit problème. D'après le nom, je devrai pouvoir écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    point  p;
    // ...
    p.set(1000.0f,1000.0f,1000.0f);
    assert(p.x() == 1000.0f);
    assert(p.y() == 1000.0f);
    assert(p.z() == 1000.0f);
    C'est ce que me dis le set(). Mais selon la valeur de la bounding box, ces assertions ne sont peut-être pas vraie.

    La réponse à la question "est-ce que je peux écrire un setter intelligent ?" n'est pas "non, parce que les setters, c'est mal". C'est "que dis tu ? les setters intelligents n'existent pas. Mais si tu changes le nom de ta fonction, tu garderas le même comportement, tout en y gagnant énormément en facilité de lecture - parce que la sémantique des noms de fonctions sera en adéquation avec leur comportement". Dans l'exemple précédent, un nom correcte serait plutôt du style move_in_bbox() (ce qui pourrait d'ailleurs permettre une fonction supplémentaire move qui, elle ne serait pas restreinte à la bounding box).
    [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.

  3. #43
    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
    Ceci dit, je serais beaucoup plus partisan de l'interdiction des mutateurs au profit des comportements bien nommé, que d'une interdiction "totale" des accesseurs...

    Pour ce qui est des accesseurs, je suis plutôt partisan d'une "utilisation raisonnée" de ceux-ci.

    Je m'explique :

    Il y a des accesseurs qui exposent très clairement des détails d'implémentation dont la connaissance ne devrait pas être nécessaire en vertu de demeter.

    Par exemple, il est totalement inopportun de placer un accesseur "getRevservoir" dans une classe voiture car, bien que l'on sache pertinemment qu'il y a bel et bien un réservoir d'essence sur chaque voiture, on ne devra jamais travailler directement sur celui-ci et toute action sur le réservoir devrait être transparente pour l'utilisateur de voiture (c'est à l'interface voiture de fournir les fonctions "tankLevel", "refill", "add(quantity)", "isOnReserve",...)

    Par contre, *certains* accesseurs sont simplement l'expression d'un service rendu par la classe.

    On peut discuter de la sémantique que l'on donne à un point, et j'avouerai que je serais du genre à accepter les fonctions x, y et z, simplement parce que, dans mon esprit, un point n'est pas quelque chose dont la responsabilité est d'être traçable, mais bien quelque chose dont la responsabilité est... de représenter une coordonnée

    De même, pour le réservoir, je n'aurais aucun problème à y placer un accesseur sur la capacité maximale qu'il peut contenir, simplement parce que cela fait partie des services que l'on peut attendre de la part d'un réservoir.

    Je serais beaucoup moins tolérant face à l'introduction d'une accesseur sur la quantité de carburant actuellement dans le réservoir, et je préférerais un comportement indiquant le "niveau de remplissage", sous la forme du quotient entre la capacité maximale et la quantité présente, nommé "niveauDeRemplissage" ou tout nom similaire, voir d'une fonction "estSurReserve" renvoyant vrai si la quantité est inférieure à une certaine valeur (mettons 5 litres, vu que c'est la quantité habituelle de la réserve).

    La raison est toujours la même, car on pourra me dire que cela revient "presque au même" : getQuantity expose un détail d'implémentation dans le sens où cela renvoie une "donnée brute", alors que "niveauDeRemplissage" ou "estSurReserve" correspondent bel et bien à des services que l'on est en droit d'attendre de la part du réservoir, à savoir : permettre d'afficher une jauge représentant l'état de remplissage et permettre d'allumer un témoin lorsque le niveau de remplissage descend en dessous d'une limite inférieure

    De plus, j'ai toujours eu tendance à estimer que tout code ne vaut que par l'utilisation qui en est faite et qu'un code inutilisé n'aura servi qu'à faire perdre du temps à celui qui l'a mis au point (voire, à lui faire s'arracher les cheveux).

    Aussi, un exemple ne se basant que sur une seule classe me semble peut etre un peu léger, dans le sens où cela ne permet que difficilement au lecteur de se faire une idée précise de la manière dont l'auteur prévoit de l'utiliser (surtout quand il s'agit d'un point)

    Un exemple mettant deux classes (ou plus) en évidences ( par exemple : Point3D et l'une de celles qui l'utilise, ou réservoir et voiture ) permettrait surement beaucoup mieux de se faire une idée de "à quoi peut bien servir cette classe"

    Peut etre tout le débat que l'on a eu ici n'est il simplement du au fait que l'exemple est soit mal choisi soit beaucoup trop simple pour arriver à inciter le lecteur à penser comme toi (je m'adresse en particulier à gbdivers là )

    [EDIT] PS :j'ai déjà souvent repris ici l'exemple du réservoir et de la voiture lorsque je tentais d'expliquer les méfaits des accesseurs et des mutateurs, peut etre pourrais tu t'inspirer de mes proses
    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. #44
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    @koala01
    Merci, je vais reprendre ton exemple

    Je ne trouvais pas que l'exemple choisi pouvais poser problème, mais vu que la plupart des personnes réagissent sur ce point, c'est qu'il est par conséquence mal choisi. A vouloir prendre un exemple trop simple, ça n'aide pas le discours

    Mon but était surtout de présenter une autre problématique (en complément de l'article d'Emmanuel Deloget) et proposer un exemple possible de solution. Solution que j'aime bien, cela permet de montrer des choses simples mais intéressantes sur les templates : que l'on peut distinguer ce qui peut être résolu à la compilation et ce qui peut l'être à l'exécution ; que l'on peut laisser le compilateur faire des choix à notre place, comme choisir la fonction correcte à appeler selon le contexte.

    Sinon, comme je l'ai déjà dit, je ne suis pas aussi radical que ce que laisse penser l'article. Ca doit être le "les accesseurs, c'est le mal" qui peut laisser penser ça (j'aime bien être polémique, les discussions sont plus intéressantes ). Je dois avouer que ça m'aggace un peu quand quelqu'un arrive avec cette problématique et qu'on lui répond d'ajouter des accesseurs, sans demander ses besoins, son design, etc. bref, sans connaître le contexte. C'est une mauvaise pratique à mon sens : le but n'est pas d'interdire les accesseurs (pas plus que d'interdire friend cité plus haut), mais que ça ne soit pas la solution par défaut sans réflexion préalable. Par exemple, pour un point, je n'ai rien contre les implémentations que l'on trouve dans Qt (QPoint en 2D, avec des x, y, setX, setY) ou mieux dans Boost.Geometry (qui utilise des fonctions libres get et set)

    @Ekleog, Emmanuel Deloget
    On est d'accord sur le fait qu'une fonction libre fait parti de l'interface (la discussion avait eu lieu je crois par rapport aux fonctions style begin et end pour les conteneurs de la stl)
    Mais je crois que séparer quand même la classe point, qui représente la sémantique d'un point, et les fonctions ou classes pour accéder aux détails internes (imposé par des problèmes d'implémentation) me semble plus propre (c'est que l'on trouve dans boost geometry)

    @pyros
    oui, tu as raison, il faudrait probablement faire un DP wrapper ici, pour localiser le code utilisant une lib C. Mais c'était pas le but du billet de proposer une interface utilisable en pratique d'une classe Point. Je crois que l'on est tous d'accord sur le fait que j'ai mal choisi mon exemple

    @Luc Hermitte
    Oui, c'est un abus de langage. On parlait de "POD" pour dire que tous les membres étaient publiques. Mais c'est bien un abus de la définition de "POD"

    @galerien69, Luc Hermitte
    Vous avez raison, c'est une source de problème dans l'exemple choisi, la dualité de la sémantique


    Bref, ça m'apprendra à choisir un problème trop simple

  5. #45
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Transfert d'une réponse posée dans les commentaires du billet

    Citation Envoyé par Kalite
    N'y a t'il pas une limitation a ce concept ?

    Prenons le cas suivant réel suivant,
    La classe A est un ensemble de paramètres de l'application.
    La classe B est une dialogue permettant l'édition des paramètres de A.

    Comment faire pour permettre l'édition de ces paramètres sans que le type de chaque paramètre soit connu par la classe B?

  6. #46
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Transfert d'une réponse posée dans les commentaires du billet

    Citation Envoyé par sevyc64
    Le concept a des limites, oui.

    Je en suis pas C++ien, mais Dotnetien, mais le principe s'applique à toute programmation objet.

    Le concept expose le principe (en résumé très rapide) de ne pas exposer les variables d'une classe permettant ainsi un éventuel traitement extérieur, mais au contraire d’intégrer dans la classe, les méthodes de traitements de ces variables, masquant, si possibles les dites variables.

    Hors il n'est pas toujours possible/judicieux de masquer les variables en questions. Il n'est pas toujours possible de définir exhaustivement tous les traitements qui pourraient être appliquer à ces variables afin d'en intégrer les méthodes correspondantes dans la classe.

    Le cas de la classe de configuration est un bon exemple. Cette classe gérant l'accès/sauvegarde de la configuration du logiciel, son but est donc de lire et d'écrire la configuration sur le support de sauvegarde (méthodes) mais aussi de mettre à disposition du reste du programme les paramètres ainsi lus (accesseurs).
    Prennent l'exemple d'une chaine de connexion à un SGBD. Ce paramètre n'a pas vocation à être utilisé directement (et uniquement) dans la classe de configuration. Et pourtant ce paramètre peut amener (sous Dotnet en tout cas) à changer de type.
    Cela voudrait dire que les méthodes utilisant cette chaine de connexion, c'est à dire des méthodes d'accès aux données, devraient être dans la classe configuration ? Personnellement, je pense qu'elles n'ont rien à y faire.


    Autre point :
    La modification du type d'un accesseur, plus généralement d'une surface d'exposition d'une classe (c'est valable aussi pour les types de retour des méthodes), constitue une cassure dans la compatibilité de la classe. Certes cela doit être éviter au maximum et représente bien souvent une mauvaise conception au départ.
    Mais lorsque cela est impossible à éviter, cela traduit une évolution majeure bien trop importante pour pouvoir assurer la compatibilité tant au niveau de la classe, qu'au niveau du code l'utilisant.
    Je en trouve pas choquant dans ce cas là, que tout le code utilisant cette classe doit être repris, ne serait-ce que pour contrôler d'éventuels effets de bord.


    Je suis d'accord que le concept exposé ici, est une "bonne pratique" que l'on devrait essayer d'appliquer le plus souvent possible, mais il ne faut pas non plus en faire sa quête du Graal, car il ne faut pas voir le voir comme un concept universel et polyvalent.

  7. #47
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    @sevyc64

    Ton "Autre point" me semblerait intéressant à développer. Tu pourrais détailler ton idée ?

  8. #48
    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
    Note qu'un titre du genre de "les accesseurs, c'est le mal" ne me dérangerait absolument pas, quitte à modérer un peu le discours dans l'article, étant entendu que l'idée est de "frapper les esprits".

    A l'extrême limite le point dans son acception courante (le fait que sa responsabilité est de représenter une coordonnée) pourrait être un parfait exemple d'utilisation raisonnée des accesseurs, s'il prenait en compte une classe utilisant les points mais... ne fournissant aucun accesseur dessus (car le point deviendrait alors "détail d'implémentation" de la classe en question).

    On insisterait alors sur le fait que get X / Y / Z correspond bel et bien aux services que l'on est en droit d'attendre de la part d'un point, mais on les mettrait en parallèle avec une classe (pourquoi pas Polygon ) qui n'expose absolument pas les points qu'elle utilise, mais dont l'utilisation prévue serait clairement expliquée dans l'article (pour, justement, placer le scope dans lequel elle est à considérer).

    L'exemple n'est pas forcément mal choisi... Il est peut etre simplement "trop simple" car ne permettant pas de fixer un scope d'utilisation
    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. #49
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Je serais beaucoup moins tolérant face à l'introduction d'une accesseur sur la quantité de carburant actuellement dans le réservoir, et je préférerais un comportement indiquant le "niveau de remplissage", sous la forme du quotient entre la capacité maximale et la quantité présente, nommé "niveauDeRemplissage" ou tout nom similaire, voir d'une fonction "estSurReserve" renvoyant vrai si la quantité est inférieure à une certaine valeur (mettons 5 litres, vu que c'est la quantité habituelle de la réserve).
    Très mauvais exemple. Si les véhicules actuels donnent le niveau de remplissage sous forme de jauge approximative, c'est par limitation technique. Je pense que tout le monde serait ravi de disposer du volume réel (avec en regard la capacité réelle). Tout comme tout un chacun préfère sur ses appareils nomades avoir une durée d'autonomie restante exacte, plutôt qu'une jauge à trois ou quatre segments.

    Si tu disposes du niveau de capacité réelle, le choix de donner à l'utilisateur cette information sous forme de ratio ou de capacité absolue concerne les exigences métiers (= les clients), et pas la conception du logiciel.

  10. #50
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    @sevyc64

    Ton "Autre point" me semblerait intéressant à développer. Tu pourrais détailler ton idée ?
    J'ai pas lu tous les commentaires précédents, mais je vais essayer de répondre sur ce point.

    Un des principes de la programmation objet est que chaque objet, dans la mesure du possible, doit pourvoir être vu comme totalement indépendant des autres objets qui vont consommer ses services. Cet objet, lorsqu'il évolue, se doit toujours dans la mesure du possible, de ne pas modifier ses interfaces existantes, que ce soit des propriétés, des méthodes, etc..., ce que j'appelle la surface d'exposition, ceci afin de rester compatible avec le code le consommant.

    Ce n'est rien d'autre, si j'ai bien compris, que le principe que tu émets, gbdivers. Hors ce principe n'est pas toujours applicable. Peu importe si la cause est une mauvaise conception ou une forte évolution, mais la modification des interfaces existantes génère une cassure dans la compatibilité.

    gbdivers, tu expose une solution efficace et non dénuée d’intérêt palliant ce problème, mais cela suppose de définir à l'avance ce que pourra être l'utilisation de la classe, actuelle et future. Nous somme d'accord, c'est une bonne pratique qui devrait être appliquée le plus souvent possible.
    Mais même dans ce cas, tu ne t'affranchis pas d'avoir à repasser le code consommant la classe lorsque tu change un type

    Prenons le cas d'une classe <<mal codée>>. Si tu change le type d'un accesseur, tu devras repasser tout le code appelant pour le modifier en fonction du nouveau type. Tu n'as pas le choix et si tu ne le fais pas, pour peu que tu ais choisi les bonnes options à la compilation, tu auras une erreur lors de celle-ci.

    Prenons maintenant le cas d'une classe bien construite. Rien de plus simple puisque tout est prévus dans la classe, il suffit de changer le code appelant, remplacer TaMethode(int) par TaMethode(double). Mais cela nécessite aussi de repasser tout le code appelant.
    Et c'est même plus pervers car, si tu oublie un changement, là ou tu devrais utiliser TaMethode(double), tu continue à appeler TaMethode(int), la compilation n'y verra probablement rien et ça te génèrera un bug dans du code plus en amont, bug qui sera bien plus difficile à identifier.

    Donc pour résumer, ce que je disais dans mon commentaire est que :
    - il faut éviter absolument, le plus possible, de modifier les interfaces des objets
    - lorsque cela n'est pas évitable, quelque soit la méthode utilisée (modification d'une interface, ou changement de la surcharge appelée d'une interface), il faut, de toute façon, repasser l'intégralité du code appelant pour vérifier que l'on ne peut pas avoir d'effet de bord source potentielle de bugs.


    Suis-je plus clair ? c'est pas certain !!!
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  11. #51
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Je reviens sur cette dualité de sémantique. J'ai réfléchie un peu plus à cette notion de point et je vais préciser ce que j'avais en tête (en essayant de ne pas m'enfoncer plus )

    J'étais parti sur la notion de point au sens géométrique du terme, c'est à dire "le plus petit élément constitutif de l'espace géométrique". De ce point de vue géométrique, la notion de point est indépendante du système de coordonnées et même de la dimensionnalité de l'espace (2D, 3D, R^n). En géométrie, on a des définitions d'objets (point, droite, plan, etc.) et des propriétés sur ces objets (un point est l'intersection de 2 droites non parallèles, etc.) On est dans un "domain specific langage".
    La classe que j'ai proposée se voulait être une implémentation de ce concept de point géométrique, destiné à un utilisateur de ce DSL (un matheux non informaticien)

    En plus de ce concept de point géométrique, on a le concept de point au sens de la géométrie analytique, c'est à dire la représentation en terme de coordonnées et de relations mathématiques.
    On a également le concept de point d'un point de vue informatique (plus précisément OpenGL ici), c'est à dire un tableau de nombres réels que l'on passe à une fonction glVertex et qui affiche sur un écran un point (pixel)

    Il est en général pas utile de distinguer ces notions en informatique pour faire de la 3D, mais pour mon explication, je voulais bien partir de la notion de point géométrique. Malheureusement, ma réflexion n'était pas assez poussée et j'ai mélangé également des notions de géométrie analytique (les coordonnées x, y, z) et d'informatique (les fonctions draw et glVertex). D'où la confusion dans l'article, qui finalement correspondait à la confusion dans mon esprit.

    Pour bien séparer ces notions, j'aurais du créer un "GeometricPoint" pour le matheux qui veut une implémentation d'un point identique à ce qu'il a l'habitude de manipuler ; les notions de "Espace", "Repere", "ReccupererCoordonéesPoint" (notions de géométrie analytique) ; la notion de "AffichePoint" (représentation sur un écran d'un point) pour l'informaticien 3D, etc.
    Par contre, il ne s'agit pas d'une approche destinée aux jeux ou à la 3D, mais une approche plus mathématique

    J'espère avoir été plus clair sur mes intentions initiales (et la source de ma confusion) et que je vais pas relancer plus de critiques

  12. #52
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Citation Envoyé par pyros Voir le message
    pour moi il s'agit plus d'un problème d'interfaçage de 2 API.
    +1

  13. #53
    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 oodini Voir le message
    Très mauvais exemple. Si les véhicules actuels donnent le niveau de remplissage sous forme de jauge approximative, c'est par limitation technique. Je pense que tout le monde serait ravi de disposer du volume réel (avec en regard la capacité réelle). Tout comme tout un chacun préfère sur ses appareils nomades avoir une durée d'autonomie restante exacte, plutôt qu'une jauge à trois ou quatre segments.

    Si tu disposes du niveau de capacité réelle, le choix de donner à l'utilisateur cette information sous forme de ratio ou de capacité absolue concerne les exigences métiers (= les clients), et pas la conception du logiciel.
    Je crois que tu laisses l'arbre cacher la foret, et tu abondes malgré tout sur ce que je dis en parlant d'une "utilisation raisonnée".

    Ce qu'il faut comprendre,l'un dans l'autre, c'est que l'utilisateur final de la voiture, il s'en foutra sans doute royalement de savoir s'il reste 10,5 litres ou 11,2 litres dans le réservoir...

    Ce qui l'intéressera par contre au plus haut point, c'est "combien de kilomètres puis-je faire avec ce qui reste d'essence avant de devoir passer à la pompe ou m'apprêter à pousser la voiture".

    Mais ce genre de réponse, c'est à la voiture à la donner (ou du moins à donner à l'utilisateur un moyen de l'évaluer).

    Alors, effectivement, peut etre que la voiture sera particulièrement intéressée, si elle dispose d'un moyen d'évaluer précisément la consommation, par le fait de connaitre "au centilitre près" la quantité d'essence qu'il reste dans le réservoir, afin, qui sait, de faire le calcul et de pouvoir dire à l'utilisateur "dans XXX kilomètres, vous devrez pousser la bagnole".

    Alors, en dehors de toute considération sur la faisabilité technique de la chose, il peut effectivement s'avérer opportun de considérer le fait que le réservoir doit pouvoir rendre le service de répondre à la question "de quelle quantité de carburant disposes tu".

    Quand je parle d'utilisation raisonnée des accesseurs, c'est exactement de cela que je parle : il s'agit d'exposer "au tout venant" ce qui peut réellement etre considéré comme un service rendu ou attendu de la part de l'utilisateur

    Par contre, l'utilisateur de la voiture n'a, a priori (tant qu'il n'est pas mécano et qu'il ne doit pas commander un autre réservoir, diront nous ) , absolument pas besoin d'avoir accès au réservoir.

    L'aperçu que l'utilisateur a du réservoir doit être "filtré" par la voiture, et j'ai presque envie de dire que si l'utilisateur veut croire que l'essence est simplement en suspension "quelque part dans la voiture" ou qu'elle coule directement dans les pneus (et meme si c'est effectivement le cas, d'ailleurs), hé bien, tant mieux (ou tant pis, selon le sens que l'on peut donner à ces mots ) pour lui

    Encore une fois, on en revient au fait que tout code (qu'il s'agisse d'une fonction, d'une classe ou d'une fonction membre de classe) ne vaut que par l'utilisation qui en est faite mais, avec la restriction importante du respect de demeter qui veut que, pour pouvoir utiliser la classe A tu n'a pas besoin de connaitre la classe B qui est utilisée par la classe A.

    Si, dans le code métier, il apparait que la voiture doit, d'une manière ou d'une autre, exposer la quantité d'essence restante, cela ne devra, en aucun cas, se faire en... renvoyant (une référence sur) le réservoir, mais bien en se basant sur les services par le réservoir pour donner l'aperçu de cette quantité sous la forme qui intéresse l'utilisateur
    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

  14. #54
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Transfère d'une réponse posée dans les commentaires du billet
    Transfert*

    Sinon, je n'ai plus rien à dire, il me semble qu'on est à peu près tous d'accord (et surtout sur la nullité de l'exemple )

Discussions similaires

  1. Réponses: 4
    Dernier message: 11/09/2006, 16h55
  2. Les polices dans les tables et les requêts
    Par zooffy dans le forum Access
    Réponses: 3
    Dernier message: 21/06/2006, 11h06
  3. Outils pour creer les accesseurs et les mutateurs
    Par MarieMtl dans le forum MFC
    Réponses: 3
    Dernier message: 03/10/2005, 17h03

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