Questions de compréhension !

daveref Messages postés 1 Date d'inscription jeudi 11 novembre 2010 Statut Membre Dernière intervention 11 novembre 2010 - 11 nov. 2010 à 09:47
syndrael Messages postés 2378 Date d'inscription lundi 4 février 2002 Statut Membre Dernière intervention 29 décembre 2012 - 12 nov. 2010 à 10:39
Bonjour à Tous,

J'aimerai avoir quelques éclaircissements concernant l'usage de la POO.

Je souhaite développer une petite application pour me mettre dans le bain.

Par contre, les concepts de POO ne sont pas encore vraiment clairs pour moi et les tutos présents sur Internet traitent généralement de création de classes, attributs, héritage...

Ma réflexion se porte d'abord sur l'analyse.
Je ne cherche en aucun cas à bénéficier de script déjà fait.

Voici quelques questions que je me pose avant de commencer. Si quelqu'un peut m'orienter et me conseiller par rapport à son expérience, ça serait génial :)

Imaginons un site où des internautes peuvent se connecter pour consulter des livres et les informations s'y rapportant (auteur, description...). Certains peuvent également ajouter des livres.

- Dans un premier temps, je vois 2 classes :

- Class User
- Class Livre

1) Première question : Doit-on pour un projet créer un objet "Application" ou "Site" comportant toutes les variables de l'application (ex : url du site, variables de configuration...)

2) Pour la class User, je créerai des attributs (nom, prénom) et méthodes classiques
(ajout utilisateur, suppression utilisateur, connexion utilisateur...)

Par contre, j'ai vraiment du mal à à savoir si cette classe doit posséder une méthode permettant de lister tous les utilisateurs dans la base ou si cette méthode doit se trouver dans la class Application ou créer une class Users

Le problème se pose également pour la class livre.


3) Concernent la class User, généralement on voit les attributs classiques définis (nom, prenom...)
Par contre, il est rare dans une appli que le nombre d'attributs pour un user soit définie une fois pour toute.
Est-il possible d'avoir un tableau d'attributs à la création de l'objet ?
J eme pose cette question dans la cas où j'aurai des attributs dynamiques stockées en bas de données.

Ex: J'aurai une table caractéristiques (id_user,nom, valeur) pour un user.
Dans cette table, 2 enregistrements :

1, nom, 'Dupont'
1, prenom, 'David'

Comment charger ses attributs à la création de l'objet ?
Doit-on toujours avoir des attributs définis dans un objet ou peux-t-on avoir un seul attribut "caractéristiques" (tableau) qui récupérerait tous les attributs dans le constructeur ?

C'est vraiment basique comme questions mais j'ai vraiment besoin d'avoir vos avis pour avancer.


Merci pour vos réponses.

2 réponses

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
11 nov. 2010 à 19:29
Salut,

Tu te poses des questions légitimes. Mais la vérité est ailleurs...

1) Doit-on pour un projet créer un objet "Application" ou "Site" comportant toutes les variables de l'application

Non, on ne "doit" pas. Mais on peut.
En fait, si c'est utile pour toi, alors fais-le. Tu as le droit : la POO n'est qu'un outil, à toi de l'utiliser comme bon te semble.

Pour prendre les deux exemples que tu cites entre parenthèses, URL du site, variables de configuration... Pour ma part, j'utilise une classe statique Config qui a pour rôle de charger des fichiers de config et de retourner les variables définies dans chaque fichier. J'ai donc plusieurs fichiers de configuration : un pour la base de données, un pour les sessions, un pour les cookies (dont certaines valeurs vont croiser celles des sessions), un pour le site (config générale), etc.
Comme elle est pas bien grosse, voici son code :

