Passer en poo ?

Passer en poo ? - PHP - Programmation

Marsh Posté le 18-08-2008 à 00:48:47    

Bonjour,  
 
Je travaille sur un petit jeu de foot en php/mysql. Je me débrouille en PHP mais je ne suis jamais passé à la programmation orientée objet, et je me dis que c’est peut-être l’occasion.  
 
Imaginons donc une rencontre entre 2 équipes. Je pensais faire :
 
- Une classe « equipe » avec des statistiques propres à l’équipe que je ne détaillerai pas ici pour être plus clair. J’ai donc 2 instances, une pour chaque équipe : $equipe[0] et $equipe[1].
 
- Une classe « joueur » avec les statistiques personnelles des joueurs : vitesse, fatigue, précision etc… ainsi que son poste sur le terrain (défenseur=0, attaquant=1…), son statut (en jeu=0, expulsé=1) et une référence à son équipe (0 ou 1). Pour les instances, il y en a autant que de joueurs : $joueur[0]… $joueur[21].
 
Jusque là, ça me paraissait cohérent. Mais à l’utilisation, j’ai un peu de mal sur 2 points :
 
- J’aimerais avoir un tableau contenant les clés de tous les joueurs (hors expulsés), trié par un attribut personnel, disons ici la fatigue : ($joueur[]->fatigue).  
 
- J’aimerais également connaître le défenseur (hors expulsé) le moins fatigué d’une équipe.
 
Ce genre de chose est fait vraiment très régulièrement dans le match, et avec différentes variables, j’aimerais donc trouver quelque chose de rapide et réutilisable efficacement.
 
J’avais réussi à faire tout ça sans programmer en objet, mais je voulais quelque chose de plus clair. Et là, mon code commence à devenir du n’importe quoi, je copie des tableaux dans tous les sens pour les trier, et je me demande si je n’ai pas fait fausse route dès le début avec ces classes. Qu’en pensez-vous ?
 
Merci.

Reply

Marsh Posté le 18-08-2008 à 00:48:47   

Reply

Marsh Posté le 18-08-2008 à 06:49:37    

Pour la liste des joueurs expulses, pourquoi ne pas creer une methode
$equipe->getExpelledPlayers(); ( avec pourquoi pas en parametre le champ selon lequel on trie le tableau ).
 
J'imagine que ta classe Equipe contient un tableau de Joueurs. Dans ce cas la methode est extremement simple, elle itere sur le tableau et si le joueur est expulse, l'ajoute au tableau du resultat.
 
Bon j'ai fait ca vite fait ya surement des erreurs mais c pour te donner l'idee.
 
Dans ta classe Equipe :

Code :
  1. public function getExpelledPlayers()
  2. {
  3. $expelledPlayers = array();
  4. foreach( $this->equipe->getPlayers() as $player )
  5. {
  6.  if ( $player->isExpelled() )
  7.   $expelledPlayers[] = $player;
  8. }
  9. return $expelledPlayers;
  10. }
  11. public function getLessTiredPlayer()
  12. {
  13. $resultPlayer = '';
  14. $minimumFatigue = 100 ; // J'ai mis ca au pif, a toi de mettre la valeur max de fatigue d'un joueur
  15. foreach( $this->equipe->getPlayers() as $player )
  16. {
  17.  if ( $player->isDefensor() && $player->getFatigue() < $minimumFatigue )
  18.  {
  19.   $result = $player;
  20.   $minimum = $player->getFatigue();
  21.  }
  22. }
  23. return $resultPlayer;
  24. }


Message édité par budlite le 18-08-2008 à 06:50:25

---------------
Fresh
Reply

Marsh Posté le 18-08-2008 à 12:55:30    

Si je comprends bien, tu verrais un truc comme ça  ?
 

