JeuWeb - Crée ton jeu par navigateur
[POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB (/showthread.php?tid=3327)

Pages : 1 2 3


[POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - NicoMSEvent - 15-12-2010

Liste des posts similaires :
[POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB
[POO] Bonne pratique n°2: ... (à venir)

Suite a ce tread : Aide dans une requetes, et surtout d'une dérive sur l'augmentation du nombre de requetes SQL qu'entrainait le passage d'une programmation procédurale vers la POO, j'ai décidé de créer un nouveau thread sur les bonnes pratiques a adopter.

Donc ce tread ci concernera la réutilisation des objets.

Comme exemple, je vais en prendre un que je connais bien, c'est a dire mon jeu Wink

J'ai un plateau contenant des tuiles. Chaque tuile est d'un certain type (auberge, herbe, eau, foret, ...)
Je n'ai pas beaucoup de type de tuiles différentes, donc je charge tous les types en mémoire, dans un tableau que je vais appeler $type_de_tuile avec comme indice l'identifiant

Lorsque je place une tuile sur le plateau visible à l'écran (mon plateau en db fait +- 1 million de cases, et j'en affiche une vingtaine à l'écran),
-je crée une tuile d'un certain type, et là je passe en paramètre le type de tuile (objet) par référence, et non par copie (donc je n'ai en mémoire qu'un seul objet, et non des copies, ce qui permet un certain gain de mémoire).
De plus, comme mon objet "type de tuile" est déjà créé, j'économise la re-création de l'objet "type de tuile", et donc les doublons avec a nouveau des accès a la DB.

La question qui me vient à l'esprit : Aurais-je eu intéret à ne créer au vol que les type de tuile que j'utilise effectivement? (Singleton sur le type de tuile?)

Exemple d'appel (simplifié) :
ma_nouvelle_tuile=new tuile(&type_tuile,pos_x,pos_y);

De même, lorsque je place un personnage, je passe en paramètre la tuile sur laquelle il doit se placer (avec passage par référence), de manière a éviter les doublons si jamais il y a plusieurs personnages sur la même tuile.

Autre question ouverte : lorsque je fais un appel AJAX, et je sais d'avance que je ne vais me servir que d'un nombre limité d'objets : par exemple la tuile sur laquelle je suis actuellement
Et sur cette tuile, je ne vais me servir que de certaines information (personnages et quêtes liées qui y sont liés), il y aurait un moyen simple de savoir jusqu'a quel profondeur je vais chercher l'information?
Je n'ai pas besoin des quêtes des PNJ sur le plateau de jeu (mais je dois voir les PNJ), par contre j'ai besoin des quêtes dans mon cadre "action possibles". Voilà deux contextes différents dans lesquels j'ai besoin d'informations différentes pour des mêmes objets. Comment différencier ces cas? (constructeurs différents?)


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - niahoo - 15-12-2010

en php les objets sont toujours passés par référence, donc déjà tu peux t'économiser des signes '&' !

"""La question qui me vient à l'esprit : Aurais-je eu intéret à ne créer au vol que les type de tuile que j'utilise effectivement?"""

et bien si tu as 20 tuiles de type 'herbe' et que ce sont 20 objets identiques, hormis leurs coordonnées, ce serait plus simple de n'avoir qu'une instance pour chaque type.

Je dirais même plus, ce serait plus simple d'avoir des classes statiques pour chaque type et un simple tableau de tuiles avec 3 champs: type_id, x, y


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Jeckel - 15-12-2010

(15-12-2010, 02:23 PM)niahoo a écrit : en php les objets sont toujours passés par référence, donc déjà tu peux t'économiser des signes '&' !

Précision : en PHP5 les objets sont généralement passé par référence... en PHP4 par contre c'est toujours par copie...


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - NicoMSEvent - 15-12-2010

@niahoo:
(15-12-2010, 02:23 PM)niahoo a écrit : en php les objets sont toujours passés par référence, donc déjà tu peux t'économiser des signes '&' !
Je ne suis pas certain de ce que tu avances. J'avais fais des tests lorsque j'avais pondu ça, et il me semblait que lorsque je passais un objet sans &, il me faisait des copies. Maintenant, afin d'éviter d'entrer à chaque fois &, il est possible de le déclarer dans le prototype de la fonction.

$type_tuile[1]->var=1;
$tuile1=new tuile($type_tuile[1]);
$tuile2=new tuile(&$type_tuile[1]);
//GetVar retourne la valeur de l'objet $type_tuile[1]->var
echo $tuile1->GetVar(); // 1
echo $tuile2->GetVar(); // 1

$type_tuile[1]->var=2;
$tuile3=new tuile($type_tuile[1]);
$tuile4=new tuile(&$type_tuile[1]);

echo $tuile1->GetVar(); // 1
echo $tuile2->GetVar(); // 2 puisque référence
echo $tuile3->GetVar(); // 2
echo $tuile4->GetVar(); // 2 (tuile 2 et 4 pointent vers le même objet en mémoire)

(15-12-2010, 02:23 PM)niahoo a écrit : """La question qui me vient à l'esprit : Aurais-je eu intéret à ne créer au vol que les type de tuile que j'utilise effectivement?"""

et bien si tu as 20 tuiles de type 'herbe' et que ce sont 20 objets identiques, hormis leurs coordonnées, ce serait plus simple de n'avoir qu'une instance pour chaque type.

Je dirais même plus, ce serait plus simple d'avoir des classes statiques pour chaque type et un simple tableau de tuiles avec 3 champs: type_id, x, y

c'est justement ce que je fais. Mais à la place du "type_id", j'ai carrément une référence vers le type de tuile, de sorte que dans mon instance de tuile, lorsque je fais

echo $type_tuile;

ma tuile s'affiche bien (grace à la fonction __tosring() de l'objet "type de tuile" qui me retourne carrément le HTML que je souhaite afficher lorsque j'imprime ma tuile);

Les classes statiques avec les types de tuiles, je ne trouve pas que ce soit une bonne idée, je les préfère en DB étant donné que je pourrais en ajouter sans préavis (et puis, si je souhaite le mettre à jour "in-game", je ne voudrais remettre mes mains dans le code source)


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Hideaki - 15-12-2010

Pour ta première question :
Si tu souhaites juste typé ta tuile sans pour autant avoir un comportement particulier afin simplement d'avoir une liste de coordonnée :
Créer une liste de point pour chaque tuile exemple List tuiles1 = { Coord1, ..., CoordX}
cette méthode est uniquement si tu souhaites récupérer un type de tuile précis.
Après si tu souhaites un système plus évolué pour récupérer un ensemble de type de tuile ( il faut voir aussi comment tu les récupères en BD).
Il te faudrait 2 Objets différents :
Groupe_Tuile qui contiendra un type de tuile et une liste de coordonnée. exemple Groupe_Tuile gt = new(Type_tuile, liste_coordonnée)
Liste_Groupes_tuile qui contiendra une liste de groupe de tuile.
Par rapport à ta solution, l'avantage réside dans le nombre d'objet créer qui sera bien inférieur.

Concernant ta deuxième question, je n'ai pas trop saisie, qu'es ce cadre des actions possibles, elle est défini par ta tuile ou ses alentours ?


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Jeckel - 15-12-2010

En terme de performance, si ta collection de type de tuile ne dépasse pas la centaine d'élément, et que tes objets types de tuiles sont des objets simples et des feuilles (c'est à dire qu'ils ne contiennent pas d'autres objets) ta solution de tout chargé dans un tableau me semble bonne... une seule requête de chargement, et une variable un peu grosse mais encore tout à fait gérable pour du PHP.

Ce qui m'inquiète par contre, c'est qu'à te lire, (l'histoire du passage par référence) j'ai l'impression que tu es encore en PHP4... si c'est le cas, passe rapidement en PHP5, tu y gagneras beaucoup, surtout au niveau de la gestion de la mémoire pour les objets (le point fort de PHP5).

Bref, je ne pense pas que le problème se situe au niveau de ta gestion des "types de tuiles", mais peut-être plutôt au niveau de la gestion des cartes complètes...

Si je lit bien, tu reconstruis la carte (avec sa vingtaine de tuile) régulièrement... il faudrait, je pense, que tu trouve un moyen de dédoubler ta carte en deux parties, une partie qui ne bouge pas (les tuiles et leur types) et une partie qui bouge (les personnages et objets).
La partie fixe, une fois l'objet (et toute sa structure) construit il faudrait que tu le stocke dans un fichier de cache (un petit serialize par exemple pour aplatir l'objet)... aux appels suivants, tu recharges l'objet depuis le fichier (unserialize) et hop, tu retrouve ton objet et toutes ses tuiles...
Pour aller plus loin, en PHP5 tu as les méthodes __sleep() et __wakeup() qui sont appelée lors d'un serialize et d'un unserialize, très pratique pour n'enregistrer que les données "fixes".

