Debuts en POO

Rechercher

Debuts en POO

Par paintbox  -  19 reponses  -  Le 29/08/2011 18:00  -  Editer  - 

Hello Cyrano,

 

je tente de me mettre à la programmation orientée objet mais je butte déjà sur un premier exercice.

J'ai pourtant suivi les tutoriaux de ApprendrePhp.

Je créé un class person dont les attribnuts sont nom, prenom et adresse.

Je créé une fonction pour afficher les infos et une autre qui permet de modifier l'adresse.

Malheureusement, rien ne s'affiche et je ne vois pas où il y aurait une erreur.

Voici le code :

class Person
    {
        private $nom;
        private $prenom;
        private $adresse;
        // => Constructeur
        public function _construct($nom, $prenom, $adresse)
            {
                $this->nom      =   $nom;
                $this->prenom   =   $prenom;
                $this->adresse  =   $adresse;
            }
        // => Affichage des données
        public function getInfo()
            {
                $coord = "$this->nom $this->prenom $this->adresse";
                return $coord;
            }
        // => Modification de adresse
        public function setAdresse($adresse)
            {
                $this->adresse = $adresse;
            }
    }
// Creation d'objets
$person1 = new Person("Albert", "Marc", "46 Avenue du Parc");
echo $person1->getInfo();

 

 

Réponses apportées à cette discussion

Par Cyrano  -  Le 29/08/2011 20:06  -  Haut de page  - 

Salut,

j'ai eu un peu de mal à le voir, ce n'est pas évident comme erreur : il s'agit de la différence entre _ et __ pour nommer ton constructeur.

Là tu as écrit _construct au lieu de __construct, donc syntaxiquement il n'y a pas d'erreur, mais ce n'est qu'une méthode ordinaire comme les autres et non le constructeur, donc les éléments qui sont envoyés lors de la création de l'instance ne servent jamais parce que le constructeur est dans ce cas implicite et ne comporte aucun paramètre, ceux qui sont envoyés ne servant à rien. En rajoutant un simple « _ » à ton constructeur, ça va résoudre ton soucis ;)

 
Par paintbox  -  Le 29/08/2011 23:20  -  Haut de page  - 

Hello Cyrano,

bien vu! Je crois que j'aurais encore pu chercher longtemps. Je ne pensais pas dutout à ce type d'erreur. Cela fonctionne effectivement mieux. J'avais également remarqué qu'aucun paramètre ne passait.