Code :
  1. class Equipe{
  2. var $side;
  3. var $joueurs = array();
  4. function Equipe($side){
  5.   $this->side = $side;
  6. }
  7. function addPlayer($ligne){     // $ligne est issu d'une requête MySQL
  8.   $this->joueurs[] = new Joueur($ligne, $this->side);
  9. }
  10. function getPlayers(){
  11.   return $this->joueurs;
  12. }
  13. public function getLessTiredPlayer() {
  14.   $resultPlayer = '';
  15.   $minimumFatigue = 100 ; // J'ai mis ca au pif, a toi de mettre la valeur max de fatigue d'un joueur
  16.   foreach( $this->getPlayers() as $keyPlayer => $objPlayer ) {
  17.    if ($objPlayer->isDefensor() &&  $objPlayer->getFatigue() < $minimumFatigue )  {
  18.     $resultPlayer = $keyPlayer;
  19.     $minimumFatigue = $objPlayer->getFatigue();
  20.    }
  21.   }
  22.   return $resultPlayer;
  23.   }
  24. }
  25. class Joueur{
  26. var $fatigue;
  27. var $poste;
  28. var $status;
  29. var $equipe;
  30. function Joueur($ligne, $equipe){ 
  31.   $this->fatigue = $ligne->fatigue;
  32.   $this->poste =  $ligne->status;
  33.   $this->status = 0; 
  34.   $this->equipe = $equipe;
  35. }
  36. function addFatigue($howmuch){
  37.   $this->fatigue += $howmuch;
  38. }
  39. function getFatigue(){
  40.   return $this->fatigue;
  41. }
  42. function isDefensor(){
  43.   return ($this->poste == 0) ? true : false;
  44. }


Reply

Marsh Posté le 18-08-2008 à 17:11:17    

Moi je te conseil de passer en francais completement ou en anglais completement dans la nomination de tes méthodes / attributs, parce que les getFatigue et isDefensor ça irrite je trouve...

Reply

Marsh Posté le 18-08-2008 à 20:41:59    

yellu a écrit :

Moi je te conseil de passer en francais completement ou en anglais completement dans la nomination de tes méthodes / attributs, parce que les getFatigue et isDefensor ça irrite je trouve...


 
c'est une question d'habitude :o
 
sérieusement, le problème c'est que let préfixes set et get sont des normes.

Reply

Marsh Posté le 19-08-2008 à 01:11:57    

Je note, mais j'avoue que pour le moment, cela m'importe peu. Budlite m'a proposé des fonctions (merci d'ailleurs), je cherche seulement à savoir si la structure, dans mon cas de figure, est correcte. Qu'en pensez-vous ? (notamment d'instancier la classe joueur dans la classe equipe, car je ne suis pas sûr que Budlite voulait dire ça).  

Reply

Marsh Posté le 19-08-2008 à 04:26:41    

philipMo a écrit :

Si je comprends bien, tu verrais un truc comme ça  ?
 

Code :
  1. class Equipe{
  2. var $side;
  3. var $joueurs = array();
  4. function Equipe($side){
  5.   $this->side = $side;
  6. }
  7. function addPlayer($ligne){     // $ligne est issu d'une requête MySQL
  8.   $this->joueurs[] = new Joueur($ligne, $this->side);
  9. }
  10. function getPlayers(){
  11.   return $this->joueurs;
  12. }
  13. public function getLessTiredPlayer() {
  14.   $resultPlayer = '';
  15.   $minimumFatigue = 100 ; // J'ai mis ca au pif, a toi de mettre la valeur max de fatigue d'un joueur
  16.   foreach( $this->getPlayers() as $keyPlayer => $objPlayer ) {
  17.    if ($objPlayer->isDefensor() &&  $objPlayer->getFatigue() < $minimumFatigue )  {
  18.     $resultPlayer = $keyPlayer;
  19.     $minimumFatigue = $objPlayer->getFatigue();
  20.    }
  21.   }
  22.   return $resultPlayer;
  23.   }
  24. }
  25. class Joueur{
  26. var $fatigue;
  27. var $poste;
  28. var $status;
  29. var $equipe;
  30. function Joueur($ligne, $equipe){ 
  31.   $this->fatigue = $ligne->fatigue;
  32.   $this->poste =  $ligne->status;
  33.   $this->status = 0; 
  34.   $this->equipe = $equipe;
  35. }
  36. function addFatigue($howmuch){
  37.   $this->fatigue += $howmuch;
  38. }
  39. function getFatigue(){
  40.   return $this->fatigue;
  41. }
  42. function isDefensor(){
  43.   return ($this->poste == 0) ? true : false;
  44. }




 
Ouais en gros je vois ca comme ca.
Une equipe est composee de plusieurs joueurs, donc un attribut de Equipe doit etre un tableau de Joueurs.
 
Et sinon toute petite correction

Code :
  1. function isDefensor(){
  2.    return ($this->poste == 0) ;
  3. }


est suffisant :D  ;)  


---------------
Fresh
Reply

Marsh Posté le 19-08-2008 à 07:58:23    

Salut,
 
Moi en général, dans une fonction comme addFatigue, je colle un return $this->fatigue à la fin.
Même si on peut dire que c'est pas vraiment sémantique et tout et tout, je vois que c'est une pratique courante dans certains langages comme Ruby (et il me semblerait que Python fasse pareil) et je dit que c'est vachement pratique :o


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 19-08-2008 à 09:34:11    

esox_ch a écrit :

Salut,
 
Moi en général, dans une fonction comme addFatigue, je colle un return $this->fatigue à la fin.
Même si on peut dire que c'est pas vraiment sémantique et tout et tout, je vois que c'est une pratique courante dans certains langages comme Ruby (et il me semblerait que Python fasse pareil) et je dit que c'est vachement pratique :o


