Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 08/05/2015, à 15:40

Destroyers

[C++] Loi de Déméter

Bonjours à tous. Une fois de plus, je suis face à une incompréhension face à mon langage de programmation préféré.
Il y a une règle que je ne vois pas comment appliquer: la Loi de Déméter.

celle ci stipule:

Loi de Déméter a écrit :

De manière générale, la Loi de Demeter interdit la composition de fonctions de type accesseur (elle définit une fonction accesseur comme étant une fonction qui retourne un objet qui existant avant l'appel de cette fonction).
source

Mais Alors ...
Imaginons une classe Personnage ayant un attribut Arme. la classe Arme possède un attribut std::string name.
Imaginons maintenant une classe gui qui affiche mon jeu.
Le problème: comment afficher le nom de l'Arme ? gui a besoin de récupérer l'Arme de mon personnage, mais je ne peux pas créer d'accesseur getArme() dans mon Personnage (selon ce que je viens de citer).
Je ne peux pas non plus créer getArmeName() non seulement par ce que c'est encore un accesseur mais en plus par ce que Personnage utiliserait un attribut de Arme (ce que la loi de Déméter interdit aussi).
Comment afficher le nom de l'Arme via ma classe gui ? Comment le récupérer ?

Ce problème est également ennuyeux si mon Personnage a un attribut Sprite. Impossible d'appeler Personnage.getSprite() pour utiliser Sprite.setPosition() ou Sprite.draw(), alors de quelle manière dessiner mon sprite ?

Encore une fois:
j'ai une classe SoundCache et une SoundPlayer, ainsi je respecte la loi de responsabilité unique. Mais alors comment récupérer les sons stockés dans Soundcache vers SoundPlayer (pas d'accesseur) et comment lancer Sound.Play() ?

Peut être est-ce la conception même de mes classes qui n'est pas bonne ? Aidez moi :3

J'ai une autre question à ce sujet:
Si Personnage a un attribut int vie, vu que ce n'est pas un objet, la loi de déméter m'autorise-t-elle à créer un accesseur getVie() ?

Merci à tous smile

Dernière modification par Destroyers (Le 08/05/2015, à 15:53)

Hors ligne

#2 Le 08/05/2015, à 21:12

alius

Re : [C++] Loi de Déméter

Les objets doivent être indépendant et doivent faire les choses par eux même.

En gros dans ton cas ça veut dire par exemple qu'il ne doit pas y avoir de méthode getArme() qui permet a ton objet gui d'aller chercher le nom de l'arme. En revanche ton objet arme doit implémenter une interface dans le genre affichable qui déclare une méthode afficheNomArme() et qui a pour principe d'afficher le nom de l'arme dans le gui.

Edit :
De plus ce n'est pas un problème de langage mais de design et d'analyse.

Dernière modification par alius (Le 08/05/2015, à 21:14)


Alius

Hors ligne

#3 Le 09/05/2015, à 09:47

grim7reaper

Re : [C++] Loi de Déméter

Destroyers a écrit :

Imaginons une classe Personnage ayant un attribut Arme. la classe Arme possède un attribut std::string name.
Imaginons maintenant une classe gui qui affiche mon jeu.
Le problème: comment afficher le nom de l'Arme ? gui a besoin de récupérer l'Arme de mon personnage, mais je ne peux pas créer d'accesseur getArme() dans mon Personnage (selon ce que je viens de citer).
Je ne peux pas non plus créer getArmeName() non seulement par ce que c'est encore un accesseur mais en plus par ce que Personnage utiliserait un attribut de Arme (ce que la loi de Déméter interdit aussi).
Comment afficher le nom de l'Arme via ma classe gui ? Comment le récupérer ?

Je pense qu’il y a deux solutions ici :
- soit la classe GUI n’a pas besoin de connaître la classe Arme, dans ce cas la classe Personnage pourrait fournir ce qu’il faut via une méthode getDescription par exemple (qui renverrait une description du personnage, de son arme, son équipement…)
- soit la classe GUI a besoin de connaître la classe Arme et dans ce cas pourrait intéragir directement avec, sans passer par Personnage.

Destroyers a écrit :

Ce problème est également ennuyeux si mon Personnage a un attribut Sprite. Impossible d'appeler Personnage.getSprite() pour utiliser Sprite.setPosition() ou Sprite.draw(), alors de quelle manière dessiner mon sprite ?
Peut être est-ce la conception même de mes classes qui n'est pas bonne ? Aidez moi :3

La classe Personnage pourrait avoir une méthode move et draw, non ?
Ainsi, l’utilisation d’un sprite serait transparente (après tout, c’est un détail interne).

Destroyers a écrit :

J'ai une autre question à ce sujet:
Si Personnage a un attribut int vie, vu que ce n'est pas un objet, la loi de déméter m'autorise-t-elle à créer un accesseur getVie() ?

Déjà, d’une manière général tu n’as pas besoin de fournir automatiquement des accesseurs (et encore moins des setters) pour chaque attributs (on voit souvent ça en Java malheureusement), sinon il n’y a aucune encapsulation au final…
Si tout ce que tu as besoin de savoir par rapport à la vie c’est si le perso est mort, tu peux avoir une méthode isAlive par exemple.

Enfin, dernier conseil : n’hésites pas à aller sur forum C++ de developpez.com car ils ont des gens qui s’y connaissent très bien en C++ et POO.

Hors ligne

#4 Le 10/05/2015, à 20:42

Destroyers

Re : [C++] Loi de Déméter

alius a écrit :

ton objet arme doit implémenter une interface dans le genre affichable qui déclare une méthode afficheNomArme() et qui a pour principe d'afficher le nom de l'arme dans le gui.

