Comments on: Coder une classe d’abstraction pour manipuler des objets en PHP5 https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18 Ressources sur le développement internet, PHP/MySQL, Ajax, marketing online, référencement... Thu, 17 Jun 2010 18:09:04 +0000 http://wordpress.org/?v=2.9.2 hourly 1 By: gtraxx https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-958 gtraxx Mon, 16 Mar 2009 21:14:39 +0000 https://www.php-experts.org/?p=18#comment-958 C'est encore plus amusant de jumeler avec des interfaces et du rewind engine tout en utilisant les design patterns. On peu alors avoir une application puissante et facile à maintenir. Je le démontre avec ma librairie en cours de développement. Je cherche notamment des contributeurs et testeurs pour la version alpha qui arrive sous peu. Le lien est dans mon pseudo, je serai ravi d'avoir un retour ou peut être un article de l'administrateur de ce blog très intéressant. C’est encore plus amusant de jumeler avec des interfaces et du rewind engine tout en utilisant les design patterns.
On peu alors avoir une application puissante et facile à maintenir.
Je le démontre avec ma librairie en cours de développement.
Je cherche notamment des contributeurs et testeurs pour la version alpha qui arrive sous peu.
Le lien est dans mon pseudo, je serai ravi d’avoir un retour ou peut être un article de l’administrateur de ce blog très intéressant.

]]>
By: Didier https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-38 Didier Fri, 05 Sep 2008 17:54:01 +0000 https://www.php-experts.org/?p=18#comment-38 L'utilisation de __get et __set peut permettre de monter, par l'intermédiaire, par exemple, d'une propriété $editableFields, un système de champs modifiables ou pas. Dans le cas d'une gestion d'utilisateur (exemple pris au hasard), on peut éditer les informations personnelles, mais pas l'ID ni le login. Ca permet de "verrouiller" certains champs qu'il ne faut absolument pas éditer. Quant aux performances, je veux bien te croire sur parole, mais je vais quand même monter rapidement un mini-bechmark, histoire d'en avoir le coeur net. Je me ferais un plaisir de vous tenir informés des résultats... En tout cas, merci beaucoup pour ces précisions ! L’utilisation de __get et __set peut permettre de monter, par l’intermédiaire, par exemple, d’une propriété $editableFields, un système de champs modifiables ou pas. Dans le cas d’une gestion d’utilisateur (exemple pris au hasard), on peut éditer les informations personnelles, mais pas l’ID ni le login. Ca permet de “verrouiller” certains champs qu’il ne faut absolument pas éditer.
Quant aux performances, je veux bien te croire sur parole, mais je vais quand même monter rapidement un mini-bechmark, histoire d’en avoir le coeur net. Je me ferais un plaisir de vous tenir informés des résultats…
En tout cas, merci beaucoup pour ces précisions !

]]>
By: Eric Daspet https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-36 Eric Daspet Fri, 05 Sep 2008 15:24:50 +0000 https://www.php-experts.org/?p=18#comment-36 Pour la question des performances je ne peux que contredire, les problèmes de __get() n'ont rien à voir avec la différence echo/print et si vous commencez à monter trop d'architectures inutiles sur ces méthodes magiques ça risque vite de vous couter bien plus cher que les unes ou deux semaines de développement nécessaires pour programmer proprement au départ. Mais ce n'est pas la question. Déjà ton truc est finalement plus complexe que trois bêtes lignes de code : $this->infos = $db->getRow("select * from $table where id = ‘$id’") Moi je le remplacerai par $infos = $db->getRow("select * from $table where id = ‘$id’") foreach( $infos as $name => $value ) $this->{$name} = $value ; Ce n'est pas beaucoup plus long mais au moins tu n'as pas besoin de méthodes magiques. Ces méthodes magiques sont quasiment toujours une mauvaise idée. Elles ne sont au mieux qu'un paliatif quand on récupère un projet déjà peu extensible et qu'on a une correction/évolution avec la contrainte "toucher le moins possible au code". Les seules utilisations vraiment sensées que j'ai vu de __get/__set/__call c'est pour l'accès à des objets distants ou des objets proxy dont ni l'utilisateur ni le créateur ne connait la liste des attributs. Un bon exemple est la manière dont fonctionne le client SOAP natif de PHP. Ce n'est pas faute d'aimer le concept d'attribut virtuel, j'adore ça au contraire, mais l'implémentation qu'a choisit PHP n'a quasiment aucun avantage. Pour la question des performances je ne peux que contredire, les problèmes de __get() n’ont rien à voir avec la différence echo/print et si vous commencez à monter trop d’architectures inutiles sur ces méthodes magiques ça risque vite de vous couter bien plus cher que les unes ou deux semaines de développement nécessaires pour programmer proprement au départ.