Une autre chose, je suppose que tu utilises les mêmes objets lorsque tu travailles sur une tuile (administration) et sur une carte complète (collection de tuiles) ? Parfois, il peut être utile d'utiliser des objets différents, plus léger lorsqu'ils sont traité en masse, pour économiser des ressources.

Je donne un exemple que j'ai vu sur une application immobilière :
Dans la base de donnée, tu as des résidences, et pour chaque résidences plusieurs logements. L'objet résidence contient la liste des logements.
A l'affichage du détails d'une résidence, tu as la liste des logements affichés... logique... Code objet, lorsque tu charges un objet "résidence", celui-ci charge ensuite la collection "logements" liés à la résidence.
Dans le moteur de recherche, on peut rechercher par type de logement (une pièce, deux pièces) mais dans le résultat on ne voit que la résidence, et le nombre de logement (une liste). Coté objet, la recherche renvoyait une liste de résidence, puis à l'affichage, pour chaque résidence, ils chargent la liste des logements, pour en resortir ensuite le nombre...

Résultat des courses : 1 requête pour la recherche, puis 1 requête par résidence affichée (pour avoir le nombre de logement) c'est un cas typique de programmation objet.

La solution : faire un objet spécifique pour le résultat de cette recherche, plus simple, et une requête SQL plus élaborée qui retourne en même temps, le nombre de logement... une seule requête, et un objet plus simple qui ne contient que les données affichées dans la liste.