Ben en ruby c'est pas une "pratique" ( au sens ou c'est toi le developpeur qui le met), c'est juste le language qui le fait automatiquement pour toi. :o


---------------
Fresh
Reply

Marsh Posté le 19-08-2008 à 09:41:03    

esox_ch a écrit :

Salut,
 
Moi en général, dans une fonction comme addFatigue, je colle un return $this->fatigue à la fin.
Même si on peut dire que c'est pas vraiment sémantique et tout et tout, je vois que c'est une pratique courante dans certains langages comme Ruby (et il me semblerait que Python fasse pareil) et je dit que c'est vachement pratique :o


Dans le addFatigue j'aurais plutôt tendance à renvoyer this perso, ça serait largement plus pratique :o


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 19-08-2008 à 09:41:03   

Reply

Marsh Posté le 19-08-2008 à 11:36:11    

masklinn a écrit :


Dans le addFatigue j'aurais plutôt tendance à renvoyer this perso, ça serait largement plus pratique :o


Pour pouvoir enchainer les commandes ?
genre

Code :
  1. $player->addFatigue(20)->addMachin(30)->addTruc(40) ;


Je ne vois que cet interet, y en a t il d'autre ?


---------------
Fresh
Reply

Marsh Posté le 19-08-2008 à 11:38:46    

budlite a écrit :


Pour pouvoir enchainer les commandes ?
genre

Code :
  1. $player->addFatigue(20)->addMachin(30)->addTruc(40) ;


Je ne vois que cet interet, y en a t il d'autre ?


Yen a pas d'autre, mais c'est super pratique. Alors que renvoyer la valeur, franchement... [:petrus75]

Message cité 1 fois
Message édité par masklinn le 19-08-2008 à 11:39:45

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 19-08-2008 à 15:37:37    

masklinn a écrit :


Yen a pas d'autre, mais c'est super pratique. Alors que renvoyer la valeur, franchement... [:petrus75]


Je pense pareil :jap:


---------------
Fresh
Reply

Marsh Posté le 19-08-2008 à 20:30:15    

budlite a écrit :


Ben en ruby c'est pas une "pratique" ( au sens ou c'est toi le developpeur qui le met), c'est juste le language qui le fait automatiquement pour toi. :o

 

C'est bien ce que j'entendais.. Si j'avais voulu dire que c'était une pratique que les dev ont, ça pourrait être pareil dans tous les langages..

 

Concernant le fait de retourner $this ou la valeur ... C'est un choix :

 
Code :
  1. irb(main):001:0> class Player
  2. irb(main):002:1> def initialize
  3. irb(main):003:2> @fatigue = 0
  4. irb(main):004:2> end
  5. irb(main):005:1> def add_fatigue fatigue
  6. irb(main):006:2> @fatigue += fatigue
  7. irb(main):007:2> end
  8. irb(main):008:1> end
  9. => nil
  10. irb(main):009:0> player=Player.new
  11. => #<Player:0xb7d44344 @fatigue=0>
  12. irb(main):010:0> player.add_fatigue 10
  13. => 10

Message cité 1 fois
Message édité par esox_ch le 19-08-2008 à 20:35:08

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 19-08-2008 à 20:39:58    

esox_ch a écrit :

C'est un choix


En l'occurence dans ton exemple c'est pas un choix du tout, juste le comportement par défaut du langage qui est de retourner le résultat de la dernière expression évaluée.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 19-08-2008 à 20:49:19    

T1 mais je dois mal m'exprimer (ou alors vous comprenez tout de travers).
Je voulais dire que c'est le choix de Ruby de retourner la dernière expression, et non pas $this comme tu l'aurais fait. Il me semble d'ailleurs que Python ait fait le même choix non?
 
De plus c'est un choix que je trouve assez judicieux, parce que comme ça, si tu veux savoir combien de fatigue a un joueur après lui avoir ajouter X, tu peux le faire en 1 coup..


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 19-08-2008 à 21:01:40    

esox_ch a écrit :

Je voulais dire que c'est le choix de Ruby de retourner la dernière expression, et non pas $this comme tu l'aurais fait.


Renvoyer this/self est un choix qui ne peut être fait qu'au cas par cas, dans la mesure où ça n'a pas de sens en dehors des méthodes.

esox_ch a écrit :

Il me semble d'ailleurs que Python ait fait le même choix non?


Non, Python demande un retour explicite, sinon il renvoie None (/null/nil/whatever).

esox_ch a écrit :

De plus c'est un choix que je trouve assez judicieux, parce que comme ça, si tu veux savoir combien de fatigue a un joueur après lui avoir ajouter X, tu peux le faire en 1 coup..


Franchement, perso j'aurais collé un attr_accessor :fatigue et baste.