Mais ce n’est pas la question.

Déjà ton truc est finalement plus complexe que trois bêtes lignes de code :

$this->infos = $db->getRow(“select * from $table where id = ‘$id’”)

Moi je le remplacerai par

$infos = $db->getRow(“select * from $table where id = ‘$id’”)
foreach( $infos as $name => $value ) $this->{$name} = $value ;

Ce n’est pas beaucoup plus long mais au moins tu n’as pas besoin de méthodes magiques. Ces méthodes magiques sont quasiment toujours une mauvaise idée. Elles ne sont au mieux qu’un paliatif quand on récupère un projet déjà peu extensible et qu’on a une correction/évolution avec la contrainte “toucher le moins possible au code”.

Les seules utilisations vraiment sensées que j’ai vu de __get/__set/__call c’est pour l’accès à des objets distants ou des objets proxy dont ni l’utilisateur ni le créateur ne connait la liste des attributs. Un bon exemple est la manière dont fonctionne le client SOAP natif de PHP.

Ce n’est pas faute d’aimer le concept d’attribut virtuel, j’adore ça au contraire, mais l’implémentation qu’a choisit PHP n’a quasiment aucun avantage.

]]>
By: Hugo https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-18 Hugo Wed, 13 Aug 2008 07:29:13 +0000 https://www.php-experts.org/?p=18#comment-18 @En codant proprement, on pourrait déjà éviter de recommencer les sites “from scratch” tous les 2 ou 3 ans, ce qui semble étonnamment être une norme dans le milieu. Ca ne m'étonne pas du tout que l'on ait à redévelopper "from scratch" les sites au bout de 2 ou 3 ans dans la mesure où les technologies du web évoluent en permanence. 2, voire même 3 ans, c'est une longue période dans le domaine du web contrairement au monde du progiciel où l'on développe parfois pendant plus de 5 ans. Je pense que les entreprises ne devraient pas se focaliser sur de la réutilisabilité du code à trop long terme (2 à 3 ans) car il y'aura clairement des évolutions majeures pendant cette période. Au contraire, je suis plutôt d'avis de dire : "il est temps de (presque) jeter (tout) à la poubelle ce que l'on a fait il y'a un an et demi et redévelopper proprement. Je comprends néanmoins que les entreprises ne veuillent pas prendre ces voies là car forcément ça leur coûte beaucoup d'argent en investissement mais c'est aussi un risque à prendre si l'on veut rester innovant, à la pointe des dernières technos et des dernières bonnes pratiques. De plus, se dire que l'on recommence avec une mise à jour de la techno (par exemple passer à PHP 5 quand on est encore en PHP 3 / 4) permet à l'équipe de développement de se former à nouveau et d'acquérir de nouvelles compétences. Un développeur web qui a passé 3 ans ou plus à faire du PHP 4 dans une société aura très certainement du mal à trouver une autre société "plus moderne" s'il n'a jamais pratiqué PHP 5. Et aujourd'hui, un développeur peut difficilement afficher sur son CV qu'il maîtrise PHP 4 tellement c'est devenu obsolète. Il est donc du devoir de l'entreprise de savoir prendre du temps à recoder certains de leurs produits avec des nouvelles technos à la fois pour une meilleure qualité, de meilleures performances, une meilleure sécurité et pour continuer de former ses salariés. ++ @En codant proprement, on pourrait déjà éviter de recommencer les sites “from scratch” tous les 2 ou 3 ans, ce qui semble étonnamment être une norme dans le milieu.

