Citation:
Envoyé par
mazertys17
Etant donné que j'utilise l'Héritage, le pointeur devient nécessaire, non ?
Il y a des chances que le recours aux pointeurs et à l'allocation dynamique soit nécessaire, mais
Citation:
Donc le shared_ptr est justifié ?
Non, absolument pas...
L'utilisation des shared_ptr n'est justifiée que quand tu n'arrives pas à déterminer "qui est responsable de la durée de vie" de ton pointeur. Dans de très nombreuses circonstance, le fait que tu n'arrives pas à le déterminer tend au contraire à prouver qu'il est très certainement utile de revoir ta conception afin de donner cette responsabilité à une et une seule classe (et sans doute d'ailleurs à une classe qui n'existera que sous une forme d'instance strictement unique)
Toutes les autres classes qui font éventuellement référence (d'une manière ou d'une autre) à tes pointeurs peuvent alors être considérées comme "des utilisateurs tout ce qu'il y a de plus simple".
Si vous voulez m'aider, je vais vous montrer ici, grosso modo comment fonctionne mon programme, jusqu'à présent :
Citation:
une class Engine, va charger les objets nécessaires à la scène depuis une class Ressource, qui va les construire puis les cloner en shared_ptr ( en gardant un modèle sous la main si on lui redemandait l'objet). l'Engine les mets alors dans un container.
Déjà sur cette phrase, on se rend compte que le principe de la responsabilité unique (SRP) n'est pas respecté ... L'engine doit effectivement garder en mémoire les objets nécessaires à la scène, mais ce n'est absolument pas à lui de charger ces objets, ni même de les créer:
Le chargement des données modélisant les différents objets (fichier *obj, sans doute) devrait être délégué à une classe qui ne s'occuperait que de cela (ObjLoader, par exemple :question:) et il en irait de même pour la création des objets de la scène, qui devrait être prise en charge par une classe distincte (ObjectFactory, par exemple) qui maintiendrait le modèle de l'objet (ce qui a été chargé par ObjLoader) et qui pourrait l'utiliser pour créer un objet d'un type particulier, qu'elle renverrait sous la forme d'un pointeur (intelligent, de préférence) sur un objet "général" (sur ta classe de base, autrement dit ;) )
La question est : pourquoi un shared_ptr... De prime abord, le seul responsable de la durée de vie des objets créés est sans doute enginge (ou peut être une classe qui trainerait et qui s'occuperait du niveau ou du terrain de jeu ???). Toutes tes autres classes ne sont que des utilisateurs de tes pointeurs ;)
Citation:
Chaque objet à accès à une class System, qui va avoir pour rôle de gérer les collisions et l'affichage, et de partager certaines infos ( comme la vue du jeu, position de la souris sur le world etc...).
Encore une fois, il y a un gros problème de responsabilité, car, si je compte bien :
- gérer les collections
- gérer l'affichage
- partager certaines informations
Ca fait... trois responsabilités... Autrement dit, cela en fait deux de trop ;)
De plus, pourquoi chaque objet devrait il avoir accès à la classe System :question: A mon sens, ce serait plutôt le système (ou plutôt : différents types de systèmes, engine pouvant être considéré comme l'un deux avec la responsabilité particuière de devoir s'occuper de la durée de vie des pointeurs ;) ) qui devrait accéder aux différents objets, non l'inverse ;)
Citation:
les Objects sont "polymorphiques", mais ils contiennent tous les 4 même class : Graphics, Physics, State et Sound, sachant que le Physics a accès au Graphics ( avec un ptr ) et au State, et que le State à accès au Graphics.
Pourquoi doivent-ils se balader avec tout cela:question:
Si tu as Graphics, Physics, State et Sound, cela correspond à ... quatre modules qui devraient pouvoir travailler de manière indépendante : A l'extrème limite, tu devrait pouvoir développer l'intégralité du module "graphics" (ou n'importe quel autre) sans avoir besoin d'aucun des autres!!! Ce sont des choses réellement tout à fait séparées!
Il n'y a donc aucune raison pour exposer les besoin de ces quatre modules dans une sorte de "module central" quelconque. Tout ce qu'il faut, c'est la possibilité de "faire le lien" entre un fichier audio (par exemple) et le fichier qui l'utilise. Et plus la donnée sera simple, plus la recherche sera facile. Du coup, un size_t dont le numéro identifie de manière unique et non ambigue chaque fichier audio (chaque élément de physique, chaque partie devant être affichée) correspond à tout ce qu'il te faut au niveau de tes objets ;)
Citation:
ex :- le State perd de la vie, il l'indique au graphics qui change l'aspect de l'objet.
- le physics entre en collision avec un objet, il l'indique au State, qui change la vie, l'indiquant ainsi au graphics.
Surement pas : le sytème de physique (je n'aime pas ce terme, car trop générique, mais bon) se rend contre que deux objets entre en collision : il envoit un message "collision avec (l'autre objet) aux deux objets en présence.
Chacun de ces deux objets émet alors un signal "collision" qui sera récupéré par le système d'affichage, celui du son et celui d'état et chacun réagira à sa propre manière :
le système d'affichage en affichant une "explosion"
le système de son en faisant entre "boum"
le système d'état en influençant sur la vie des objet ayant émis le signal ;)
Ca ne te parrait pas plus "logique" :question:
Citation:
Chaque objet envoi donc automatiquement au System ses différentes infos, dans leur plus petit "état" possible, à savoir une Collision et une IE, par ex.
Tes objets doivent rester les plus simples possibles, surtout au niveau de la partie "business" (métier, si tu préfère): des données rudimentaires (des type primtifis de préférences, des structures simples si tu n'a pas le choix) et la possibilité d'émettre et de recevoir quelques signaux, et c'est tout
Citation:
Apparemment, cela ne semble pas respecter le "SRP" ( dont je n'ai pas encore tout compris ).
Ce n'est en effet clairement pas le cas ;)
SRP signifie Single Responsability Principle (ou, si tu préfères, principe de la responsabilité unique) Et il est finalement simple à comprendre : si tu veux pouvoir faire évoluer facilement ton projet, chaque classe, chaque fonction ne doit s'occuper que de faire une seule et unique chose. Cela t'apporte énormément d'avantages, parmi lesquels on peut citer:
- des petites fonctions, de petites classes de peu de lignes (instructions) ==> facile à lire et à comprendre
- des petits comportements tout simples que l'on peut utiliser ensemble dans de très nombreuses combinaisons ==> tu rajoute un "cas particulier sans aucun problème"
- Des petits comportements, ca fait peu de variable et c'est facile à tester ==> tu as beaucoup plus facile à "prouver" que ta fonction fait ce qu'elle est sensée faire ;)
- j'en passe et de meilleures...
Citation:
Mais en faisant ainsi, je pensais optimiser un peut les choses en faisant en sorte que les informations soient traités au plus bas niveau possible.
N'essaye pas d'optimiser maintenant... Donald Knuth disait
Citation:
Envoyé par Donald Knuth
premature optimization is the root of all evil
Cela pourrait se traduire par quelque chose comme "l'optimisation prématurée est le chemin vers l'enfer". Et il a raison. Commence par avoir un code facile à lire et à comprendre, même s'il ne fait pas forcément ce qu'on attend de lui.
Mais, comme il sera facile à lire et à comprendre, tu auras facile à le corriger pour qu'il réagisse exactement de la manière dont on est en droit de s'y attendre et donc d'atteindre la deuxième étape :
Commence par avoir un code qui fait exactement ce que tu attends de sa part, même s'il n'est pas forcément le plus efficace : un code qui fonctionne lentement est utilisable, même s'il met la patience de l'utilisateur à rude épreuve... Mais un code qui "plante rapidement" ne l'est pas du tout, et tend à énerver beaucoup plus l'utilisateur ;)
Une fois que tu as tout cela, tu peux passer à la troisième étape : avoir un code qui fait rapidement ce que l'on attend de lui...
La priorité consistera à déterminer "où ca coince", mais, pour cela, il faut que ca fonctionne ;) :
Une fois que tu sais où ca coince, il faut déterminer pourquoi:
- Selon l'utilisation qui est faite des données, certains types de collections s'avèrent beaucoup plus rapides que d'autres. Certains algorithmes tendent aussi parfois à relier Bruxelles à Paris en passant par Moscou, Vladivostock et Londres... Si on peut éviter ces détours, on ne s'en sent généralement que mieux ;)
- Parfois, un test qui évitera un traitement lourd fera gagner énormément de performances, surtout si ce test lourd est effectué souvent
Citation:
Est-ce cohérent selon vous ?
Heu, je crois que toute ma réponse te permet de répondre par toi meme à cette question non :question: