Class PDO²

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Class PDO²

par rami » 11 mai 2008, 16:17

L'héritage casse le principe d'encapsulation. Une sous classe dépend du fonctionnement de la classe mère (en l'occurrence la classe PDO ici). Il faut au maximum éviter la dépendance à l'implémentation et travailler sur le concept de contrat (programmer par interface).
Sur un plan purement logique, un point m'échappe dans ce raisonnement.

Je pars du principe de base que les fonctions natives d'une version stable d'un langage n'évolueront à priori pas de façon régressives, l'extension ne posera pas de problème dans le temps. Mais comme tu l'as souligné, si on suppose que l'évolution du langage déclare la classe PDO final et donc non extensible, tu n'auras pas le choix de faire une composition. En revanche, pour une modification dans son fonctionnement, que ce soit par héritage ou composition, tu vas quand même te heurter à un problème. L'objet instancié n'aura pas le même comportement et du coup son utilisation dans ta propre classe, qu'elle étende PDO ou en utilise une instance de composition, en sera modifiée également parce que le comportement des méthodes ou des propriétés en aura été modifié... Le résultat de ta propre classe sera donc obligatoirement différent aussi, non ?

Notez que je ne suis pas un gourou de la POO loin s'en faut, je pars peut-être d'une erreur d'interprétation :-k
Tout à fait Cyrano, l'exemple que j'ai donné n'est pas bon. Je voulais dire que tu es dépendant de l'implémentation de la classe mère pas de son contrat (puisque si son contrat change, tu es impacté dans tous les cas).
Prenons un exemple plus concret. Imaginons que tu aies besoin d'étendre PDOStatement pour des raisons diverses, il faut alors l'indiquer à PDO (exemple issu des commentaires de la doc) :
class PDO   {
    class Database extends PDO {
    function __construct($dsn, $username="", $password="", $driver_options=array()) {
        parent::__construct($dsn,$username,$password, $driver_options);
        $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement', array($this)));
    }
}
class DBStatement extends PDOStatement {
    public $dbh;
    protected function __construct($dbh) {
        $this->dbh = $dbh;
    }
}
L'implémentation de PDO fait que la connexion sera fermée seulement à la fin du script. Cela peut poser un problème car le comportement est changé car tu monopolises une connexion inutile à la base. Si tu es dans un environnement fortement sollicité ou si ton traitement dure longtemps, tu pourrais donc saturer le nombre de connexions possibles.
Le code est donc clairement dépendant de l'implémentation de PDO. Si au contraire, tu utilises la composition, tu évites ce problème.

Je ne sais pas si c'est très clair...

Par expérience, j'ai développé un framework basé sur Zend Framework et j'ai massivement utilisé l'héritage plutôt que le composition. A chaque nouveau besoin où je suis obligé de modifier le comportement de classe mères, les applications qui utilisent les versions précédentes risquent de ne plus fonctionner, ou du patir d'effets de bords.
Cela ne pose pas de problème dans le cadre d'application standalone, mais dès que tu développes du code censé être réutilisable, ca devient un problème. Car si un de nos clients décident d'ajouter des fonctionnalités à l'application, soit il faut adapter cette application au nouveau framework (ce qui peut être couteux), soit maintenir plusieurs versions du framework (ce qui n'est pas terrible non plus)

par katagoto » 11 mai 2008, 14:58

Ca change de la méthode procédurale, c'est plus simple a comprendre et ça nous permet de séparer l'affiche du "hard coding", c'est différent...

par SpintroniK » 11 mai 2008, 14:47

Marche pas...
Ca fait même planter Apache, comme la dernière solution que j'ai proposé.
Par contre avec l'héritage, j'ai envie de dire que ça à l'avantage d'être immédiat, c'est plus logique (je trouve) :
Class SQl extends PDO
{
    public $lien;
    public function __construct($url, $login, $password, $nom){
        try
        {
            $lien = parent::__construct('mysql:host='.$url.';dbname='.$nom, $login, $mdp);
        }

        catch(Exception $e)
        {
            //Erreur
        }

    } 
}
Avec ça, je dois juste faire $sql->query(...)

par katagoto » 11 mai 2008, 14:35

Bon, comme vous le savez je suis pas alaise en POO mais je pense que c'est ça :
public function query($mysql) 
    { 
        return(parent::query($mysql)); 
    } 

par SpintroniK » 11 mai 2008, 13:49

Oui, d'ailleurs je me suis gouré dans le code que j'ai mis, ça c'était la première chose que j'avais testé.
Après, en fait, j'ai fait ceci, qui donne la même erreur :
	public function query($mysql)
	{
		return($this->lien->query($mysql));
	}
Mais j'avoue ne pas y comprendre grand chose, normalement le $this->lien contient PDO non ?

j'ai aussi essayé ça :
	public function query($mysql)
	{
		return(PDO::query($mysql));
	}
Normalement ça marche ça nan ?

par Cyrano » 11 mai 2008, 13:27

Dans ta fonction, $lien n'est défini nulle part, et donc pas comme objet non plus :arrow: erreur automatique.

par SpintroniK » 11 mai 2008, 13:20

Comment fait-on avec cette technique pour utiliser la méthode query de PDO?

j'ai essayé ceci : (dans la calsse) :
	public function query($mysql)
	{
		return($lien->query($mysql));
	}
et dans le script :
 $sql = new SQL($url, $login, $pass, $bdd);
$sql->query(...);...
mais j'ai un message d'erreur : Call to a member function query() on a non-object
Je comprends pas trop (et je suis mauvais :D)

par Cyrano » 11 mai 2008, 12:13

Je me trompe sûrement (car moi non plus mon niveau de POO n'est pas "sublime"), mais en ajoutant un "calque" comme ça, si PDO change je n'aurais qu'à modifier ma classe et non tout mon code, ce sera plus rapide il me semble. Non ?!?
Tout aussi logique, et même dans ce cas préférer la composition à l'héritage ne se justifie pas davantage...

C'est pour ça que j'attends avec intérêt un éclaircissement de rami sur ce point :-k

par katagoto » 11 mai 2008, 12:08

Je me trompe sûrement (car moi non plus mon niveau de POO n'est pas "sublime"), mais en ajoutant un "calque" comme ça, si PDO change je n'aurais qu'à modifier ma classe et non tout mon code, ce sera plus rapide il me semble. Non ?!?

par SpintroniK » 11 mai 2008, 10:27

Je suis un peu d'accord avec le raisonnement de Cyrano, mais mon niveau en POO n'est pas excellent donc je peux me tromper.
En gros, si tu utilise PDO d'une façon ou d'une autre si une méthode de PDO est modifiée ça va forcément se répercuter sur ton code, quelque soit la technique que tu utilises pour appeler PDO, ça me parait plutôt logique...
Pour reprendre zeus, si un jour tous les fruits doivent être rouges (exemple très con) alors ta pomme deviendra forcément rouge.
Enfin si on réfléchit comme ça, ça paraît logique, maintenant peut être que ça n'est pas la bonne interprétation :?:

par Cyrano » 11 mai 2008, 10:13

L'héritage casse le principe d'encapsulation. Une sous classe dépend du fonctionnement de la classe mère (en l'occurrence la classe PDO ici). Il faut au maximum éviter la dépendance à l'implémentation et travailler sur le concept de contrat (programmer par interface).
Sur un plan purement logique, un point m'échappe dans ce raisonnement.

Je pars du principe de base que les fonctions natives d'une version stable d'un langage n'évolueront à priori pas de façon régressives, l'extension ne posera pas de problème dans le temps. Mais comme tu l'as souligné, si on suppose que l'évolution du langage déclare la classe PDO final et donc non extensible, tu n'auras pas le choix de faire une composition. En revanche, pour une modification dans son fonctionnement, que ce soit par héritage ou composition, tu vas quand même te heurter à un problème. L'objet instancié n'aura pas le même comportement et du coup son utilisation dans ta propre classe, qu'elle étende PDO ou en utilise une instance de composition, en sera modifiée également parce que le comportement des méthodes ou des propriétés en aura été modifié... Le résultat de ta propre classe sera donc obligatoirement différent aussi, non ?

Notez que je ne suis pas un gourou de la POO loin s'en faut, je pars peut-être d'une erreur d'interprétation :-k

par katagoto » 11 mai 2008, 10:00

Le sujet est résolut, je ne saisit juste pas nuance, mais je pense que ça vient du fait que $methode n'a pas été déclarer...

Merci à tous

++

par zeus » 11 mai 2008, 09:52

Ensuite, merci à zeus, mais comment dois-je l'utiliser, j'ai bien une idée :
public function __call($methode, $parametres)
C'est presque ça, ce code est fonctionnel sauf que c'est
public function __call($lien, $methode)
L'héritage casse le principe d'encapsulation. Une sous classe dépend du fonctionnement de la classe mère (en l'occurrence la classe PDO ici). Il faut au maximum éviter la dépendance à l'implémentation et travailler sur le concept de contrat (programmer par interface).

L'héritage peut fragiliser le code car il dépend de détails d'implémentation. Clairement, n'ayant pas la main sur l'implémentation de la classe PDO, utiliser la composition permet de s'affranchir du fonctionnement interne de la classe.

J'ai tendance à utiliser l'héritage dans du code que je maîtrise. C'est fort pratique pour factoriser du code. Mais dès que je dépend du code d'autrui, j'utilise au maximum la composition afin de rester insensible aux modifications futures de la librairie que j'utilise
Je comprend ces arguments là et je trouve qu'ils peuvent avoir un fond très judicieux.
Or, je pense qu'une bonne modélisation prend en compte l'état des objets avant même de penser au code.
Or, pour moi, une pomme est un fruit, et il y a héritage. Lorsque j'arrive au niveau de l'implémentation, il est trop tard pour refaire ce choix là.
Je suis surement un peu trop utopique, mais jusque là, prendre du temps sur une grosse conception ne m'a jamais causé de soucis irrémédiables.

PS : désolé katagoto :(

par katagoto » 11 mai 2008, 09:30

Je sens un débat intéressant. ;)
Erf
// tu ne devrais pas hard coder le DSN car ta classe ne peut pas
//être utilisée avec MySQL par exemple
Je tiens compte de ta remarque, mais je penses que tout le monde connait mes convictions su ce sujet et à défaut d'avoir raison, c'est toujours mon code...

Bref pour ceux qui ne l'aurait pas compris, j'essai d'éviter de surcharger mon code en local car je travail avec des codeurs pas très portés sur la sécurité, voilà...

Ensuite, merci à zeus, mais comment dois-je l'utiliser, j'ai bien une idée :
<?php
class sql {
   public function __call($methode, $parametres) {
         try
         {
            return $methode->$parametres;
         }
         catch(Exception $e) 
        { 
            $_SESSION['erreur']=$e; 
            header("Location:erreur_sql.php"); 
        } 
   }
}
Je crois que c'est ça

PS : Faites le débat après la résolution de mon problème SVP :roll:

PPS : J'ai fait du C++ (qui est connu pour sa méthode objet), et j'ai toujours été partagé entre le fait d'éliminer la redondance de mes applications quit à augmenter les dépendances, et j'en suis venu à la conclusion que moins il y aurait de dépendance plus les maintenances et les améliorations seraient simple... voilà pour moi

par rami » 11 mai 2008, 00:42

L'héritage casse le principe d'encapsulation. Une sous classe dépend du fonctionnement de la classe mère (en l'occurrence la classe PDO ici). Il faut au maximum éviter la dépendance à l'implémentation et travailler sur le concept de contrat (programmer par interface).

L'héritage peut fragiliser le code car il dépend de détails d'implémentation. Clairement, n'ayant pas la main sur l'implémentation de la classe PDO, utiliser la composition permet de s'affranchir du fonctionnement interne de la classe.

J'ai tendance à utiliser l'héritage dans du code que je maîtrise. C'est fort pratique pour factoriser du code. Mais dès que je dépend du code d'autrui, j'utilise au maximum la composition afin de rester insensible aux modifications futures de la librairie que j'utilise

Exemple :
Imagine que tu surcharge la méthode fetch de PDO pour ajouter un comportement particulier. Pour diverses raisons, les programmeurs de PHP décident de rendre la méthode finale dans la prochaine version de PDO (je sais, ce n'est pas possible en PHP, c'est simplement une illustration). Et là c'est le drame car ta classe ne fonctionnera plus.
Au contraire, si tu utilises la composition, ca sera complètement transparent dans ton code

Liens utiles:
http://www.artima.com/designtechniques/compoinh.html (à lire absolument)
http://blog.emmanueldeloget.com/index.p ... omposition

Je te conseille aussi le très bon livre : Java efficace de Joshua Bloch