Comme je le disais, je commence la POO et même si je comprends le principe, le fonctionnement j'ai du mal a voir cela en pratique. Donc si tu as des exemples d'utilisations ou des sites avec des exercices, je suis preneur (je sais que t'es explications sont très bonnes et m'ont bien servies jusqu'à présent)

 

Encore merci !

 
Par Cyrano  -  Le 30/08/2011 07:51  -  Haut de page  - 

Il y aurait un très bon bouquin pour comprendre les concepts de l'orienté-objet, malheureusement l'éditeur n'existe plus en France, il faudrait donc tenter de le trouver en occasion : « Analyse et conception orientée objet - tête la première » publié chez O'Reilly, sinon il est aussi disponible au format numérique à la Fnac

J'avais eu un peu de mal à rentrer dedans au départ parce qu'il est surtout basé sur la programmation en Java qui pour le coup est un langage full objet. Mais les principes sont les mêmes en PHP.

Sinon, dis-toi que certains principes de bases sont indispensables : par exemple, une classe ne fait qu'une seule chose, mais elle le fait bien. Et pour certains traitements complexes, on aura parfois besoin de combiner plusieurs classes. Le plus diffcile en débutant consiste à identifier ce qui peut être considéré ou non comme un objet. C'est souvent assez abstrait. On se pose aussi souvent la question de l'intéret de la POO par rapport à des collection de fonctions qu'on pourrait inclure comme on le fiait en procédural. Ce point est du reste de mon point de vue difficile à expliquer, ça vient avec l'usage et en fin de compte, ça simpifie la vie. Mais je dirais aussi surtout que ça amène à utiliser des principes de programmation propres et durables dans le temps. On crée des classes qui sont portables sur de très nombreux projets. À terme, ça a amené à la création d'ensembles beaucoup plus complexes comme Symfony, Zend Framework et autres du genre qui font que lorsqu'on construit une application, on peut se concentrer sur le code métier au lieu de devoir aussi écrire certains traitements qui existent déjà ailleurs et qu'on pourrait reprendre sans modification.

Petit à petit, tu vas réaliser qu'il n'est pas inutile d'avoir une vision d'ensemble des paquets de classes et que la modélisation peut simplifier beaucoup la conception : ça devrait t'inciter à t'intéresser à la modélisation en UML.

 

 
Par paintbox  -  Le 30/08/2011 13:26  -  Haut de page  - 

Hello,

 

merci pour ces conseils. Effectivement j'essai aussi de me mettre à l'ULM. Je vais essayer de trouver le livre dont tu parles.

Et pour la POO je crois, comme tu le dis, que cela viendra à force d'en faire. C'est donc mon nouvel objectif.

Encore merci

 
Par paintbox  -  Le 31/08/2011 13:08  -  Haut de page  - 

Hello Cyrano,

nouveau soucis dans mon apprentissage de l'orienté objet.

Je suis en train de faire un tuto trouvé sur un site.

L exercice est la gestion des commandes d'une pizzeria.

 

Voici ma class :

class Commande
    {
        public $nomClient;
        public $listePizza = Array();
        public $prixRoyal = 6;
        public $prixCampagnarde = 8;
        // Ajout quantité pizza royale
        public function ajouterRoyale($nombre)
            {
                $this->listePizza[0]+=$nombre;
            }
        // Ajout quantité pizza campagnarde
        public function ajouterCampagnarde($nombre)
            {
                $this->listePizza[1]+=$nombre;
            }
        // Fonction qui calcul le prix
        public function calculerPrix()
            {
                $montant_Royal       = $this->listePizza[0] * $this->prixRoyal;
                $montant_Campagnarde = $this->listePizza[1] * $this->prixCampagnarde;
                return $montant_Royal + $montant_Campagnarde;
            }
        // Fonction qui affiche le resultat de la commande
        public function afficherCommande()
            {
                echo 'Commande du client : '.$this->nomClient;
                echo '<br />Pizza(s) Royale : '.$this->listePizza[0];
                echo '<br />Pizza(s) Campagnarde : '.$this->listePizza[1];
                echo '<br />Total de votre commande : '.$this->calculerPrix();
                echo ' Euros<br />';
            }
    }

 

Ensuite, voici la page sur laquelle je créé mes objets et ou j'indique la quantité de pizza commandées

 

include ('pizza.class.php');
$client = new commande();
$client->nomClient="Dupont";
$client->listePizza[0]=5;
$client->listePizza[1]=2;
echo 'Nom du client 1 : '.$client->nomClient.'<br />';
echo 'Quantite de Pizza Royale commandee : '.$client->listePizza[0].'<br /><br />';
$client->afficherCommande();
$client2 = new Commande();
$client2->nomClient='Durand';
$client2->ajouterCampagnarde(12);
echo 'Nom du client 2 : '.$client2->nomClient.'<br />';
echo 'Quantite de Pizza Campagnarde commandee : '.$client2->listePizza[0].'<br /><br />';
$client2->afficherCommande();

 

 

Pour info, listePizza correspond aux différentes pizzas. C'est un tableau qui contient pour l'instant 2 pizzas.

En fait j'obtiens à plusieurs reprises des Undefined Offset.

 

Je ne comprends pas pourquoi. J'ai tenté de déclarer listePizza en array mais cela ne change rien.

J'ai fais un var_dump de listePizza et le résulat me parrait correct.

 

J'aurais donc besoin de tes lumières pour m'éclairer sur ce problème.

 

Merci

 
Par paintbox  -  Le 31/08/2011 14:07  -  Haut de page  - 

J'ai compris mon erreur.

 

En fait dans mes fonctions ajouterRoyale et ajouterCampagnarde, je faisais un $this->listePizza[0]+=$nombre; alors que je n'avais pas initialisé $listePizza.

en déclarant ceci public $listePizza = Array("0", "0"); ou en testant si $listePizza est vide, mon problème est résolu.

 

Merci

 
Par Cyrano  -  Le 31/08/2011 14:12  -  Haut de page  - 

Presque.

Là j'ai pas trop le temps mais ce soir je te ferai quelques commentaires sur tes classses. Tu es bien parti, maintenant on va optimiser un peu tout ça en introduisant quelques concepts techniques qui, une fois mis au jour, vont te sembler évidents quant à l'optimisation générale.

À plus tard ;)

 
Par paintbox  -  Le 31/08/2011 14:40  -  Haut de page  - 

