TourDeJeu, le réseau des jeux en ligne alternatifs : jeux web multijoueurs, jeux par forum. En savoir +

Flux RSS des discussions du forum : pour les joueurs, et pour les créateurs et MJ
  Reply to this topicStart new topicStart Poll

> P.o.o Constructeur / Constructeur Par Défaut
manakeo
Ecrit le : Samedi 18 Novembre 2006 à 17h03
Quote Post


Pro
*

Groupe : Membre
Messages : 119


Dans la lignée de Sybler, je suis face à une question qui me bloque.

Je vais prendre un exemple: une classe joueur.

On ne peut avoir q'un seul constructeur par classe. Mais il y a deux facons de créér un objet joueur d'ou le problème, enfin ce n'est pas un problème mais plus un choix difficile.

Les 2 méthodes:

- passer en parametre les valeur du joueur et donc créer une occurence via ses valeurs.
- Ne passer qu'une valeur: l'ID. Et dans le constructeur avoir une requete de chargement qui créer une occurence grace au valeur de la table retournée par la requete.

Oui mais pb, c'est que j'ais besoin des deux" types" de constructeurs.

Avantage de la méthode 2:
SI je créer une occurence d'un joueur via la méthode n°2, cela est plus simple si jamais je dois ajouter un attribut a la classe joueur, je modifie simplement le constructeur et voila.

Problème: Si je veux ajouter un joueur. Je ne peux pas créer une occurence joueur qui n'existe pas encore, et donc je ne peux pas accéder au méthode du style "verifier le nom", "verifier le mail" etc.
Avec la methode 2 je pourrais plus que je passe en parametre les valeur et donc créer mon occurence.

c'est un peu compliqué j'espere avoir été clair. Donc mon soucis est quel choix de constructeur? Comment régler les pb du a l'un ou a l'autre?


--------------------
MJ : Jeu par forum / pbem de Hard Science Fiction : Station Alpha

PMEmail PosterUsers Website
Top
Sybler
Ecrit le : Samedi 18 Novembre 2006 à 18h07
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


PHP n'est pas un language très typé, tu peux donc faire un constructeur comme celui-ci:


CODE

function __construct(&$db, $arr)
{
  if (!is_array($arr)){
     $query = "SELECT * FROM table WHERE id=$arr;";
     $result = $db->query($query);
     $arr = mysql_fetch_assoc($result);
  }

  $this->id = $arr['id'];
  $this->nom = $arr['nom'];

}


Mais le polymorphisme est effectivement quelque chose qu'il serait agréable d'avoir en PHP sauf que tant que les variables ne seront pas plus typée, ca sera difficile pour PHP de faire quelque chose de réellement bien.


--------------------
user posted image
PMEmail PosterUsers Website
Top
Ludvig
Ecrit le : Samedi 18 Novembre 2006 à 19h43
Quote Post


Pro
*

Groupe : Membre
Messages : 109


On peux pas faire du overloading juste en fonction du nombre des parametres
vue que php est pas typesafe ?

Comme ça :

CODE
class ABC
{

ABC($ID);   //<-constructeur 1 (1 parametre)
ABC($xpos,$ypos,$nom);//<-constructeur 2 (3 parametres)

};



?

(dsl pour le syntaxe)

/Ludvig


--------------------
user posted image
PMEmail Poster
Top
Sybler
Ecrit le : Samedi 18 Novembre 2006 à 20h09
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


La surdéfinition/surchage de fonction n'est pas permise en PHP malheureusement. (Corrigez-moi si jamais je me trompe: ca ferais mon plus grand bonheur)

Et la syntaxe de constructeur que tu utilise est celle de PHP4. En php5 c'est vraiment __construct() ... et non le meme nom que la classe (juste pour faire différent des autres languages.. erf)


--------------------
user posted image
PMEmail PosterUsers Website
Top
Beiji
Ecrit le : Samedi 18 Novembre 2006 à 22h52
Quote Post


Pro
*

Groupe : Inspecteur de l'annuaire
Messages : 91


La surdéfinition n'existe toujours pas.

N'est-il pas possible de mettre des valeurs par défaut dans le cas d'une création de joueurs ? Ce serait des valeurs mises à zéro.

Comme on l'a dit, PHP ne fait que son entrée dans l'OO donc il faudra encore attendre pour pouvoir faire correctement de l'OO.