<?php
class Config {

private static $configurations = array();
private static $core;

public static function loadCore() {
$coreConfigFile = ROOT.'/core.cfg.php';
if (!is_file($coreConfigFile)) {
throw new Exception(sprintf('Could not load core configuration. '.
'Please make sure that %s exists and is a regular file',
$coreConfigFile));
}
self::$core = new ArrayObject(require $coreConfigFile, ArrayObject::ARRAY_AS_PROPS);
}

public static function load($configName) {
if (!self::isLoaded($configName)) {
$configFile = self::$core -> appPath.'/config/'.$configName.'.cfg.php';
if (is_file($configFile) && is_readable($configFile)) {
$cfg = require $configFile;
foreach ($cfg as $k => $v) {
if (is_array($v)) {
$cfg[$k] = new ArrayObject($v, ArrayObject::ARRAY_AS_PROPS);
}
}
self::$configurations[$configName] = new ArrayObject($cfg,
ArrayObject::ARRAY_AS_PROPS);
return TRUE;
}
else {
throw new Exception(sprintf('Could not load %s configuration. '.
'Please make sure %s exists and is readable.',
$configName, $configFile));
}
}
}

public static function isLoaded($configName) {
return isset(self::$configurations[$configName]);
}

public static function get($configName) {
if (self::isLoaded($configName) || self::load($configName)) {
if (isset(self::$configurations[$configName])) {
return self::$configurations[$configName];
}
}
}

public static function __callStatic($name, $args) {
if (isset(self::$core[$name])) {
if (array() === $args) {
return self::$core[$name];
}
}
}

}
?>


Pour fonctionner, elle a besoin au minimum d'un fichier core.cfg.php situé à la racine de l'application (définie dans la constante ROOT). Il ressemble à ça :
<?php

return array(
/**
 * Relative path to application directory, from yaf-php
 * You may also use an absolute path
 */
'appPath' => realpath('../application'),

/**
 * Default timezone
 */
'timeZone' => 'Europe/Paris',

/**
 * Language
 */
'locale' => 'fr_FR.utf8',

/**
 * Display 404 Error when no controller found
 * If set to FALSE, display home page
 */
'controllerError404' => TRUE,
);

?>


En gros, le fichier retourne un tableau associatif clé=>valeur (chaque valeur pouvant être un tableau de la forme que l'on souhaite).
L'utilisation :
Config::appPath();

renvoit la variable de config appPath définie dans core.cfg.php. D'une manière générale, l'appel à une méthode statique non définie renvoit la variable de configuration dans le fichier core.cfg.php

Config::get('db');

retourne la configuration correspondant au fichier db.cfg.php situé dans le répertoire appPath.
Les configurations sont des ArrayObjects, ce qui permet d'appeler les variables de configuration comme des propriétés :
echo Config::get('db') -> hostname;

renvoit le nom d'hôte du serveur de base de données

2) j'ai vraiment du mal à à savoir si cette classe doit posséder une méthode permettant de lister tous les utilisateurs dans la base ou si cette méthode doit se trouver dans la class Application ou créer une class Users


Là encore, c'est comme tu veux. Techniquement, ce ne serait pas très cohérent de lister plusieurs utilisateurs dans la classe User. Tu peux le faire dans une classe Application, ou avoir une classe Users (que j'appellerais plutôt UserCollection pour éviter les erreurs dûes à l'oubli du S).
La classe UserCollection pourrait alors être un itérateur qui renverrait, à chaque itération, une instance de User.
Tout dépend si tu as VRAIMENT besoin de tous les attributs d'un utilisateur quand tu vas les lister.

3) Par contre, il est rare dans une appli que le nombre d'attributs pour un user soit définie une fois pour toute.

Ta vision des choses est, à mon sens, erronnée.
Il faut différencier l'état d'une application dans une version donnée et son état au fil du temps.
Evidemment, une application évolue. Dans la première version, un User va avoir des attributs donnés, relativement basiques. Plus tard, tu voudras rajouter des fonctionnalités, et tu ajouteras de nouveaux champs dans la table des membres. Ca fait partie de la vie de l'application, et donc du développement.
La classe que tu vas écrire doit être fonctionnelle pour une version donnée : tu as donc un nombre d'attributs qui n'est pas censé évoluer. Quand, dans la version suivante, tu rajouteras des champs dans la table, tu rajouteras également les attributs dans la classe (ou pas, à voir avec l'alternative que je présente plus loin). Rajouter des atributs, ça fait partie du développement au même titre que rajouter des champs dans la table. Si tu crées une nouvelle table, tu écriras peut-être une nouvelle classe : tu ne vas pas avoir une seule classe qui gère toutes les tables dynamiquement, non ? Ben pour les champs/attributs, c'est pareil... Ou pas.
Tu peux tout à fait stocker les attributs dans un tableau associatif et avoir un getter et un setter pour accéder au tableau (typiquement, j'utilise les méthodes magiques __get() et __set()).
Mais voici comment je fais plus précisément.
J'ai une classe abstraite DbObject (peu importe son nom). Chaque objet qui est une matérialisation d'un enregistrement d'une table sera une instance d'une classe étendant DbObject. Cette classe DbObject me permet de définir des méthodes génériques, qui sont les mêmes pour tous (User, Book, Article, etc) et qui me permettent notamment de gérer dynamiquement les champs que je souhaite charger lors des requêtes SELECT.
Par exemple, quand un utilisateur se connecte au site, les informations dont j'ai besoin sont : son niveau utilisateur (permissions)... et c'est à peu près tout. Quand il affiche la page d'acceuil, s'il est connecté, j'ai besoin de son pseudo pour lui dire bonjour, de la langue définie dans ses préférences (pour qu'il comprenne quand je lui dis bonjour), de son fuseau horaire (pour savoir si je dois pas plutôt lui dire bonsoir), etc.
Quand il est sur l'édition de son profil, j'ai besoin de tous les champs de son profil. Etc, etc.
Ma classe DbObject possède donc une méthode addField() qui me permet de définir les champs à récupérer dans ma requête SELECT.

C'est un vaste sujet : tu peux t'intéresser aux ORM (Object Relational Mapping) comme Doctrine, Propel, ou ceux inclus dans les frameworks comme Zend, Kohana, etc). Moi, je fais un truc qui n'est pas tout à fait de l'ORM ni du DAO ni complètemen du CRUD : je m'adapte en fonction de mes besoins, de ce ma manière de coder, etc...

Pour la classe Livre, c'est un peu pareil : sur certaines pages tu auras besoin de très peu d'informations sur chaque livre (résultats de recherche, liste en homepage, etc), sur d'autres, il t'en faudra beaucoup plus (un peu plus sur la page de détails d'un livre, tous les champs dans l'admin). A toi d'écrire les objets dont tu as besoin en fonction de ton site, comment il est structuré, etc.


Tout ça pour dire qu'il n'y a pas de vérité absolue : la POO n'est qu'une approche de développement, une manière d'organiser et structurer son code. Elle n'est pas implémentée de la même manière suivant les langages. C'est juste un outil qui permet de faire des choses... A chacun de l'utiliser comme il le souhaite en fonction de ses besoins et de ses contraintes.

Une chose importante : la base de données est LE pilier de ton site internet, il est important et même primordial de la concevoir avant de penser à tes objets, qui ne seront que le reflet de la base, des entités que tu manipuleras.
Tu peux avoir besoin de créer autant de classe qu'il y a de tables. Ce ne sera peut-être pas utile. Tout dépend comment tu te sens à l'aise avec tout ça...

J'espère que tout ce blabla te sera utile ;)

--
Neige

Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)
0
syndrael Messages postés 2378 Date d'inscription lundi 4 février 2002 Statut Membre Dernière intervention 29 décembre 2012 20
12 nov. 2010 à 10:39
je confirme.. bla bla utile et très bien détaillé.
S.
0
Rejoignez-nous