Ok j attends tes explications !

Merci

 
Par Cyrano  -  Le 31/08/2011 19:12  -  Haut de page  - 

Salut,

en fait j'ai réalisé que c'était bon. À ce stade, ce ne serait peut-être pas une bonne idée de commencer à te noyer dans des concepts tordus. Donc tel que c'est avec ta correction sur la déclarration de ta propriété de classe $listePizza, c'est très bienn.

 

Juste un truc quand même : évite autant que possible d'utiliser un echo() dans une classe. Une classe est faire pour manipuler des données et retourner ou non des valeurs à partir de ces données, il faut déléguer l'affichage à une autre partie. Tu pourrais avoir cependant une utilisation intéressante de la méthode magique __toString() : remplace ta méthode afficherCommande par ceci :

/**
     * Affichage de l'instance de la classe dans son état courant.
     *
     * @return String
     */
    public function __toString()
    {
        $affichage = 'Commande du client : '.$this->nomClient .
                     '<br />Pizza(s) Royale : '.$this->listePizza[0] .
                     '<br />Pizza(s) Campagnarde : '.$this->listePizza[1] .
                     '<br />Total de votre commande : '.$this->calculerPrix() .
                     ' Euros<br />';
        return $affichage;
    }

Ensuite, au lieu de faire « $client2->afficherCommande(); », fais un « echo($client2); » et... découvre pourquoi on appelle ça une méthode magique ;)

 

 
Par paintbox  -  Le 31/08/2011 22:23  -  Haut de page  - 

Hello Cyrano,

concernant le echo dans la classe, oui en effet j'avais aussi lu que c'était déconseillé, mais le tutos que j'ai trouvé procédait comme cela. Pas toujours évident d'avoir une bonne méthode quand on se base sur divers tutos péchés à gauche à droite. En tout cas je note que ce n'est plus à refaire!

Concernant la méthode magique hum je ne vois pas trop.

En cherchant sur le net, j'ai trouvé ceci :

"La méthode __toString détermine comment la classe doit réagir lorsqu'elle est convertie en chaîne de caractères."

Mais j'avoue que je ne vois pas de différence entre mon affichage et celui avec __toString(), ou alors quelque chose m'échappe sans doute.

 

Je vais essayer de traiter un formulaire de contact (methode POST) à l'aide de la POO, mais je suis un peu perdu. J'ai une vague idée que je vais appliquer.

 

Merci pour tes explications !

 

 

 
Par Cyrano  -  Le 31/08/2011 22:27  -  Haut de page  - 

La raison est simple : il n'y a plus de echo dans la classe elle même et tu gères l'affichage à l'extérieur, c'est pas plus compliqué que ça ;)

 
Par paintbox  -  Le 31/08/2011 22:44  -  Haut de page  - 

Ok, je voulais sans doute chercher trop loin. Et en effet je viens de tester :

 

public function afficherCommande()
            {
                $affichage = 'Commande du client : '.$this->nomClient .
                     '<br />Pizza(s) Royale : '.$this->listePizza[0] .
                     '<br />Pizza(s) Campagnarde : '.$this->listePizza[1] .
                     '<br />Total de votre commande : '.$this->calculerPrix() .
                     ' Euros<br />';
                return $affichage;
            }

 

et cela ne me retourne pas le même résultat qu'avec __toString()

 

Je viens de tester le formulaire. C'est basique dans un premier temps mais puis-je te demander ton avis sur la façon de faire? Est-ce la bonne méthode, il y a t-il mieux ?

 

Voici ma classe :

class monForm
    {
        private $nom;
        private $prenom;
        public function __construct($nom, $prenom)
            {
                $this->nom = $nom;
                $this->prenom = $prenom;
            }
        public function __toString()
            {
                $message = "Bonjour " .$this->nom.' , '.$this->prenom;
                return $message;
            }
    }

 

Et ma page avec mon formulaire :

<?php
include_once('monForm.class.php');
?>
<html>
    <body>