Ca ne m’étonne pas du tout que l’on ait à redévelopper “from scratch” les sites au bout de 2 ou 3 ans dans la mesure où les technologies du web évoluent en permanence. 2, voire même 3 ans, c’est une longue période dans le domaine du web contrairement au monde du progiciel où l’on développe parfois pendant plus de 5 ans.

Je pense que les entreprises ne devraient pas se focaliser sur de la réutilisabilité du code à trop long terme (2 à 3 ans) car il y’aura clairement des évolutions majeures pendant cette période. Au contraire, je suis plutôt d’avis de dire : “il est temps de (presque) jeter (tout) à la poubelle ce que l’on a fait il y’a un an et demi et redévelopper proprement.

Je comprends néanmoins que les entreprises ne veuillent pas prendre ces voies là car forcément ça leur coûte beaucoup d’argent en investissement mais c’est aussi un risque à prendre si l’on veut rester innovant, à la pointe des dernières technos et des dernières bonnes pratiques. De plus, se dire que l’on recommence avec une mise à jour de la techno (par exemple passer à PHP 5 quand on est encore en PHP 3 / 4) permet à l’équipe de développement de se former à nouveau et d’acquérir de nouvelles compétences. Un développeur web qui a passé 3 ans ou plus à faire du PHP 4 dans une société aura très certainement du mal à trouver une autre société “plus moderne” s’il n’a jamais pratiqué PHP 5. Et aujourd’hui, un développeur peut difficilement afficher sur son CV qu’il maîtrise PHP 4 tellement c’est devenu obsolète. Il est donc du devoir de l’entreprise de savoir prendre du temps à recoder certains de leurs produits avec des nouvelles technos à la fois pour une meilleure qualité, de meilleures performances, une meilleure sécurité et pour continuer de former ses salariés.

++

]]>
By: Didier https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-17 Didier Tue, 12 Aug 2008 22:37:12 +0000 https://www.php-experts.org/?p=18#comment-17 Hugo: il est du devoir de l'équipe technique de faire comprendre aux "instance dirigeantes" comment la deuxième option (code propre plus cher à produire) peut être rentable à moyen ou long terme. En codant proprement, on pourrait déjà éviter de recommencer les sites "from scratch" tous les 2 ou 3 ans, ce qui semble étonnamment être une norme dans le milieu. J'ai déjà vu des entreprises (et pas des moindres) reconnaitre que le code d'un projet avait "mal vieilli"... avant même sa mise en production. La méthode d'accès à la DB fait partie des "raccourcis" que j'ai consentis à prendre pour alléger au maximum les exemples. En effet, un singleton serait beaucoup plus approprié. Merci pour toutes ces précisions, notamment au niveau des restrictions imposées à la génération de documentation. Palleas: bah quoi ! :p Hugo: il est du devoir de l’équipe technique de faire comprendre aux “instance dirigeantes” comment la deuxième option (code propre plus cher à produire) peut être rentable à moyen ou long terme. En codant proprement, on pourrait déjà éviter de recommencer les sites “from scratch” tous les 2 ou 3 ans, ce qui semble étonnamment être une norme dans le milieu. J’ai déjà vu des entreprises (et pas des moindres) reconnaitre que le code d’un projet avait “mal vieilli”… avant même sa mise en production.
La méthode d’accès à la DB fait partie des “raccourcis” que j’ai consentis à prendre pour alléger au maximum les exemples. En effet, un singleton serait beaucoup plus approprié.
Merci pour toutes ces précisions, notamment au niveau des restrictions imposées à la génération de documentation.

