Précédent   Forum des professionnels en informatique > PHP > Langage > Syntaxe
Syntaxe Forum d'entraide sur la syntaxe de PHP et la POO. Avant de poster -> FAQ syntaxe, Cours d'initiation et cours de POO
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/10/2007, 18h03   #1
Membre régulier
 
Inscription : mai 2007
Messages : 144
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 144
Points : 78
Points : 78
Par défaut [POO] et accesseurs

Bonjour à tous,

Je développe actuellement une application web, en utilisant la POO de PHP.

Seulement voilà, certaines de mes pages étaient relativement longues à générer, et je me suis posé la question de savoir pourquoi.

En fait, j'ai écrit mes classes avec des accesseurs (getters/setters) pour accéder aux attributs (déclarés comme privés) de mes objets... Très pratique et assure une certaine cohérence de l'ensemble... Seulement voilà, j'ai remarqué qu'en terme de performance, ce n’était pas terrible...

En effet, en accédant directement à mes attributs (déclarés donc comme public et sans passer par des accesseurs), les performances de mon application étaient grandement améliorées !

Bref... Sans doute que je m'y prends mal dans ma façon de programmer... Quand est-ce qu'il est selon vous nécessaire de déclarer un attribut comme publique, privé, d'ajouter des accesseurs, etc. ?

Merci beaucoup pour vos conseils !
Evocatii
Evocatii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/10/2007, 22h02   #2
Membre chevronné
 
David DRAPEAU
Consultant OpenERP
Inscription : juin 2003
Messages : 807
Détails du profil
Informations personnelles :
Nom : David DRAPEAU

Informations professionnelles :
Activité : Consultant OpenERP

Informations forums :
Inscription : juin 2003
Messages : 807
Points : 728
Points : 728
Envoyer un message via MSN à zyongh Envoyer un message via Skype™ à zyongh
Par défaut à suivre avec attention

Voilà un post qui j'espère va générer beaucoup de messages et que je vais suivre avec attention.

J'ai une façon très "cartésienne" d'utiliser les types d'accès. Si un paramètre (ou une méthode) ne doit être accessible ni par une classe qui en hérite ni par un script qui appelle la classe, j'utilise private. Etc. Par contre j'utilise protected vraiment si le paramètre (ou la méthode) doit absolument être hérité par une autre classe et public si la fonction est destinée à être utilisée dans un script. Sinon c'est protected le cas échéant et private si possible.

De mon côté même dans des classes conséquentes (plusieurs dizaines de méthodes) ou des projet d'une certaines envergure (plusieurs dizaines de milliers de lignes de code) programmés en POO, je n'ai remarqué aucun ralentissement entre des variables (méthodes) private et ces mêmes variables passées en proctected ou en public.

Pourrais-tu poster ton code (ou une partie) afin qu'on analyse ce que tu as fait?
__________________
Expertise OpenERP - programmation PHP/MySQL
toujours à l'écoute du marché
zyongh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/10/2007, 23h54   #3
Invité de passage
 
Inscription : décembre 2006
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 4
Points : 4
Points : 4
Ayant l'habitude de prog en POO je n'ai jamais eu de problème de ralentissement dûe aux accesseur mais il est vrai que ceux si posent problème lorsqu'ils sont trop nombreux...

Je programme à peu prêt comme david, même s'il est vrai que j'ai une tendance aigu vers le private...

As-tu essayer d'utiliser les méthode magique __set et __get pour voir si cela accélérer ou non ? Cela serait déjà une première chose à tester il me semble
mentiss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 11h06   #4
Membre régulier
 
Inscription : mai 2007
Messages : 144
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 144
Points : 78
Points : 78
Bonjour à tous,

Merci pour vos réponses.

Pour vous montrer le code qui pose problème, je vous fais un exemple.

Cette boucle était appelée un certains nombres de fois et j'ai constaté un ralentissement (j'entends par rapport aux autres pages de mon site qui se chargeaient nettement plus rapidement) :