<?php
 if (isset($_POST['envoyer']))
    {
        $client = new monForm($_POST['nom'], $_POST['prenom']);
        echo $client;
    }
    else
    {
?>
    <form method="post" action="" name="monformulaire">
        <label>Nom : </label>
        <input type="text" name="nom" />
        <label>Prenom : </label>
        <input type="text" name="prenom" />
        <input type="submit" name="envoyer" value="Envoyer" />
    </form>
<?php
    }
?>
    </body>
</html>

 

Suis-je dans le bon? Est-ce que je fais bon usage de la POO de cette façon?

 

Merci pour ton avis

 
Par Cyrano  -  Le 31/08/2011 22:57  -  Haut de page  - 

DIsons que pour le moment, j'ai l'impression que tu es en phase d'exploration et la POO est un vaste domaine. L'important est d'obtenir le résultat voulu dans un premier temps.

Dans un second temps, l'idée des classe est de créer des systèmes de traitement génériques et réutilisables dans à peu près n'importe quelle application. C'est comme ça qu'on commence en général rapidement par se construire des classes pour l'accès aux bases de données, puis des classes de traitements de données par exemple pour valider des informations en provenance d'un formulaire, ou encore des classes qui permettent d'envoyer des courriels plus facilement qu'avec les simples méthodes natives du langage qui obligeraient à écrire plus de code.

Plus tard, on intègre les « Design Pattern » ou « Motifs de conception » qui sont des solution génériques à des problèmes récurrents dans la manière d'organiser les différentes classes entre elles.

Je ne sais pas si tu as fait une recherche du bouquin que je t'ai suggéré plus tôt, mais ce ne sera pas une perte de temps, d'autant moins si tu le trouve, et ce ne sera pas de l'argent jeté par les fenêtres si tu l'achètes, c'est une petite mine d'or qui te fera gagner bien du temps dans la compréhensions générale et dans certains cas bien particuliers de la POO. Autre bouquin pour aborder la POO en PHP5, c'est « PHP5 Avancé » de Cyril Pierre de Geyer et publié chez Eyrolles, le chapitre sur la POO est assez complet même si les exemples sont assez basiques, mais tu y verras tous les aspects fondamentaux et essentiels. Celui-ci est en revanche toujours disponible en librairie, il en est à la 5ième édition ce me semble.

 
Par paintbox  -  Le 02/09/2011 08:37  -  Haut de page  - 

Hello Cyrano,

 

en effet je suis encore en phase d'exploration. Je teste et j'essaie de voir l'usage que je peu faire de la POO. Comme je l'ai dit, je comprend le principe et le fonctionnement mais j'ai du mal à voir la POO en pratique, de "visualiser" des cas pratiques. Je cherche des exercices sur le net mais pas évident d'en trouver.

Le premier libvre que tu m'as recommandé a l'air effectivement très bien. Malheureusement comme tu le craignais, il est épuisé sous format papier. Je vais encore voir si je n'arrive pas à en dénicher un, je voudrais éviter le format PDF moins agréable à consulter.

Merci

A+

 

 
Par paintbox  -  Le 02/09/2011 12:34  -  Haut de page  - 

Hello Cyrano,

j'aurais besoin une fois de plus de tes coseils sur la bonne façon d 'utiliser "l'héritage". Je suis toujours dans la phase apprentissage et tests. Je test l'héritage.

Voici mon problème j'ai créé une class parent "animaux" dont les attributs sont $nbpates et $nbyeux.

J'ai 2 autres classes enfants "chat" et "chien".

Mon soucis est que j'ai eu du mal a définir les attributs "parent" et "enfants".

Pour info, j'avais d'abord créé un constructeur pour la classe parent ($nbpates et $nbyeux) et un constructeur pour la class chat pour l'attribut $crichat. Je n'arrivais pas à attribuer des valeurs aux différents attributs de chacun. J'ai donc créé un seul constructeur pour chat qui attribue les 3 attributs.

Je voudrais tes conseils sur la bonne manière de faire.

 

Voici mon code :

class animaux
    {
        // Declaration des attributs
        public $nbpates;
        public $nbyeux;
        // Constructeur
        //public function __construct($nbpates, $nbyeux)
        //    {
        //        $this->nbpates  = $nbpates;
        //        $this->nbyeux   = $nbyeux;
        //    }
    }

 

 

Mes class chat et chien :

class chat extends animaux
    {
        // Declaration des attributs
        private $crichat;
        // Constructeur
        public function __construct($nbpates, $nbyeux, $crichat)
            {
                $this->nbpates  = $nbpates;
                $this->nbyeux   = $nbyeux;
                $this->crichat  = $crichat;
            }
    }

 

 