Ceci dit, après des recherches, la méthode __call peut-être utilisé dans ce sens ...
PM
Top
pascaltje
Ecrit le : Dimanche 19 Novembre 2006 à 20h51
Quote Post


Ouf
*

Groupe : Membre
Messages : 242


QUOTE (Sybler @ 18 Nov 2006, 19:09 )
La surdéfinition/surchage de fonction n'est pas permise en PHP malheureusement. (Corrigez-moi si jamais je me trompe: ca ferais mon plus grand bonheur)

on peut la simuler en fonction du nombre d'arguments, via la fonction func_num_args :
http://fr.php.net/manual/fr/function.func-num-args.php

de mon coté j'utilise plutot des constructeurs du style:

CODE

function __construct( $id = 0, $arr = FALSE)
{
$this->id = $id;
if( $arr != FALSE && is_array($arr) )
  {
  // appel de la methode d initialisation à partir d un tableau
  }
}


hope it helps!

A+

Pascal


--------------------
PMEmail PosterUsers Website
Top
wells
Ecrit le : Lundi 20 Novembre 2006 à 11h20
Quote Post


Pro
*

Groupe : Membre
Messages : 143


Et dire qu'une simple fonction ferait l'affaire. Pourquoi mais mon Dieu, pourquoi vous vous acharnez a faire de l'objet la ou il n'y en a nullement besoin.

Ca me tue moi ça lol. smile.gif

Enfin cela dit, pour ton problème je penche plus pour un constructeur de type 1), suivit d'une fonction qui met a jour via la table.


--------------------
user posted image
PMEmail PosterUsers Website
Top
manakeo
Ecrit le : Lundi 20 Novembre 2006 à 13h53
Quote Post


Pro
*

Groupe : Membre
Messages : 119


QUOTE (wells @ 20 Nov 2006, 10:20 )
Et dire qu'une simple fonction ferait l'affaire. Pourquoi mais mon Dieu, pourquoi vous vous acharnez a faire de l'objet la ou il n'y en a nullement besoin.

Ca me tue moi ça lol. smile.gif

Enfin cela dit, pour ton problème je penche plus pour un constructeur de type 1), suivit d'une fonction qui met a jour via la table.

laugh.gif

On se rend compte pk quand on est dedans biggrin.gif
Merci pour vos conseil.
Au final j'ais opter pour un constructeur du type:

_construct($id,$tab){

if($id!=0)
{
je charge a partie de la BD le joueur par son id
}
else
{
j'instancie un nouveau joueur grace au tableau)
}
}


--------------------
MJ : Jeu par forum / pbem de Hard Science Fiction : Station Alpha

PMEmail PosterUsers Website
Top
Sybler
Ecrit le : Lundi 20 Novembre 2006 à 17h10
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


QUOTE (wells @ 20 Nov 2006, 10:20 )
Et dire qu'une simple fonction ferait l'affaire. Pourquoi mais mon Dieu, pourquoi vous vous acharnez a faire de l'objet la ou il n'y en a nullement besoin.

Ca me tue moi ça lol. smile.gif

Enfin cela dit, pour ton problème je penche plus pour un constructeur de type 1), suivit d'une fonction qui met a jour via la table.

... hum, je sais pas... peut-être parceque maintenant les actions prennent 80% moins de temps et de code.

Que tout est ordonné ( du genre: echo "Vous êtes actuellement dans le lieu: " . $perso->getLieu()->getNom(); )

Que j'ai une documentation généré automatiquement sur mon développement.

Que ca m'assure que mes programmeurs assistants utilise du code optimisé et qu'il ne modifie pas des données protégé.

ha oui ca me permet aussi de charger les informations sur demande seulement, mais de les garder stocker en mémoire et de ré-utiliser ces informations une seconde fois (ou plus) sans refaire de requête... et le tout géré de facon strictement transparente.


^^ Non pour vrai ca sert à rien la POO. C'est juste un truc pour rendre les Hello World plus compliqué.