Palleas: bah quoi ! :p

]]>
By: Palleas https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-15 Palleas Mon, 11 Aug 2008 19:32:58 +0000 https://www.php-experts.org/?p=18#comment-15 > Or, et malheureusement, il est de nos jours nécessaire de se rappeler que l’hébergement d’un site, même si ses coûts pourraient être réduits par de l’optimisation poussée/poussive sur le code, coûtera bien moins cher qu’un développeur qualifié, à plein temps, occupé à maintenir du code “optimisé” mais dont on pourrait aisément se passer en achetant un serveur plus puissant Mais LOL ! > Or, et malheureusement, il est de nos jours nécessaire de se rappeler que l’hébergement d’un site, même si ses coûts pourraient être réduits par de l’optimisation poussée/poussive sur le code, coûtera bien moins cher qu’un développeur qualifié, à plein temps, occupé à maintenir du code “optimisé” mais dont on pourrait aisément se passer en achetant un serveur plus puissant

Mais LOL !

]]>
By: Hugo https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-14 Hugo Mon, 11 Aug 2008 19:11:11 +0000 https://www.php-experts.org/?p=18#comment-14 Salut, Je ne suis pas tout à fait d'accord avec ce tutoriel bien qu'il soit bien expliqué. Je commence concernant la variable globale d'accès à la DB. A mon sens, déclarer une variable comme globale dans une classe (ou une fonction) oblige à la déclarer quelque part ailleurs en dehors de la classe, ce qui est loin d'être maintenable, évolutif et modulaire (comme vous l'évoquiez au sujet de l'optimisation abusive). Une meilleure solution, serait certainement de stocker cette instance dans une variable superglobale du tableau $GLOBALS. Ou encore mieux, d'utiliser par exemple un singleton (ou multiton si l'on veut gérer plusieurs connexions) à l'intérieur de la classe. Par exemple : class GenericObject { protected $_infos = array(); public function save() { $oDb = DatabaseManager::getInstance(); $oDb->query('INSERT INTO table (champ) VALUES("toto")'); } } Ainsi, on ne se trimballe plus une variable globale mais une instance unique de l'objet d'accès à la DB que l'on manipule à travers une classe. Concernant les performances, j'aimerai que vous nous éclairiez car je ne vois pas en quoi _get(), __set() ou encore les APIs "Reflexion" posent problème au niveau des performances. Je n'ai jamais entendu à ce jour que l'utilisation de ces APIs puisse mettre à mal un serveur mutualisé... Et puis avec des caches d'opcodes on compenses grandement les pertes de performances car les scripts ne sont plus réinterprêtés et précompilés à chaque requête. Enfin, il ne faut pas oublier de mentionner que malgré leur côté très pratique, ces deux méthodes magiques ne permettent pas de générer de la documentation technique du code, ni de permettre l'auto-complétion dans les IDE tels qu'Eclipse. Donc je suis personnellement très sceptique à les utiliser et je préfère de loin me taper à la main l'écriture des getters et setters de mes classes qui me permettent : 1/ De pouvoir générer de la documentation technique du code 2/ De pouvoir profiter de l'auto-complétion dans Eclipse et donc gagner finalement du temps quand j'utilise mes objets 3/ D'éviter d'avoir du code monolithique dans la seule méthode __get() lorsque l'on a besoin de faire du contrôle d'accès. 4/ De pouvoir effectivement faire du contrôle d'accès propre, maintenable et modulaire sur mes attributs. Le problème en utilisant les méthodes magiques __get() et __set() c'est que l'on ne peut pas facilement traiter les types et valeurs de chaque attribut virtuel représentant un champ de la table. Admettons que ma table est constitué de 20 champs de type très hétérogènes (int, varchar, blob, date, datetime, double...). La seule solution pour faire du contrôle d'accès sur les valeurs, c'est d'écrire à la main dans les deux méthodes, une série de if() ou un long switch()... Par exemple, si je fais : $oTransaction = new Transaction() $oTransaction->from = 'Pierre'; $oTransaction->to = 'Hugo'; $oTransaction->amount = 54.76; $oTransaction->time = '2008-08-11 20:45:43'; $oTransaction->save(); Je me retrouve ici avec deux chaines, un nombre et une date. Pour m'assurer que ces valeurs ont des formats et des valeurs correctes, je serai obligé de les contrôler dans __set() public function __set($property, $value) { switch($property) { case 'to': $this->to = (string) $value; break; case 'from': $this->from = (string) $value; break; case 'amount': if(!is_numeric($value) || ($value amount = (double) $amount; break; case 'time': if(!icheckdate($value) || (strtotime($value) time = (int) strtotime($amount); break; default: throw new Exception('Attribut non reconnu'); break; } } De même pour retourner les bons types et format en lisant la valeur d'une propriété, il faudra tester chaque propriété et appliquer la conversion de format et / ou le transtypage adéquat. On se retrouve donc avec du code monolithique et imbuvable, alors qu'avec des getters() et setters() on a la chance de s'y retrouver plus facilement puisqu'à une méthode getXXX() et setXXX() correspond le traitement d'un attribut XXX. Donc il faut voir les méthodes magiques comme une fonctionnalité fort appréciable pour développer vite mais pas forcément pour développer bien... Et malheureusement, je rebondis sur ce que vous dites concernant la valeur ajoutée du développeur aujourd'hui pour dire que oui je suis d'accord sur ce point de vue là mais que malheureusement on ne peut pas coder vite et bien. C'est un choix à prendre pour une entreprise. Soit on décide absolument de vendre pas cher, de casser les prix et de mettre la pression aux développeurs pour qu'ils écrivent le moins de code possible au risque que ce dernier soit complètement peu modulaire et maintenable ; ou bien on prend un peu plus de temps ce qui permet d'écrire plus de code mais certainement du meilleur code, bien documenté, plus maintenable, plus modulaire... Personnellement je partage plus le deuxième esprit mais malheureusement rares sont les entreprises qui décident cette voie là puisqu'elle n'est pas suffisamment rentable pour elles... Dommage car cela ouvre davantage de portes aux mauvais développeurs et aux codeurs du dimanche qui écrivent des applications bancales et pas toujours sécurisées comme il se devrait. A bientôt, Hugo. Salut,