class chien extends animaux
    {
        // Declaration des attributs
        private $crichien;
    }

 

Merci

 
Par Cyrano  -  Le 02/09/2011 14:30  -  Haut de page  - 

Ok, alors en résumé, le principe de déclinaisons de classes héritant les unes des autres consisteà partir du plus générique vers le plus spécifique. Comme tu l'as compris, et comme tes classes le reflêtent bien, les animaux ont des points communs et des points quileurs sont propres. Il faut donc arriver à déterminer ce qui est réellement générique du reste et voir éventuellement ce qui est commun dans leurs spécificités.

Lorsqu'on crée ce genre de montage, on va souvent utiliser une « Super-classe » parente et une interface où on va définir les méthodes des classes qui héritent de la super-classe. En arrière-plan, tu verras peut-être apparaître l'idée de polymorphisme. Lorsque tu crée un objet, il a un certain type, mais lequel : celui de la classe héritant ou de la super-classe ? Les deux, mais pour des questions de bonnes pratique, on se basera sur le type de la super-classe. On pourra alors utiliser les mêmes méthodes que l'objet soit « chien » ou « chat »

Mais lorsque tu définis les propriétés d'un chien ou d'un chat, ta manière de faire ici n'apporte pas grand chose : tu es obligé de préciser lorsque tu crée ton instance les valeurs de ces propriétés : du coup, tu n'as en réalité plus besoin des sous-classes. Pour corriger le tir, dans la mesure ou tes sous-classes sont déjà spécialisées, tu peux pré-définir les valeurs de ces propriétés dans les sous-classes elle-mêmes. Ce qui par contre changera, c'est surtout au niveau des méthodes dans leur implémentation. Les méthodes seront les mêmes pour toutes les sous-classes, mais l'implémentation dépendra de la sous-classe spécifique.

Revoyons tes classes et voyons comment les exploiter :

<?php
abstract class animaux
{
    protected $animal;
    protected $nbpates;
    protected $nbyeux;
    protected $cri;
    public function jesuis()
    {
        return "Je suis ". $this->animal;
    }
}
class chat extends animaux
{
    public function __construct()
    {
        $this->animal  = 'un chat';
        $this->nbpates = 4;
        $this->nbyeux  = 4;
        $this->cri     = 'Miaou !';
    }
}
class chien extends animaux
{
    public function __construct()
    {
        $this->animal  = 'un chien';
        $this->nbpates = 4;
        $this->nbyeux  = 4;
        $this->cri     = 'Wouaff !';
    }
}
class mouche extends animaux
{
    public function __construct()
    {
        $this->animal  = 'une mouche';
        $this->nbpates = 6;
        $this->nbyeux  = 2;
        $this->cri     = 'Bzzzz !';
    }
}

Première observation : on ne crée jamais directement d'instance de la classe animaux : on va donc la déclarer abstraite. Les propriétés et méthodes qui s'y trouveront seront le plus souvent protégées et devront être redéfinies dans les sous-classes.

Lorsque je crée un objet chien, je n'ai nul besoin de préciser les valeurs de ses propriétés, c'est directement dans le constructeur spécifique. Ce qui nous intéresse par contre, c'est d'avoir des méthodes pour récupérer les valeurs de ces propriétés.J'ai donc mis une méthode publique jesuis() qui retourne l'identité de l'animal, identité que je définis dans le construteur de la sous-classe.

Pour être sur que toutes mes classes ont bien les mêmes méthodes, en marges des méthodes publiques directement héritées de la super-classe et les implémentent, on a deux possibilités:

  1. ajouter une interface qu'implémenteront toutes les sous-classes.
  2. Créer des méthodes protégées dans la super-classes qui devront être redéfinies dans les sous-classes.

On va prendre la seconde solution,

Ajoutons une méthode crier dans la super-classe, mais cette fois on mettra une méthode protégée.

abstract class animaux
{
    protected $animal;
    protected $nbpates;
    protected $nbyeux;
    protected $cri;
    public function jesuis()
    {
        return "Je suis ". $this->animal;
    }
    abstract protected function crier();
}

Maintenant, jouons un peu avec nos objets :

