22-03-2020, 04:08 PM
Citation :un contrôleur différent (ni Unity, ni City) qui appelerais directement les deux modèles depuis le contrôleur pour leur demander d'exécuter le traitement des données.Je ne suis pas sûr d'avoir saisis, alors je reformule (peut-être donc que je paraphrase): cela donnerait qqc du style [controlleur de la page] -> appelle -> ["sous"-controlleur qui gère la notion de sacrifice et qui a 2 modèles en dépendances (propriétés de classe)] -> appelle -> [modèle 1 pour ajouter des ressources puis modèle 2 pour virer les unités, puis d'autres modèles si besoin]
Citation : je trouve que l'on y perds en visibilité dans le code du moteur du jeu.Je ne suis pas d'accord car cela dépend juste de comment tu gères la déclaration de ta structure de DB. Dans mon cas, j'ai un dossier avec les tables (éventuellements, un sous-dossier pour une table donnée + ses triggers s'il y en a), un dossier de procédures stockées "génériques" (par exemple, si plusieurs pages ont besoin de sacrifices, je fais une procédure stockée que je mets là-dedans et que j'appelle en disant qui sacrifie quoi, et la procédure fait le traitement de sacrifice) et d'autres dossiers pour les autres types d'objets stockés (event, view et functions).
Il est en plus possible de créer un (ou plusieurs) fichiers SQL définissant chacun une procédure stockée "limitée" au dossier où le fichier se trouve (par exemple, on pourrait avoir un fichier __city_sacrifice.sql définissant une procédure stockée de gestion de sacrifices qui se trouverait dans /variisapce/endpoint/city/sacrifice/ et qui ne serait donc accessible que par /variisapce/endpoint/city/sacrifice/unit/ et /variisapce/endpoint/city/sacrifice/building/ si on peut sacrifier des batiments ou des unités)
Citation :il doit donc aller chercher dans les migrationsLe problème (de beaucoup de gens apparemment?!) quand je parle de faire des trucs via les objets stockés en DB, c'est qu'ils sont dans des optiques de migrations pure. Or, il ne faut pas. Quand tu utilises un SVN, ce n'est pas toi qui écris des diff, puis dis au SVN "allez, applique ça à mon code"! T'imagines le bordel... En pratique, tu écris le code réelle, et tu laisses le SVN se débrouiller comme un grand pour faire le diff. Dans le cas des bases de données, je conseille de faire de même (c'est ce que je fais).
La procédure que j'ai écrite précédemment, c'est ce qui se trouve dans mon fichier SQL. Bon, ok, y'a "DELIMITER $$ DROP PROCEDURE IF EXISTS game_action_city_sacrifice$$" avant et "DELIMITER ;" après (j'avais hésité à ne pas les mettre mais l'IDE se perd ensuite, vu qu'il n'a pas le bon delimiter, alors, j'ai laissé comme ça). Quand je veux changer la logique de cette action, je change le contenu de ce fichier.
L'outil de déploiment, lors d'une mise à jour du jeu, n'a alors plus qu'à bêtement exécuter tous les fichiers SQL pour mettre la DB à jour. En pratique, j'ai optimisé et sécurisé: l'outil de déploiment purge d'abord une DB de test en virant tout son contenu, puis il charge tous les SQL dans cette DB de test et si rien n'a planté [parce que ça m'est arrivé que l'IDE ne repère pas une erreur de syntaxe SQL par exemple] alors l'outil fait le *diff* entre cette DB de test et la DB réelle du jeu, et l'exécute.
Je procède de même pour les functions, les triggers, les view, les event (attention alors à bien définir une date explicite de début de l'event, sinon, l'outil met "NOW", donc la date de déploiment, et il trouve donc toujours un diff avec la DB du jeu oui, je me suis déjà fait avoir sur ce point!) et les tables. Pour ces dernières, le diff va consister à rajouter/retirer/modifier (les typages) des colonnes. Dans le cas d'une colonne qu'on devrait "drop", j'ai mis en place la règle "renomme d'abord la colonne, rends-la NULLable DEFAULT NULL, et tagge-la avec une date à partir de laquelle la colonne peut être réellement supprimée". Ca m'évite de supprimer des colonnes direct au déploiment, et de perdre des données. En cas de mise à jour foireuse, je peux donc revert mon code (merci Mercurial!) puis le redéployer: l'outil va alors voir le diff entre la DB du jeu et la DB "comme elle était avant", il va voir que des colonnes se nomment "x__old_datedesuppression" dans la DB du jeu alors qu'une colonne "x" existe dans le code. L'outil va alors dire "ok, cette colonne n'est plus dépréciée, je la renomme juste en 'x'" et je récupère les données du jeu
Donc au fond, c'est gérable, mais cela part d'un principe important: le jeu est "codé" en SQL. Dans cette optique, je n'ai donc *aucune* logique de jeu dans mon code PHP. PHP ne sert qu'au templating du jeu finalement, et à récupérer les paramètres d'entrée des pages (get/post/cookie). Bon, ok, j'en profite à ce moment-là pour faire une validation rapide (type "ce paramètre doit être un ID, donc, je vérifie que c'est un integer, strictement positif, et inférieur à 0x7fffffff" mais sans plus: si ces conditions sont respectées, pouf, c'est envoyé à la procédure stockée de la page, et à elle de tout gérer ensuite).
Les rares cas où j'ai besoin d'un lien PHP/SQL, par exemple, parce qu'une constante de jeu doit être appliquée dans la logique du jeu (SQL) et affichée au joueur pour qu'il comprenne ce qui se passe (PHP), alors le plus souvent, la constante se trouve dans la base de donnée (soit dans une vue, soit dans une table: ça dépend de la structure dont j'ai besoin) et est récupérée comme une donnée de page classique (si c'est récurrent entre les pages, aka si c'est une donnée qui est utilisée dans le template du jeu et non sur une page précise, alors le template du jeu fait appel à un genre de "fausse page web" [un endpoint qui n'est accessible que par PHP et non par une URL] qui fait appel à sa procédure stockée, laquelle récupère les infos, puis ce endpoint convertit ça en bean de données et le template du jeu le récupère et peut faire son formattage).
Une autre approche possible que j'ai en réserve consiste à créer une (ou plusieurs) classes de constantes PHP contenant les quelques valeurs utiles, et à les utiliser dans le code PHP, puis à faire un test unitaire (c'est à ça IMO que servent les tests: je m'en fous de figer les signatures de mes méthodes partout dans mon code, un test ne devrait servir qu'à combler les lacunes de l'IDE quand y'en a et à figer l'API publique du jeu) qui s'assure que les mêmes valeurs sont dans la DB (ou carrément, dans les fichiers SQL qui en ont besoin).
Woarf, je me suis étalé... probablement inutilement :p Je retourne à mon interface de création de vaisseaux!