Code :
1
2
3
4
5
6
7
if ($object->getX()->getId() == 'A' || $object->getY()->getId() == 'B') {
  $this->attribut = 'VALUEXXX';
} else if ($object->getX()->getId() == 'C' || $object->getY()->getId() == 'D') {
  $this->attribut = 'VALUEYYY';
} else if () {
  // Etc.
}
(Ma page se chargeait sur environ 0.3 secondes.)

Je l'ai donc remplacée par :

Code :
1
2
3
4
5
6
7
if ($object->x->id == 'A' || $object->y->id == 'B') {
  $this->attribut = 'VALUEXXX';
} else if ($object->x->id == 'C' || $object->y->id == 'D') {
  $this->attribut = 'VALUEYYY';
} else if () {
  // Etc.
}
(Ma page se chargeait sur environ 0.08 secondes.)

Mon script gagnait donc en rapidité si je n'utilisais pas les accesseurs ! Plus j'augmente le nombre de fois que cette boucle est appelée, plus la différence est significative entre les deux codes.

Sinon, mentiss, non je n'ai pas essayé avec les __set et __get.

Enfin, j'ai appris à programmer en Java (façon Java Beans), et donc j'ai toujours utilisé des accesseurs. Mais je me demande finalement si j'ai vraiment compris le concept des accesseurs, car en y réfléchissant, je ne vois pas non plus l'intérêt de déclarer du "private" partout.

Alors si quelqu'un qui a compris la théorie pourrait ré-expliquer le concept, ça serait vraiment sympa.

P.S : Deux articles intéressants sur le sujet (en anglais) :

http://www.darronschall.com/weblog/archives/000149.cfm
http://www.javaworld.com/javaworld/j...5-toolbox.html
Evocatii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 12h09   #5
Membre éclairé
 
Avatar de Linio
 
Inscription : octobre 2005
Messages : 427
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 427
Points : 304
Points : 304
Difficile de juger sur des temps aussi petits.

Faudrait faire boucler beaucoup tes instructions et voir les différences effectives.

Moi personnellement sur mon appli PHP je me pose beaucoup la question de l'optimisation, mais je dois avouer que j'ai jamais eu dans l'idée de faire des variables publiques partout et d'y accéder à droite à gauche, vu qu'on est plusieurs sur le projet.

De plus si vraiment y'avait des lacunes de perf, je pense que ça se saurait non?