Je ne suis pas tout à fait d’accord avec ce tutoriel bien qu’il soit bien expliqué.

Je commence concernant la variable globale d’accès à la DB. A mon sens, déclarer une variable comme globale dans une classe (ou une fonction) oblige à la déclarer quelque part ailleurs en dehors de la classe, ce qui est loin d’être maintenable, évolutif et modulaire (comme vous l’évoquiez au sujet de l’optimisation abusive). Une meilleure solution, serait certainement de stocker cette instance dans une variable superglobale du tableau $GLOBALS. Ou encore mieux, d’utiliser par exemple un singleton (ou multiton si l’on veut gérer plusieurs connexions) à l’intérieur de la classe. Par exemple :

class GenericObject
{
protected $_infos = array();

public function save()
{
$oDb = DatabaseManager::getInstance();
$oDb->query(‘INSERT INTO table (champ) VALUES(“toto”)’);
}

}

Ainsi, on ne se trimballe plus une variable globale mais une instance unique de l’objet d’accès à la DB que l’on manipule à travers une classe.

Concernant les performances, j’aimerai que vous nous éclairiez car je ne vois pas en quoi _get(), __set() ou encore les APIs “Reflexion” posent problème au niveau des performances. Je n’ai jamais entendu à ce jour que l’utilisation de ces APIs puisse mettre à mal un serveur mutualisé… Et puis avec des caches d’opcodes on compenses grandement les pertes de performances car les scripts ne sont plus réinterprêtés et précompilés à chaque requête.

Enfin, il ne faut pas oublier de mentionner que malgré leur côté très pratique, ces deux méthodes magiques ne permettent pas de générer de la documentation technique du code, ni de permettre l’auto-complétion dans les IDE tels qu’Eclipse. Donc je suis personnellement très sceptique à les utiliser et je préfère de loin me taper à la main l’écriture des getters et setters de mes classes qui me permettent :