Voilà, j'espère avoir été clair...
(15-12-2010, 02:39 PM)Hideaki a écrit : List tuiles1 = { Coord1, ..., CoordX}
Groupe_Tuile gt = new(Type_tuile, liste_coordonnée)

Hmm... je ne sais pas de quel langage il s'agit, mais je crois que Nico est en PHP (4 à mon avis) et ce que tu donnes... ce n'est pas du PHP il me semble...


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Hideaki - 15-12-2010

En effet ce n'est pas du php cependant, c'est un concept de manière que quelque soit ton langage on puisse le comprendre Wink

D'ailleurs je profite pour corriger un peu :

List tuiles = { Coord1, ..., CoordX}
Groupe_Tuile gt = new(Type_tuile, tuiles)


Re: POO.. - niahoo - 15-12-2010

Que je mette un '&' dans l'en-tête de ma fonction set_obj, un passage par référence explicite donc, ou que je ne le fasse pas, j'obtiens le même résultat:

<?php
class tt {
public $v;
public $tt;
public function __construct($v=0) {
$this->v = $v;
}
public function set_obj(tt $obj) {
$this->tt = $obj;
}
public function show() {
echo 'val:',$this->tt->v,"\n";
}
public function pp() {
$this->v++;
}
}

$a = new tt;
$a->pp();
echo $a->v, "\n";
$b = new tt(5);
$b->set_obj($a);
$a->pp();
$b->show();
$a->pp();
$b->show();
$a->pp();
$b->show();

Donc, peut-être est-ce que tu déclenche des copies dans ton constructeur ou ailleurs ?


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - Jeckel - 15-12-2010

(15-12-2010, 02:53 PM)Hideaki a écrit : En effet ce n'est pas du php cependant, c'est un concept de manière que quelque soit ton langage on puisse le comprendre Wink

D'ailleurs je profite pour corriger un peu :

List tuiles = { Coord1, ..., CoordX}
Groupe_Tuile gt = new(Type_tuile, tuiles)

Ah ok, donc j'vais reprendre en détails...

(15-12-2010, 02:39 PM)Hideaki a écrit : Pour ta première question :
Si tu souhaites juste typé ta tuile sans pour autant avoir un comportement particulier afin simplement d'avoir une liste de coordonnée :
Créer une liste de point pour chaque tuile exemple List tuiles1 = { Coord1, ..., CoordX}
cette méthode est uniquement si tu souhaites récupérer un type de tuile précis.

En gros, c'est à dire que dans le type de tuile, tu stocke la liste des endroits où elle apparait? c'est bien ça?

Si oui, c'est intéressant en effet, mais par contre, ça ne facilite pas la génération de la carte, pour trouver les tuiles contiguë par exemple, ça me semble plus complexe, non ?

(15-12-2010, 02:39 PM)Hideaki a écrit : Après si tu souhaites un système plus évolué pour récupérer un ensemble de type de tuile ( il faut voir aussi comment tu les récupères en BD).
Il te faudrait 2 Objets différents :
Groupe_Tuile qui contiendra un type de tuile et une liste de coordonnée. exemple Groupe_Tuile gt = new(Type_tuile, liste_coordonnée)
Liste_Groupes_tuile qui contiendra une liste de groupe de tuile.
Par rapport à ta solution, l'avantage réside dans le nombre d'objet créer qui sera bien inférieur.

Ok, ceci te constitue donc ta map d'une manière plus "light", j'ai bon? mais on revient toujours au problème du parcours qui me semble plus complexe, non ?
(15-12-2010, 03:00 PM)niahoo a écrit : Que je mette un '&' dans l'en-tête de ma fonction set_obj, un passage par référence explicite donc, ou que je ne le fasse pas, j'obtiens le même résultat:

Comme dis plus haut, c'est la différence entre PHP4 et PHP5... il semble maintenant évident que Nico est en PHP4... d'où la nécessité du passage par référence, sinon, en PHP4 c'est uniquement des copies...


RE: [POO] Bonne pratique n°1: réutilisation des objets et limitation des requêtes en DB - NicoMSEvent - 15-12-2010