A l'intérieur de l'objet en revanche effectivement je fais un $this->blabla plutôt que le getter (mais bon ça c'est logique).

Pour en revenir aux accesseurs, en théorie ils sont tous publics. Des méthodes privées/publiques/protégées sont très utiles dans le cadre d'un projet collaboratif et permet de limiter le champ d'actions des autres développeurs, typiquement, bon ça c'est privé, je peux pas y toucher, donc je fais avec une autre jolie méthode déjà implémentée.
__________________
Linio
Linio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 12h42   #6
Membre chevronné
 
David DRAPEAU
Consultant OpenERP
Inscription : juin 2003
Messages : 807
Détails du profil
Informations personnelles :
Nom : David DRAPEAU

Informations professionnelles :
Activité : Consultant OpenERP

Informations forums :
Inscription : juin 2003
Messages : 807
Points : 728
Points : 728
Envoyer un message via MSN à zyongh Envoyer un message via Skype™ à zyongh
Par défaut voici la raison

Citation:
Envoyé par Evocatii Voir le message
Sinon, mentiss, non je n'ai pas essayé avec les __set et __get.
La lenteur doit sûrement venir du fait que tu utilises des getters/setters programmés en PHP alors que les méthode magiques PHP __get() et __set() sont programmés en C car intégrés au moteur PHP, donc aucun problème de ralentissement.
__________________
Expertise OpenERP - programmation PHP/MySQL
toujours à l'écoute du marché
zyongh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 13h36   #7
Membre éclairé
 
Avatar de Linio
 
Inscription : octobre 2005
Messages : 427
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 427
Points : 304
Points : 304
C'est bizarre quand même.

Vous êtes sûr que c'est effectivement plus rapide, y'a un article là dessus?
__________________
Linio
Linio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 13h41   #8
Membre chevronné
 
David DRAPEAU
Consultant OpenERP
Inscription : juin 2003
Messages : 807
Détails du profil
Informations personnelles :
Nom : David DRAPEAU

Informations professionnelles :
Activité : Consultant OpenERP

Informations forums :
Inscription : juin 2003
Messages : 807
Points : 728
Points : 728
Envoyer un message via MSN à zyongh Envoyer un message via Skype™ à zyongh
Citation:
Envoyé par Linio Voir le message
C'est bizarre quand même.

Vous êtes sûr que c'est effectivement plus rapide, y'a un article là dessus?
Un article sur quoi?
__________________
Expertise OpenERP - programmation PHP/MySQL
toujours à l'écoute du marché
zyongh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 13h52   #9
Membre éclairé
 
Avatar de Linio
 
Inscription : octobre 2005
Messages : 427
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 427
Points : 304
Points : 304
Sur la potentielle rapidité supérieur de la fonction __get pour faire un getter.

Parce que de ce que j'en vois c'est exactement pareil qu'un getter normal, il faut faire l'affectation à la main, donc je vois pas en quoi ça peut être plus rapide (mais bon je dois pas voir la grande image). Ca m'intéresse parce que pour mon projet j'accède à pas mal d'accesseurs, et j'aimerais savoir si je dois changer tout mon projet ou pas?
__________________
Linio
Linio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 14h17   #10
Membre chevronné
 
David DRAPEAU
Consultant OpenERP
Inscription : juin 2003
Messages : 807
Détails du profil
Informations personnelles :
Nom : David DRAPEAU

Informations professionnelles :
Activité : Consultant OpenERP

Informations forums :
Inscription : juin 2003
Messages : 807
Points : 728
Points : 728
Envoyer un message via MSN à zyongh Envoyer un message via Skype™ à zyongh
Citation:
Envoyé par Linio Voir le message
Sur la potentielle rapidité supérieur de la fonction __get pour faire un getter.
Parce que PHP reconnait tout de suite __get() comme méthode magique qui a pour objectif d'être getter ce qui n'est pas le cas pour ta méthode getter() qui pour PHP est une méthode comme les autres. Cela reste une supposition. Fais un test avec une boucle qui prend environ 10 secondes avec ta méthode refais la même chose avec __get() et tiens nous au courant.
__________________
Expertise OpenERP - programmation PHP/MySQL
toujours à l'écoute du marché
zyongh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 14h22   #11
Membre régulier
 
Inscription : mai 2007
Messages : 144
Détails du profil
Informations forums :
Inscription : mai 2007
Messages : 144
Points : 78
Points : 78
Bon, j'ai fait un test avec une boucle exécutée un grand nombre de fois...

Citation:
Temps avec ->getId() : 13,6877 secondes.
Temps avec ->id : 3,4484 secondes.
Code source de mon test au cas où :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
class BenchPrivate {
  private $id;
  public function __construct($id) {
    $this->id = $id;
  }
  public function getId() {
    return $this->id;
  }
}
 
class BenchPublic {
  public $id;
  public function __construct($id) {
    $this->id = $id;
  }
}
 
$benchPrivate = new BenchPrivate('TOTO');
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
  $benchPrivate->getId();
}
$end = microtime(true);
echo 'Temps avec ->getId() : ' . number_format($end - $start, 4, ',', '') . ' secondes.<br />';
 
$benchPublic= new BenchPublic('TOTO');
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
  $benchPublic->id;
}
$end = microtime(true);
echo 'Temps avec ->id : ' . number_format($end - $start, 4, ',', '') . ' secondes.<br />';
?>
C'est donc plus rapide de se passer d'accesseurs... Maintenant, c'est évidemment négligeable dans des quantités faibles. Mais par exemple, en cas d'appel répété à un getter, on voit la différence, comme ce fut le cas dans ma page web.

Enfin, quant aux __get(), a priori, ils n'ont pas été conçu dans l'optique de récupérer des attributs, même si beaucoup de gens les utilisent de cette façon.
Evocatii est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 14h38   #12
Membre éclairé
 
Avatar de Linio
 