1/ De pouvoir générer de la documentation technique du code
2/ De pouvoir profiter de l’auto-complétion dans Eclipse et donc gagner finalement du temps quand j’utilise mes objets
3/ D’éviter d’avoir du code monolithique dans la seule méthode __get() lorsque l’on a besoin de faire du contrôle d’accès.
4/ De pouvoir effectivement faire du contrôle d’accès propre, maintenable et modulaire sur mes attributs.

Le problème en utilisant les méthodes magiques __get() et __set() c’est que l’on ne peut pas facilement traiter les types et valeurs de chaque attribut virtuel représentant un champ de la table. Admettons que ma table est constitué de 20 champs de type très hétérogènes (int, varchar, blob, date, datetime, double…). La seule solution pour faire du contrôle d’accès sur les valeurs, c’est d’écrire à la main dans les deux méthodes, une série de if() ou un long switch()… Par exemple, si je fais :

$oTransaction = new Transaction()
$oTransaction->from = ‘Pierre’;
$oTransaction->to = ‘Hugo’;
$oTransaction->amount = 54.76;
$oTransaction->time = ‘2008-08-11 20:45:43′;
$oTransaction->save();

Je me retrouve ici avec deux chaines, un nombre et une date. Pour m’assurer que ces valeurs ont des formats et des valeurs correctes, je serai obligé de les contrôler dans __set()

public function __set($property, $value)
{
switch($property)
{
case ‘to’:
$this->to = (string) $value;
break;
case ‘from’:
$this->from = (string) $value;
break;
case ‘amount’:
if(!is_numeric($value) || ($value amount = (double) $amount;
break;
case ‘time’:
if(!icheckdate($value) || (strtotime($value) time = (int) strtotime($amount);
break;
default:
throw new Exception(‘Attribut non reconnu’);
break;
}
}

De même pour retourner les bons types et format en lisant la valeur d’une propriété, il faudra tester chaque propriété et appliquer la conversion de format et / ou le transtypage adéquat.

On se retrouve donc avec du code monolithique et imbuvable, alors qu’avec des getters() et setters() on a la chance de s’y retrouver plus facilement puisqu’à une méthode getXXX() et setXXX() correspond le traitement d’un attribut XXX.

Donc il faut voir les méthodes magiques comme une fonctionnalité fort appréciable pour développer vite mais pas forcément pour développer bien… Et malheureusement, je rebondis sur ce que vous dites concernant la valeur ajoutée du développeur aujourd’hui pour dire que oui je suis d’accord sur ce point de vue là mais que malheureusement on ne peut pas coder vite et bien. C’est un choix à prendre pour une entreprise. Soit on décide absolument de vendre pas cher, de casser les prix et de mettre la pression aux développeurs pour qu’ils écrivent le moins de code possible au risque que ce dernier soit complètement peu modulaire et maintenable ; ou bien on prend un peu plus de temps ce qui permet d’écrire plus de code mais certainement du meilleur code, bien documenté, plus maintenable, plus modulaire… Personnellement je partage plus le deuxième esprit mais malheureusement rares sont les entreprises qui décident cette voie là puisqu’elle n’est pas suffisamment rentable pour elles… Dommage car cela ouvre davantage de portes aux mauvais développeurs et aux codeurs du dimanche qui écrivent des applications bancales et pas toujours sécurisées comme il se devrait.

A bientôt,

Hugo.

]]>
By: Julien BREUX https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/comment-page-1#comment-13 Julien BREUX Sat, 09 Aug 2008 09:41:08 +0000 https://www.php-experts.org/?p=18#comment-13 Très bonne idée, cela dit, c'est un peu déroutant d'un point de vue conceptualisation. Mais efficace ;) Très bonne idée, cela dit, c’est un peu déroutant d’un point de vue conceptualisation.
Mais efficace ;)

]]>