grim7reaper a écrit :

La classe Personnage pourrait avoir une méthode move et draw, non ?

Ce que vous dites est intéressant, mais dans ce cas mes classes ne respectent plus la loi de responsabilité unique, ce qui poserait des problèmes de d'entretien du code.

grim7reaper a écrit :

Déjà, d’une manière général tu n’as pas besoin de fournir automatiquement des accesseurs (et encore moins des setters) pour chaque attributs (on voit souvent ça en Java malheureusement), sinon il n’y a aucune encapsulation au final…

Ne t'en fais pas je ne fais pas un accesseur par attribut. wink
Je demande juste si d'une manière générale cette loi nous autorise à faire des accesseurs sur des types de base. j'ai donné ici l'exemple de la vie mais il peut en être de même pour le mana, la vitesse de déplacement, ou même le nombre d'instances de son contenues dans un soundCache.

grim7reaper a écrit :

- soit la classe GUI n’a pas besoin de connaître la classe Arme, dans ce cas la classe Personnage pourrait fournir ce qu’il faut via une méthode getDescription par exemple (qui renverrait une description du personnage, de son arme, son équipement…)

Passer par une classe pour accéder à une autre est justement ce que je cherche a éviter pour respecter la loi de Déméter.

grim7reaper a écrit :

- soit la classe GUI a besoin de connaître la classe Arme et dans ce cas pourrait intéragir directement avec, sans passer par Personnage.

C'est exactement ce que je cherche à faire big_smile
Mais c'est là que je ne sais pas comment faire... puisque mon Arme est dans mon Personnage hmm
C'est là que je demande de l'aide ^^

merci pour vos réponses.

Dernière modification par Destroyers (Le 10/05/2015, à 20:43)

Hors ligne

#5 Le 11/05/2015, à 12:52

Compte anonymisé

Re : [C++] Loi de Déméter

Destroyers a écrit :

Passer par une classe pour accéder à une autre est justement ce que je cherche a éviter pour respecter la loi de Déméter.

grim7reaper a écrit :

- soit la classe GUI a besoin de connaître la classe Arme et dans ce cas pourrait intéragir directement avec, sans passer par Personnage.

C'est exactement ce que je cherche à faire big_smile
Mais c'est là que je ne sais pas comment faire... puisque mon Arme est dans mon Personnage hmm
C'est là que je demande de l'aide ^^

merci pour vos réponses.

Je ne sais pas si ça respecte la Loi de Démeter, mais tu peux toujours passer par les classes amies

Cdlt wink

#6 Le 12/05/2015, à 05:27

grim7reaper

Re : [C++] Loi de Déméter

Destroyers a écrit :
alius a écrit :

ton objet arme doit implémenter une interface dans le genre affichable qui déclare une méthode afficheNomArme() et qui a pour principe d'afficher le nom de l'arme dans le gui.

grim7reaper a écrit :

La classe Personnage pourrait avoir une méthode move et draw, non ?

Ce que vous dites est intéressant, mais dans ce cas mes classes ne respectent plus la loi de responsabilité unique, ce qui poserait des problèmes de d'entretien du code.

Exact, mauvaise solution.

Destroyers a écrit :
grim7reaper a écrit :

Déjà, d’une manière général tu n’as pas besoin de fournir automatiquement des accesseurs (et encore moins des setters) pour chaque attributs (on voit souvent ça en Java malheureusement), sinon il n’y a aucune encapsulation au final…

Ne t'en fais pas je ne fais pas un accesseur par attribut. wink

C’est bien alors, car c’est une mauvaise pratique assez courante malheureusement.

Destroyers a écrit :

Je demande juste si d'une manière générale cette loi nous autorise à faire des accesseurs sur des types de base. j'ai donné ici l'exemple de la vie mais il peut en être de même pour le mana, la vitesse de déplacement, ou même le nombre d'instances de son contenues dans un soundCache.

La loi de Demeter n’interdit pas de fournir des accesseurs, mais elle interdit de les chaîner.

Destroyers a écrit :
grim7reaper a écrit :

- soit la classe GUI n’a pas besoin de connaître la classe Arme, dans ce cas la classe Personnage pourrait fournir ce qu’il faut via une méthode getDescription par exemple (qui renverrait une description du personnage, de son arme, son équipement…)

Passer par une classe pour accéder à une autre est justement ce que je cherche a éviter pour respecter la loi de Déméter.

Non, le fait qu’une méthode de la classe Personnage fasse appel à une méthode de la classe Arme est OK, car la loi t’autorise à appeler les méthodes de tes variables membres.
Donc tu peux tout à fait avoir une méthode Personnage.getDescription() qui va appeler les méthodes de Arme.

Destroyers a écrit :
grim7reaper a écrit :

- soit la classe GUI a besoin de connaître la classe Arme et dans ce cas pourrait intéragir directement avec, sans passer par Personnage.

C'est exactement ce que je cherche à faire big_smile
Mais c'est là que je ne sais pas comment faire... puisque mon Arme est dans mon Personnage hmm
C'est là que je demande de l'aide ^^

Je pense que si ta classe GUI a une méthode void display(const Arme& weapon) et que tu l’appelles via

GUI.display(perso.getArme())

Ça devrait être OK, car dans la méthode display tu pourras accéder aux méthodes et attributs de la classe Arme (car c’est un objet passé en paramètre)
De plus, maintenant, si un jour l’Arme n’est plus dans la class Personnage, ça n’impactera pas le code de la classe GUI (il faudra seulement changer l’appel), donc tu évites le couplage.

Hors ligne