Inscription : octobre 2005
Messages : 427
Détails du profil
Informations forums :
Inscription : octobre 2005
Messages : 427
Points : 304
Points : 304
Citation:
Envoyé par Evocatii Voir le message
Enfin, quant aux __get(), a priori, ils n'ont pas été conçu dans l'optique de récupérer des attributs, même si beaucoup de gens les utilisent de cette façon.
C'était ce qu'il me semblait d'où ma question. Après je me doutais bien que l'accès direct était plus rapide que le passage par un getter, mais le getter n'est pas vraiment là pour l'optim mais pour la structure du code. Ca reste une question de choix après...
__________________
Linio
Linio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 15h14   #13
Membre chevronné
 
David DRAPEAU
Consultant OpenERP
Inscription : juin 2003
Messages : 807
Détails du profil
Informations personnelles :
Nom : David DRAPEAU

Informations professionnelles :
Activité : Consultant OpenERP

Informations forums :
Inscription : juin 2003
Messages : 807
Points : 728
Points : 728
Envoyer un message via MSN à zyongh Envoyer un message via Skype™ à zyongh
Par défaut tout au feu

Ouais ben moi je vais brûler mes suppositions car j'ai modifié le script de sorte à voir la différence entre getId() et __get() et le résultat est 16,xxx secondes pour getId() et 19,xxx secondes pour __get().

Voici le code modifié
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php class BenchPrivate {
  private $_id;
      public function __construct($id) {     $this->_id = $id;
  }      
  public function getId() {
    return $this->_id;
  }
}

class BenchPrivate2 {
  private $_id = array();
  public function __set($cle, $valeur) {
    $this->_id[$cle] = $id;
  }
  public function __get($cle) {
    return $this->_id[$cle];
  }
}   

class BenchPublic {
  public $id;
  public function __construct($id) {
    $this->id = $id;
  }
}   // avec un getter() fait main $benchPrivate = new 

BenchPrivate('TOTO');
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
  $benchPrivate->getId();
} 
$end = microtime(true);
echo 'Temps avec ->getId() : ' . number_format($end - $start, 4, ',', '') . ' secondes.<br />';
 
// Avec la méthode magique __get() de PHP
$benchPrivate2 = new BenchPrivate2();
$benchPrivate2->tester = 'TOTO'; // Enregistré grâce à la méthode __set()   
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
  $benchPrivate2->tester; // Récupéré grâce à la méthode __get() 
}
$end = microtime(true);
echo 'Temps avec ->__get() : ' . number_format($end - $start, 4, ',', '') . ' secondes.<br />';
 
$benchPublic= new BenchPublic('TOTO');
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
  $benchPublic->id;
}
$end = microtime(true);
echo 'Temps avec ->id : ' . number_format($end - $start, 4, ',', '') . ' secondes.<br />';
?>
__________________
Expertise OpenERP - programmation PHP/MySQL
toujours à l'écoute du marché
zyongh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/10/2007, 15h57   #14
Invité de passage
 
Inscription : décembre 2006
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2006
Messages : 4
Points : 4
Points : 4
Bien entendu c'est une question de choix, après même si le __get n'avait pas pour optique de servir de getter à la base il n'en reste pas moins que c'est une possibilité d'application et d'utilisation de cette méthode magique... pourquoi ne pas l'utiliser dans ce cas là ?

De toute façon je dirais qu'il est inévitable d'utiliser des get lorsque l'on ne veux pas que la variable de classe puisse être modifier n'importe comment à l'extérieur (voire carrément pas !). Il faut donc faire une différenciation entre les variables modifiable sans soucis et les autres...

exemple :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
private $var = null ;
 
public function getVar() {
   return $this->var ;
}
 
public function setVar($var) {
   if(is_string($var)) {
      .... // do treatment
      $this->var = $var ;
      return true ;
   }
   return false ;
}
Dans ce cas là il est judicieux d'utiliser les accesseurs sinon s'il s'agit d'un simple allias au = je ne vois pas trop l'utilité si ce n'est une question esthétique peut-être ^^
mentiss est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h31.


 
 
 
 
Partenaires

Hébergement Web