$oChien     = new chien();
$oChat      = new chat();
$oMouche    = new mouche();
echo("<p>". $oChien->jesuis() ."</p>\n"); // Affiche : Je suis un chien
echo("<p>". $oChat->jesuis() ."</p>\n"); // Affiche : Je suis un chat
echo("<p>". $oMouche->jesuis() ."</p>\n"); // Affiche : Je suis une mouche

Jusque là, tout va bien. Si maintenant il me prenait la fantaisie d'appeler la méthode crier, j'aurais un problème :

echo("<p>". $oChien->crier() ."</p>\n");

Le résultat est simple :

Fatal error:  Class chat contains 1 abstract method and must
therefore be declared abstract or implement the remaining methods
(animaux::crier) in D:\www\_Temporaire\_tmp\PaintBox\heritage.php on line 31

Normal, ma méthode est protégée et surtout abstraite, donc accessible seulement dans la classe où elle est définie ou dans les classes héritées. Comme elle est abstraite, on doit impérativement implémenter les comportements spécifiques dans les sous-classes. Note que la méthode abstraite n'a pas de corps, donc pas de « {} », expérimente et ajoute des acoolades et exécute le code, tu vas voir ce que ça donne. Modifions la classe chien :

class chien extends animaux
{
    public function __construct()
    {
        $this->animal  = 'un chien';
        $this->nbpates = 4;
        $this->nbyeux  = 4;
        $this->cri     = 'Wouaff !';
    }
    public function crier()
    {
        return($this->jesuis() ." : ". $this->cri);
    }
}
// Appelons maintenant la méthode crier :
echo("<p>". $oChien->crier() ."</p>\n"); // Affiche : Je suis un chien : Wouaff !

Voilà, ça va te donner de quoi méditer un moment avec ces éléments. Essaye de bien discerner et regarde la documentation sur les interfaces, tu vas peut-être découvrir qu'il serait plus intéressant dans le cas présent d'ajouter une interface et pourquoi ;)

 

 

 
Par paintbox  -  Le 02/09/2011 16:00  -  Haut de page  - 

 

Ok, je comprends mieux comme ceci. Mais je crois que je commence un peu a saturer niveau POO.

J'ai compris tes explications, mis à part 2 choses :

 

1° Je ne saisi pas trop pourquoi déclarer une méthode abstract dans animaux alors qu'on va devoir de toute façon la redéclarer dans chat, chien et mouche. On est obligé de le faire dans les 3 puisque elle est en abstract dans animaux.

 

2° si je souhaite ajouter un attribut à la class chat mais que la valeur de cet attribut dépendera de ce que l'utilisateur entrera. Exemple bidon : si je déclare un attribut $couleur qui sera vide dans ma class chat et que je demande à l'utilisateur la couleur du chat.

La solution à laquelle je pense, est de passer en paramètre la couleur au constructeur dans la class chat.

comme ceci:

 

class chat extends animaux
{
    public $couleur;
    public function __construct($couleur)
    {
        $this->animal  = 'un chat';
        $this->nbpates = 4;
        $this->nbyeux  = 4;
        $this->cri     = 'Miaou !';
        $this->couleur = $couleur;
    }
   public function crier()
    {
        return($this->jesuis() ." : ". $this->cri);
    }
  public function couleur()
    {
        return ( $this->animal.' est de couleur '.$this->couleur);
    }
}

 

 

Cela fonctionne, mais est-ce la bonne méthode et est-ce propre ?

En fait si j'inciste sur le fait d'avoir un attribut dont la valeur est définie par l'utilisateur c'est dans le cas dans formulaire.

Si on a un formulaire contact identique pour les particulier et les entreprises, on pourrait donc avoir une Super-Classe Client avec les attributs $nom, $adresse puis avoir une Sous-Classe Particulier et une autre Entreprise avec chacune des attributs propres. Je viens de faire des recherches sur les interfaces. J'ai trouvé l'interface Iterator. Je laisse cela pour l'instant de côté mais je compte bien y revenir ;-)

 
Par Cyrano  -  Le 02/09/2011 17:18  -  Haut de page  - 

Ok je vois :