Message cité 1 fois
Message édité par masklinn le 19-08-2008 à 21:02:09

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 19-08-2008 à 21:56:44    

budlite a écrit :


 
Ouais en gros je vois ca comme ca.
Une equipe est composee de plusieurs joueurs, donc un attribut de Equipe doit etre un tableau de Joueurs.
 
Et sinon toute petite correction

Code :
  1. function isDefensor(){
  2.    return ($this->poste == 0) ;
  3. }


est suffisant :D  ;)  


 

Code :
  1. function isDefensor() {
  2.  return $this->poste;
  3. }


 
est suffisant :D  ;)


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 19-08-2008 à 23:40:07    

masklinn a écrit :


Franchement, perso j'aurais collé un attr_accessor :fatigue et baste.

 

Certes, mais si tu sais que tu vas souvent devoir ajouter de la fatigue à un joueur (par exemple s'il subit un tacle), et que donc tu vas le changer s'il a plus que X de fatigue, ça peut être pratique de faire un :

 
Code :
  1. unless( player.add_fatigue(10) < MAX_FATIGUE )
  2. change_player(player, fresh_players.pop)


Alors que sinon ça aurait demandé une ligne de plus (d'abord faire le add_fatigue, puis appeler l'accessor) ... Mais bon au fond les deux ont du sens ...
et pis ça aide pas des masses l'auteur du topic de savoir si Ruby et Python font ça ou pas (à part p-e de se rendre compte qu'au lieu d'écrire son site en PHP (en tentant de l'écrire OO) il aurait pu choisir un langage qui est OO de base)

Message cité 1 fois
Message édité par esox_ch le 19-08-2008 à 23:40:36

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 20-08-2008 à 08:02:59    

esox_ch a écrit :

Alors que sinon ça aurait demandé une ligne de plus (d'abord faire le add_fatigue, puis appeler l'accessor) ...


Non mais avec un attr_accessor le add_fatigue dégage hein, il sert plus à rien [:dawa]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 20-08-2008 à 08:06:38    

Faut voir dans le contexte de l'appli ..
Par exemple si la fatigue ne peut jamais diminuer (à part être remise à 0 entre 2 match), je trouve que ça a pas beaucoup de sens de faire un attr_accessor.
Je ferais un add_fatigue + attr_reader :fatigue


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 20-08-2008 à 08:32:18    

esox_ch a écrit :

Faut voir dans le contexte de l'appli ..
Par exemple si la fatigue ne peut jamais diminuer (à part être remise à 0 entre 2 match)


Dans ce cas tu crées une property avec une vraie méthode en writer [:spamafote]
 
Non parce que ton add_fatigue, si tu lui passes un nombre négatif sans checker il va diminuer la fatigue hein [:dawa]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 20-08-2008 à 14:30:45    

Mouais bof je suis pas convaincu .. Mais de toutes façons on s'en fout :D  
 

Code :
  1. def add_fatigue fatigue
  2. @fatigue += fatigue unless fatigue < 0 # Voilà :)
  3. end


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 20-08-2008 à 14:49:16    

esox_ch a écrit :

Mouais bof je suis pas convaincu ..


Pas convaincu de quoi exactement [:pingouino dei]

Code :
  1. attr_reader :fatigue
  2. def fatigue= fatigue
  3.    @fatigue = fatigue unless fatigue < @fatigue
  4. end


[:spamafote]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 20-08-2008 à 15:08:28    

Pas convaincu que ce soit beaucoup mieux. Me semble que les 2 approches sont valables


Message édité par esox_ch le 20-08-2008 à 15:09:05

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 20-08-2008 à 18:18:20    

Merci pour vos réponses. Mais pour ce qui concerne le ruby, j'avoue que cela ne m'intéresse pas.  
Par contre, avec ce modèle, je reviens à la question initiale. J'aimerais obtenir régulièrement un tableau de tous les joueurs (des deux équipes donc), avec en clé l'id du joueur (référence à l'objet joueur en fait) et en valeur un critère défini trié (fatigue par exemple, mais il y en a beaucoup d'autres). Est-ce que cette structure est vraiment adaptée ? Parce que dans le cas présent, si je ne me trompe pas je dois reformer un tableau à partir des deux tableaux ($equipe[0]->joueurs[] et $equipe[1]->joueurs[]). Y a-t-il plus simple ? Merci à vous.


Message édité par philipMo le 20-08-2008 à 18:19:18
Reply

Marsh Posté le 20-08-2008 à 18:49:53    

Bah tu peux créer un tableau joueurs à partir des 2 autres ayant comme index l'ID du l'utilisateur et comme valeur la valeur en question, après tu fais un sort et c'est bon.. Sinon si tu as déjà à portée de main un array contenant tous les ID des joueurs, tu peux faire une requête SQL sur ces ID avec un ORDER BY fatigue


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed