Artchitecture POO et optimisation SQL

Petit nouveau ! | 6 Messages

07 oct. 2009, 13:57

Salut,

Je pose le problème ici car je développe en PHP, mais il concerne plus particulièrement la manière d'aborder le problème. Le concept, donc.

Pour expliquer mon propos simplement, je propose de prendre un exemple simple. imaginons que je dispose d'une table contenant des articles, et deux classes pour les gérer correctement.

Je vais au plus simple, je passe certains constructeurs, certaines vérifications de données, ainsi que la définition de certaines méthodes.
class Catalogue
{
 
protected $db;
 
public function creerArticle() { }
 
public function getArticlesByUser($username)
{
 
   $articles = array();
 
   $this->db->query('SELECT article_id, ... FROM article WHERE username = ...');
 
   while ( $d = $db->fetch_assoc() )
   {
      $articles[] = new Article($d);
   }
 
   return $articles;
 
}
 
 
public function getArticlesByCategorie($username) { }
 
... 
 
}
 
 
class Article()
{
 
protected $id;
protected $name;
...
 
function __construct($mixed)
{
   if ( is_int($mixed) )
   {
      $this->db->query('SELECT article_id, ... FROM article WHERE id= ...');
      $mixed = $db->fetch_assoc()
   }
   $this->id = $mixed['article_id'];
   $this->name = $mixed['article_name'];
}
 
public function supprimer() { }
 
public function getName() { }
 
...
 
}
En gros, c'est le principe, avec des contrôles sur l'intégrité des données en plus.


Le problème... Dans un soucis d'économiser les requetes SQL au nécessaire (et donc de ne pas charger tous les articles), le code devient vite crade, et ne respecte pas forcement les concepts de la POO. Du moins, la class Catalogue pourrait être static, ça ne changerait rien, et les arguments ne sont pas passés proprement à la class Article. Cependant, laisser la classe Article faire une requete SQL pour charger les données chaque article n'est pas envisageable !

Autre soucis, au niveau de la redondance SQL. Rien ne m'empeche de charger plusieurs fois un même objet (par exemple, si je fais un new Article(6) suivit d'un second new Article(6), 2 requetes SQL seront créées). de même si je fais un new Article(8) alors que cet article a déjà été chargé lors de l'appel de getArticlesByUser('toto') par exemple.

J'avais imaginé détourner le principe du sigleton (par exemple, un tableau static contenant plusieurs instances, selon l'ID de l'article), mais ça s'éloigne beaucoup trop du concept de la POO.

Bref, si vous avez des conseils sur l'architecture à adopter, ou même des mots clés à me donner pour faciliter mes recherches Google, ça m'aiderait beaucoup.

Merci d'avance.

Mammouth du PHP | 983 Messages

21 oct. 2009, 23:07

Il y a plusieurs façons de faire en fonction de la taille du projet, du nombre d'utilisateurs potentiels, du but visé (apprendre, faire quelque chose qui marche...) :
  • - Active Record pour la gestion des CRUD
    - DAO : DAta Access Object
    - Passer par un ORM (Object Relational Mapper), style Doctrine
Le principe général, c'est que tes objets métier (Catalogue, Article) ne doivent pas avoir trop de responsabilités, et pour les puristes de l'objet, ils ne devraient avoir aucune autre responsabilité de d'être des conteneurs de données ( POJO en Java par exemple).

Eléphanteau du PHP | 22 Messages

01 nov. 2009, 13:56

moi j'aime bien utiliser une classe static data access par business object qui est chargée de tout l'sql, avec une classe manager qui a la responsabilité de créer/sauver les objets et faire d'autre trucs... comme l'a dit rami les business objects meme n'ont pas trop de reponsabilité, de meme, la classe data access ne contient pas trop de logique non plus, ça c'est la classe manager qui fait ca...

si tu es interessé je pourrais t'envoyer quelques classes par mail.

Eléphant du PHP | 369 Messages

01 nov. 2009, 14:23

Salut,
[...]
J'avais imaginé détourner le principe du sigleton (par exemple, un tableau static contenant plusieurs instances, selon l'ID de l'article), mais ça s'éloigne beaucoup trop du concept de la POO.
Tu veux sans doute parler de multitons.
Tu peux aller encore plus loin en utilisant les méthodes crud.

Sans rapport: regarde du côté PDO ca peut t'interresser.

C'était juste une piste, bon code @+ ;)

Mammouth du PHP | 985 Messages

01 nov. 2009, 14:47

Je dirais surtout PDO avec des requêtes préparées.
Outre le côté sécurité, cela permet surtout à la base de faire un minimum de requêtes pour un maximum d'opérations sur une Bd Mysql...
http://php.net/manual/fr/pdo.prepare.php
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.