Citation:
Envoyé par
Sytten
Wow 8O super trop top :aie:
Enfin ça répond à beaucoup de questions sans réponse.
Merci de ces explications très détaillées et du soin apporté à ta réponse, elle a vraiment été utile!
Apportée avec plaisir qui plus est :D
Citation:
- Voir tout comme étant un service est vraiment une base qu'il me manquait. Ça démontre clairement que les setter ne sont pas une bonne chose pour l'OO...
Certains (dont moi) estiment d'ailleurs (loi de déméter à l'appuis) que les setters sont purement et simplement aberrants ;)
Citation:
-Exactement mon problème! Même syntaxe à quelques lettres près^^ Juste ça vient de m'ouvrir les yeux sur cette loi:ave:
De rien, cela te permettra surement de rendre ton code beaucoup plus flexible et évolutif ;)
Citation:
- Pour le reste de l'exemple, j'avoue que je ne dispose pas encore de toutes les connaissances nécessaires pour le comprendre (notamment au niveau des template), mais je vais certainement le relire dans un avenir rapproché (puisque je dois assimilé ces connaissances avant mon prochain projet qui sera plus ambitieux...)
En fait, comme je te l'ai dit plus haut, les template permettent de s'intéresser uniquement à la manière dont les objets sont manipulés.
La syntaxe est souvent verbeuse (d'où l'utilisation des nombreux typedefs pour la rendre un peu plus facile :D), mais, autrement, tu dois juste te dire qu'un type générique doit "simplement" correspondre (du point de vue des services que l'on peut en attendre) à ce dont tu as besoin...
Pour le reste, l'utilisation est fort proche de celle que l'on fait en orienté objet (ou en impératif pour les fonctions libres ;))
Citation:
- La constance dans les règles de nommage est bien évidemment de rigueur, j'ai lu un article l'autre jour sur les règles des devs de google (
http://google-styleguide.googlecode....k/cppguide.xml). Ça peut être un début, surtout que je commence à avoir certaines règles moi-même. Il va juste être important, j'imagine, que je définisse des règles claires et précises avec ma team avant le début de notre projet...
Lorsqu'on travaille en équipe, il est d'autant plus important d'avoir des règles de codage acceptées et utilisées par tous ;)
Mais l'on peut assez facilement se contenter d'un "jeu de règles de base" que l'on agrandi au fur et à mesure ;)
Citation:
- Dans le cas des tests unitaires, il faut donc ajouter certaines lignes de code si je comprend bien le temps du test. Cela peut se faire un debug mode (afin de voir en direct la modification des données dans la fonction).
Oui, il s'agit de rajouter du code, mais non, cela ne doit pas être directement intégré dans le code de ton projet.
L'idée est beaucoup plus proche de celle qui consisterait à demander à un utilisateur imbécile, distrait et manquant de sommeil d'utiliser les comportements que tu as mis au point.
Tu ne vas pas t'intéresser à la manière dont le comportement arrive à un résultat, mais au résultat lui-même, et veiller à ce que le résultat corresponde bel et bien à ce qui est attendu de la part du comportement testé.
Généralement, on crée un (ou plusieurs) projet(s) de test en parallèle au projet proprement dit, pour éviter de devoir attendre pendant une demi heures que tous les tests soient passés avant de pouvoir tester "soi meme" le résultat, et l'on s'assure très régulièrement (et surtout après une modification / correction ou un ajout) que tous les tests continuent à se dérouler correctement.
Citation:
Question qui me vient comme ça: vaut-il la peine de prendre de le temps d'en faire un/plusieurs pour chaque nouvelle fonction? ou seulement les fonctions critiques (comprendre les plus importantes) méritent qu'on en fasse...
Toute nouvelle fonction mérite d'être testée, soit séparément (pour les plus complexe), soit en groupe (on utilisera par exemple régulièrement "l'accesseur" sur un donnée pour vérifier que le résultat d'un comportement donné correspond à ce qu'on attendait ;))
Citation:
- Si on n'utilise pas ce fameux modèle MVC, y a-t-il d'autres façon de coder correctement un jeu en respectant les principes? (Afin de ne pas se retrouver avec des gods objects notamment...)
A vrai dire, MVC rentre dans la catégorie de ce que l'on appelle les "patrons de conception" (desing patterns en anglais) tout comme le patron de conception "visiteur" ou "fabrique" ou n'importe quel autre patron décrit à l'origine par le Gof.
Il est tout à fait possible que le simple fait de respecter certains principe (le fameux SOLID et la loi de déméter en tête) fasse "naturellement" ressembler ton projet à quelque chose de fort proche du MVC.
La raison en est sommes toutes relativement simple : la plupart des patrons de conceptions ne sont que le résultat de la "normalisation" de pratiques que l'on rencontre naturellement dans différents projets ;)
Citation:
- Dans le cas d'un MVC, comment les classes PersonnageControler, PersonnageView et Personnage, par exemple, doivent-elle interagir entre elles? Un lien d'amitié serait-il approprié ou doit-on passer par des fonctions membres?
Il n'y a pas vraiment de "bonne" ni de "mauvaise" réponse à ce sujet.
La réponse la plus adaptée ressemble beaucoup plus à "ca dépend des services que l'utilisateur est en droit d'attendre de ces différentes classes".
Ainsi, si ton controleur (ou ta vue) doit faire appel à des services auxquels "n'importe qui" est susceptible de faire appel au niveau du modèle, la voie de la sagesse conseillerait d'utiliser les fonctions membres.
Par contre, si ton controleur (ou ta vue) doit manipuler des éléments internes à ton modèles pour lesquels il n'y a strictement aucune raison valable pour en donner l'accès à "n'importe qui", la même sagesse conseillerait de privilégier l'amitié au fait de donner accès à qu'elle que chose qui serait estampillé "touche pas à ca p'tit con" :D
Citation:
- Dans un cas concret de mon jeu, j'ai une fonction dig dans laquelle il y a une boucle le temps du creusage du bloc (notamment pour ne pas que le joueur fasse d'autres actions durant le creusage). Pourtant, je dois continuer à afficher mes éléments dans cette boucle. La solution que j'ai utilisé (et que je n'aime pas puisque qu'elle est mauvaise et peu flexible) consiste à passer en paramètres les objets que je dois afficher et ensuite les passer à mes fonctions libres qui s'occupent de les afficher. Comment faire pour éviter de devoir passer tous mes objets à afficher dans mes fonctions lorsqu'il y a une boucle? Une implémentation solide du MVC me permettrait-elle de résoudre mon problème? Si oui, comment faire changer ma vue si je change des données en utilisant mon controler (je suis encore dans cette boucle dont je ne peux sortir avant d'avoir fini de creuser)? Finalement, l'utilisation d'une boucle pour faire cela est-il approprié (tout simplement^^)?
Bon, la réponse à cette question risque d'être complexe, il va falloir t'accrocher :D
Du point de vue de la conception, le fait que ton personnage est occupé à creuser mérite amplement d'être représenté au niveau de la partie métier (du modèle), tout comme le fait qu'il est en train d'attendre, de dormir, de manger, de prendre une potion, d'attaquer, de courir ou que sais-je.
chaque "action" effectuée par ton personnage prend un "certain temps" et interdit (pour la plupart en tout cas) ton personnage de faire "autre chose" pendant qu'il est occupé à effectuer cette action.
Une fois qu'il a fini l'action à laquelle il est occupé, il sera en mesure d'attendre l'ordre suivant qui provoquera une nouvelle action, qui prendra aussi un certain temps et qui l'empêchera de faire quoi que ce soit d'autre jusque l'action ait été effectuée entièrement, et ainsi de suite, durant toute la durée du jeu (ou peu s'en faut).
Le fait qu'il soit occupé à attendre ou à effectuer "n'importe quelle action" sera utilisé aussi bien par le contrôleur que par la vue:
Par le contrôleur pour savoir si ton personnage peut recevoir "l'ordre suivant", par la vue pour, le cas échéant, faire en sorte d'afficher une animation qui "mime" l'action entreprise par ton personnage.
Le principe généralement utilisé est celui de la "machine à état": on définit une série d'états distincts ("en attente","courant", "frappant", "buvant","piochant","lançant un sort",...) qui correspond au fait que le personnage est occupé à effectuer l'action en question.
Une fois qu'il a fini l'action qu'il est occupé à effectuer, le personnage se remet dans un état "de base" (qui est, en l'occurrence, "en attente") et qui donne accès aux autres états.
Lorsque le contrôleur recevra l'ordre de faire effectuer une action particulière, il indiquera au modèle de de se placer dans l'état qui correspond à l'action et déclenchera un "compte à rebours" afin de pouvoir déterminer "à quel moment l'action prend fin".
Quand le contrôleur remarquera que le compte à rebours est terminé, il indiquera au modèle qu'il est temps de remettre le personnage à son état initial ("en attente").
Maintenant, ce n'est pas parce qu'un compte à rebours est en cours qu'il faut que le jeu se bloque et empêche le reste de fonctionner :aie:
La solution consiste généralement à travailler avec plusieurs threads, de manière à ce que l'exécution de l'affichage de la vue (par exemple) puisse continuer de manière indépendante de ce qui se passe du coté du controleur et de manière à ce que le controleur puisse (le cas échéant) recevoir d'autres ordres pour d'autres objets alors qu'il est déjà occupé à attendre la fin d'une action pour un objet spécifique.
Mais l'utilisation des threads mériterait à elle seul un roman, je vais donc la laisser "de coté" pour l'instant, histoire de te permettre d'assimiler tout ce que j'ai dit jusqu'à présent ;)
Enfin, je voudrais revenir sur un aspect qui est passé "au bleu" lors de mon intervention précédente, à savoir:
Citation:
Si on n'utilise pas ce fameux modèle MVC, y a-t-il d'autres façon de coder correctement un jeu en respectant les principes? (Afin de ne pas se retrouver avec des gods objects notamment...)
En fait, il faut savoir que la notion de "god object" est suffisamment vague pour permettre de décrire à peu près n'importe quelle situation :aie:
Une chose est certaine : il serait très mauvais que toutes tes classes du modèle, des controleurs et de la vue ne viennent à hériter (de manière directe ou indirecte) d'une classe Object :D
Cependant, il y a parfois des situations assez confuses:
Au niveau du modèle (de la partie métier), plus tu arriveras à garder des petites (surtout en terme de "profondeur") hiérarchies de classes, plus tu auras facile à faire évoluer ton projet et à le maintenir.
Au niveau du contrôleur, tu auras sans doute un nombre de hiérarchie similaire à celui que tu trouve dans ton modèle, mais il n'est pas "forcément exclu" que tu puisse te retrouver avec une classe proche de AbstractControler qui serait une base commune à toutes les hiérarchies de controleurs que ton projet utilise.
Enfin, au niveau de la vue, il semblerait assez légitimes que "tout ce qui peut être affiché" fasse partie d'une hiérarchie de classe dont la classe de base serait proche de "DrawableItem".
Tu auras sans doute quelques (hiérarchies de) classes "périphériques", mais tout, du grain d'herbe à ton personnage en passant par les armes, les différents objets, les oiseaux qui volent dans le ciel ou les murs devront vraisemblablement pouvoir être considérés comme ... des objets susceptibles d'être tracés
Ce sera très clairement le meilleur moyen de déterminer "quel que soit le type d'objet à tracer" les objets qu'il te faudra afficher à un instant T, et, surtout, d'être en mesure de les afficher ;)
Maintenant, peut on en arriver à parler de god object :question: Il serait peut etre intéressant de lancer un débat sur le sujet car je suis relativement mitigé à ce propos ;)