Une méthode abstraite présente un avantage, à première vue une entrave mais c'est loin d'être le cas, en obligeant à redéfinir la méthode dans la sous-classe. C'est pour le coup une bonne pratique qui prend tout son sens lorsqu'on travaille à plusieurs. Si un des développeur de l'équipe doit développer la classe poissonrouge, il devra obligatoirement définir une implémentation à cette méthode en retournant par exemple « Je n'ai pas de cri, je suis dans l'eau bande de neuneus ! » et personne n'aura une erreur fatale à cause d'une méthode pas définie du tout. C'est une forme de programmation par contrat : une des clause du contrat est « Tu dois implémenter cette méthode ». C'est aussi pour une question d'homogénéité globale du code.

Ajouter un attribut propre à une seule classe : rien ne l'interdit, mais dans ce cas, il sera préférable de passer par une méthode setAttribut($attr, $valeur) et alimenter une propriété qui sera par exemple un tableau. Rien n'indique que tu ne devra pas un jour développer une nouvelle sous-classe qui nécessitera également cette fonctionnalité : donc il vaut mieux anticiper, et définir la manière de rajouter des éléments de façon homogène.Pour bien faire il faudrait que je te recopie deux ou trois des chapitres du bouquin mentionné plus tôt parce que ce serait encore plus clair et basé sur des exemples homogènes.

L'idée client /particulier/entreprise à la base n'est pas une mauvaise idée, pourtant à l'usage tu réaliseras que c'est pourtant moins heureux comme solution parce que tu ne discute pas avec une entreprise mais avec son représentant qui est ... un particulier, et en fin de compte une entreprise est composée de 1 à n particuliers, et je dirais que c'est un problème que j'ai eu à me poser puisque je patauge précisément là-dedans depuis pas mal de temps : je suis sur la construction d'un outil qui doit justement traiter des problèmes du genre avec des clients qui peuvent être soit des particuliers soit des entreprises.

Mais pourtant je n'ai développé aucune classe client ni aucune classe entreprise dans mon code métier. Attention quand même à un point : PHP n'est pas Java ou C++, ce n'est pas un langage Full Objet et ce n'est pas forcément une bonne idée de vouloir tout faire un objet même si ce serait relativement faisable. Les classes que j'ai du développer par contre et dans lesquelles j'ai du mettre en pratique un certain nombre de ces concepts, c'est pas exemple mon système de gestion de formulaires ou encore mon système d'accès aux bases de données, packages complexes dans leur construction, mais qui me simplifient à l'extrème la gestion des formulaires ou de la manipulation de données dans mon code métier en limitant à assez peu de méthodes à connaître.

Et il faut distinguer ce qui est librairies de ce qui est code métier. Les librairies, ce sont des classes ou du code qui sont suffisamment génériques pour pouvoir être utilisés dans n'importe quelle application sans qu'on doive en changer une virgule, alors que le code métier, c'est le code spécifique à une application donnée parce qu'elle traite des problèmes qui lui sont propres. L'application peu être un blog, un outil de gestion de factures, un forum, un site d'agence immobilière et que sais-je encore. Tous sont différent, mais tous peuvent s'appuyer sur certaines librairies qui sont strictement identiques.

C'est là que la POO est intressante, bien pratiquée, elle homogénéise la manière de traiter des problèmes récurrents qu'on peut retrouver sous différentes formes. Et le grand art dans la conception objet, c'est que si le développement est générique et extensible, tu peux devoir étendre certaines classes trop génériques pour spécialiser davantage certains traitements pour tes besoins métier. Ainsi, je me suis écrit une classe qui étend Zend_Pdf parce que j'avais besoin de créer des documents d'une certaine manière : je ne me suis pas pris la tête à ré-écrire la classe Zend_Pdf, elle fait très bien ce qu'elle m'apportait, mais trop généraliste pour mon besoin, je l'ai simplement étendue en faisant hériter ma propre classe de Zend_Pdf.

Est-ce que ça répond à tes interrogations ?

 
Par paintbox  -  Le 02/09/2011 17:45  -  Haut de page  - 

Oui c'est déjà plus claire. Je crois que j'essaie d'adapter la POO à tous les cas ce qui visiblement n'est pas toujour nécessaire. Je dois arriver à identifier les situations pour lesquelles c'est nécessaire.

Je crois que cela viendra avec la pratique.

Je mets cela un peu de côté et vais m'y remettre d'ici peu.

Merci encore pour tes excellentes explications !

 

Ajouter une réponse à la discussion

Seuls les membres connectés sont autorisés à poster dans les forums !

Identifiez-vous
Join |  ID/MDP? |