Et si tout les languages sérieux (C++, C#, Java, etc) penchent pour ca, c'est juste pour être plus compliqué et se donner un air "cool" entre eux.


--------------------
user posted image
PMEmail PosterUsers Website
Top
wells
Ecrit le : Lundi 20 Novembre 2006 à 19h28
Quote Post


Pro
*

Groupe : Membre
Messages : 143


Et dire que tout ca EST FAISABLE AVEC DE SIMPLES FONCTIONS.

Je n'ai pas dit que ce mode de codage est sans intérêt, je dit juste que quand je fait un nom_joueur() bah moi aussi sa me retourne ce que je veux, que je peux le garder en mémoire, que c'est réutilisable sans toucher le coeur du codes et ainsi de suite.

Maintenant si vous êtes trop de mauvaise foi pour l'avouer sa ne regarde que vous.


--------------------
user posted image
PMEmail PosterUsers Website
Top
manakeo
Ecrit le : Lundi 20 Novembre 2006 à 20h05
Quote Post


Pro
*

Groupe : Membre
Messages : 119


Pour de petit projet oui totalement wells. Mais pas pour des projets plus imposant.


--------------------
MJ : Jeu par forum / pbem de Hard Science Fiction : Station Alpha

PMEmail PosterUsers Website
Top
Nambew
Ecrit le : Lundi 20 Novembre 2006 à 20h30
Quote Post


Kid
*

Groupe : Membre
Messages : 43


Je crois que le débat OOP vs Procédural n'a pas sa raison d'être dans le topic, ce n'est pas le thème et ça n'aidera en rien celui qui attend des réponses.

Pour ma part, si c'est possible je laisserais le contructeur vide ou avec un id optionnel. Si l'id est passé, tu passes par une méthode load( id ) pour charger le joueur et des getter/setter pour créer un joueur avec des données extérieurs. Ça évite de passer par une méthode avec beaucoup de paramètres ce qui rendrait le code moin clair.
PM
Top
Sybler
Ecrit le : Lundi 20 Novembre 2006 à 23h11
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


QUOTE (Zan @ 20 Nov 2006, 19:05 )
Pour de petit projet oui totalement wells. Mais pas pour des projets plus imposant.

Je sais que ca n'a pas beaucoup d'intérêt de faire ca, mais je ne peux pas m'en empecher:
+1


EDIT: (parceque juste +1 c'était trop gratuit )

Au fait, comment tu (wells) peux te permettre un tel jugement puisque tu n'a JAMAIS vu nos moteurs de jeu ? Es-tu dans le meme contexte de développement que nous ? (c'est à dire as tu une équipe de développeur ou tu est seul dans tes fonctions ? , à tu une documentation pour chacune de tes fonctions ? etc etc )

Ps.: Je viend d'aller voir TON moteur de jeu, et j'ai trouvé l'idée de demander aux joueurs de faire un résumé du background du jeu vraiment ... bonne ! hehe, good job ;p C'est pas breveté comme concept j'espère ... ? (Remarque moi ils se tappent un examen après l'inscription pour avoir accès à plus d'un seul secteur)


--------------------
user posted image
PMEmail PosterUsers Website
Top
wells
Ecrit le : Mardi 21 Novembre 2006 à 00h01
Quote Post


Pro
*

Groupe : Membre
Messages : 143


J'arrêterais la car effectivement ce n'est pas le sujet du post en question. Cependant pour coder depuis 7 ans en procédural en php, et faire de l'objet tout les jours en DotNet, je connais bien les deux options.

Je ne dit pas que l'objet n'a aucun intérêt. Je dit que parfois, dans certain cas de figure (comme la demande de ce post) une simple fonction fait souvent aussi bien sans avoir à ce prendre la tête sur des questions tel que posé ici.

Mais de reste je suis d'accord avec vous, l'objet a parfois un intérêt certain.

Mon moteur de jeu (environ 4 à 5 milles lignes) est 100% procédural, il tourne bien et j'attends qu'on me prouve, test à l'appuies, que le même moteur serait plus rapidement en objet.

Reste la question de la doc ,qui est il est vrai, est agréable de pouvoir générer automatiquement. Je travaille personnellement seul et je ne compte pas ouvrir mes sources donc le soucis est moindre, mais cela reste un +1 pour l'objet c'est certain.


--------------------
user posted image
PMEmail PosterUsers Website
Top
Sybler
Ecrit le : Mardi 21 Novembre 2006 à 05h50
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


"que le même moteur serait plus rapidement en objet."

.. non, mais par contre le projet aurrait peut-etre moins d'un million de ligne...



Sinon, je dérive le sujet (tout en gardant comme lien l'aspect "rapide" de la POO que wells à soulevé) vers une autre question Zan et moi sur MSN (enfait plus moi que lui je crois (Mais ca devrait intéresser tout le monde))



Est-ce qu'il vaux mieux garder un concept d'objet très théoriquement correct (aka ByTheBook) ou vaux t'il mieux sacrifier 2-3 principes parfois pour arriver à un résultat final plus optimisé dans certains cas précis.



Le cas de figure ici est:
- Une carte de banque donne accès à
- Un compte de banque qui lui fait partie
- D'une banque

Les relations:
- Une banque possède des comptes + Un compte est relié à une seule banque [ 1->N ]
- Les comptes possède des cartes + Une carte est relié à un seul compte [ 1->N ]





Voici une problèmatique (mais je ne veux pas une solution qui traite spécifiquement ce cas, le tout doit rester généralement ré-utilisable pour tous les autres cas impliquant Carte/Compte/Banque):

QUOTE

Mon joueur à 10 cartes bancaires.

Je veux afficher une tableau (une ligne par carte) avec comme colone:
- Le nom sur la carte (Ex.: Carte d'accès de Bob)
- Le nom du compte bancaire ( Compte bancaire de Maurice )
- Le nom de la banque ( Banque St-Rodrigue )

ici Maurice à donnée une carte d'accès à son compte à Bob, son bon ami d'affaire.

^^ oubliez pas que "Bob" à 10 cartes différentes, je n'ai donné qu'un exemple pour "imager un contexte".



Donc l'idée est d'arriver à gérer les données le plus optimalement possible.


Voici les quelques solutions présentée (Des mauvaises, mais parfois optimisés, aux techniquement superbes, mais souvent non-optimisés):

SOLUTION 1:
CODE

Créer un héritage non conforme à l'idéologie de l'Orienté Objet:

Class Carte extend Compte{}
Class Compte extend Banque{}
Class Banque{}


Avantage:
- Facilité d'instanciation: En chargeant une Carte, automatiquement les informations de Compte et Banque seront remplis correctement via l'appel des constructeurs parent.
- Possibilité d'effectuer une seule (1) requête SQL [ instancier dans une boucle while($arr=mysql_fetch_assoc()) et passer $arr aux constructeur ]

Inconvéniant:
- Le principe de l'héritage n'est pas applicable dans ce cas, puisqu'une carte n'est pas un compte et un compte pas une banque.
- Si 3 cartes proviennent de la même banque, la meme banque sera contenue 3 fois en mémoire.


SOLUTION 2:
CODE

Créer une seule classe Carte qui contiend toutes les propriétés du compte et de la banque.


Avantage:
- Facilité d'instanciation: En chargeant une Carte, automatiquement les informations de Compte et Banque seront remplis correctement via l'appel des constructeurs parent.
- Possibilité d'effectuer une seule (1) requête SQL [ instancier dans une boucle while($arr=mysql_fetch_assoc()) et passer $arr aux constructeur ]

Inconvéniant:
- Le principe de l'objet n'est pas respecté dans ce cas, puisqu'une carte n'est pas un compte et un compte pas une banque.. une carte ne devrais pas avoir les attributs de compte et de banque.
- Si 3 cartes proviennent de la même banque, la meme banque sera contenue 3 fois en mémoire.


SOLUTION 3:
CODE

Créer une classe GestionBanque et GestionCompte qui gèrais un tableau d'objet de type Banque et Compte. Créer une méthode getBanque($noBanque) et getCompte($noCompte) qui parcours le tableau pour retourner l'objet voulu. Si l'objet n'est pas chargé, le charger à ce moment, puis le retourner.


Avantage:
- Les données sont optimisés en mémoire: Aucun doublon.
- Les données relatives au compte et à la banque sont uniquement chargé si elle sont utilisés.

Inconvéniant:
- Plus de requêtes SQL (mais vu que se sont des requêtes plus légère, ca pourrait être un avantage aussi)
- Créer des classes de Gestion (donc des classes de plus = structure moins simple et non uniforme à l'ensemble du projet)
- Complique l'utilisation générale du code (Il faut passer par une classe de gestion pour accéder à l'objet de classe Banque ou Compte)



SOLUTION 4:
CODE

Créer une classe Banque qui contiend un tableau d'objet de type Compte.
Créer une classe Compte qui contiend un tableau d'objet de type Carte.
Créer une classe Carte.


Avantage:
- Respecte bien le concept de l'orienté objet

Inconvéniant:
- Instanciation TRÈS complexe: Je vois mal comment je vais arriver à créer tout ca de facon optimisée et correct considérant qu'au départ je n'ai qu'un seul ID de carte bancaire. (Il faut commencer la création par l'objet Banque normalement)


Vos commentaires / idées, etc...


--------------------
user posted image
PMEmail PosterUsers Website
Top
Haiken
Ecrit le : Mardi 21 Novembre 2006 à 17h23
Quote Post


Ouf
*

Groupe : Membre
Messages : 360


Solution 4 of course, sinon ce n'est pas la peine de faire de l'objet. Oui c'est complexe, c'est pour cela que les frameworks de persistence existent (ezpdo entre autres). Ceux qui sont intelligents permettent de configurer une recuperation des objets lies a celui que l'on veut recuperer (je recupere tous les comptes lies a la banque), ou de ne les recuperer que s'ils sont utilises (lazy fetching)


--------------------
PMEmail Poster
Top
Sybler
Ecrit le : Mardi 21 Novembre 2006 à 18h05
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


Sauf que: qui possède réellement la carte ?

L'inventaire du personnage.

Alors lorsque je génère l'inventaire, comment est-ce que je vais arriver à lui intégrer une carte ?

Il faut avoir une solution qui permette, sans dupliquer l'information en mémoire de pouvoir à la fois:

- Afficher le nom de la banque d'une carte contenue dans l'inventaire d'un personnage.
- Afficher la liste des cartes d'une banque ou d'un compte.



EDIT:
La seule facon que je vois serait une méthode GestionBanque, qui contiendrait des méthodes telles que:

CODE

class GestionBanque{
   private $arrBanque;
   public function getFromCarte($carteId, $what, $nonTrouve=false){
      foreach($this->arrBanque as $banque){
          foreach($banque->getArrCompte() as $compte)
              foreach($compte->getArrCarte() as $carte)
                  if( $carte->getId() == $carteId)
                      switch($what){
                           case 'carte':
                                return $carte;
                                break;
                           case 'compte':
                                return $compte;
                                break;
                           case 'banque':
                                return $banque;
                                break;
                       }

       //Non trouvé
       if (!$nonTrouve){
            $this->loadCarte($carteId);
            return $this->getFromCarte($carteId, $what, true);
       }else{
            return -1;
       }
   }
}


^^ Et je souligne qu'une classe gestionBanque serait à mon avis préférable car je ne vois pas ce qui pourrait "contenir" une banque (sauf un lieu, mais si je dois instancier un lieu (donc trouver QUEL lieu contiend à la banque) pour accéder à une carte contenue dans l'inventaire du personnage, au final je trouve ca ... peu agréable à utiliser comme système.


--------------------
user posted image
PMEmail PosterUsers Website
Top
Sinclair
Ecrit le : Jeudi 23 Novembre 2006 à 15h15
Quote Post


Pro
*

Groupe : Membre
Messages : 133


QUOTE (Sybler @ 20 Nov 2006, 16:10 )
ha oui ca me permet aussi de charger les informations sur demande seulement, mais de les garder stocker en mémoire et de ré-utiliser ces informations une seconde fois (ou plus) sans refaire de requête... et le tout géré de facon strictement transparente.

Heu ... j'ai bien compris les autres arguments, mais celui là je ne vois pas concrètement à quoi ça correspond coté poo.

Merci pour l'éclaircissement.


--------------------
Concepteur/Développeur de guildes.jpc.free.fr
PM
Top
Sybler
Ecrit le : Jeudi 23 Novembre 2006 à 17h56
Quote Post


Ouf
*

Groupe : Membre
Messages : 453


Bah c'est assez simple, regarde ce code (simplifié au maximum)

CODE

class Banque{
  private noBanque; //No de la banque
  private arrComptes; //Tableau des comptes de la banque


  function getCompte($noCompte){

     foreach ($arrCompte as $compte)
         if ($compte->getNoCompte() == $noCompte)
            return $compte;

     //Si le compte n'est pas trouvé, il n'y aurra aucun return
     //Charger le compte dans le tableau
     $nouvCompte = new Compte($noCompte);
     $arrCompte[count($arrCompte)] = $nouvCompte
     return $nouvCompte;
  }
}


^^ mais mon point est que pour les BANQUES, pour pouvoir implanter un tel système, je ne vois pas d'autre choix que de créer une classe gestionBanque.
J'espèrais voir une personne me pointer une autre alternative, mais comme la plupart semblent rester silentieux...


--------------------
user posted image
PMEmail PosterUsers Website
Top
« Sujets + anciens | Programmer | Sujets + récents »

Reply to this topicStart new topicStart Poll