passage de la modélisation à l'implémention : indépendance des classes

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 : passage de la modélisation à l'implémention : indépendance des classes

par d0m » 24 mai 2008, 16:24

merci pour l'exemple, comme tu dis ca marche mieux que plusieurs lignes d'explications.

Merci à vous 2 pour vos réponses. :pouce:

par zeus » 24 mai 2008, 15:48

Non, pas tout à fait.

Le principe est de faire en sorte que chaque classe contienne la liste des champs de la table correspondante (classe Film pour table Film, classe Réalisateur pour table Réalisateur, ...)

Quand tu charges une instance de la classe Film, tu commences par construire ta requête en posant les champs de la table Film, puis ton continue en posant les champs de la table liées.
Mais comme un exemple est plus parlant qu'un grand discours :
class Film
{
	protected $id_film;
	protected $a_acteurs;
	protected $realisateur;
	
	// Liste des champs de la table associée
	const a_champs_db = array( 'id_film', 'titre', 'annee', 'id_realisateur' )
	const table_name = 'Film';
	
	public function loadFromDb($o_db, $id_film)
	{
		$str_liste_champ = '';
		
		// Liste des champs présents dans le SELECT, des tables présentes dans le FROM et des clauses WHERE
		$a_select 	= self::a_champs_db;
		$a_from 	= array(self::table_name);
		$a_where 	= array('id_film='.$id_film);
		
		// Ajout des champs, de la table et des clauses provenant de la table Réalisateur
		$a_select 	= array_merge($a_select, Realisateur::getFields());
		$a_from[] 	= Realisateur::table_name;
		$a_where[] 	= self::table_name .'.id_realisateur = '. Realisateur::table_name .'.id_realisateur';
		
		
		// Construit le SELECT à partir de la liste des champs de la table
		$str_select = implode($a_select, ', ');
		$str_from 	= implode($a_from, ', ');
		$str_where 	= implode($a_where, ' AND ');
		
		$str_requete = sprintf( 'SELECT %s FROM %s WHERE %s',
								$str_select,
								$str_from,
								$str_where);
	}
	
	/**
	 *  Méthode statique permettant de récupérer la liste des champs de la classe
	 */
	public static function getFields()
	{
		return self::a_champs_db
	}
}
Pour ne pas te faire tout le boulot, je n'ai pas fait la partie qui doit récupérer les champs propre à la table Réalisateur, et je n'ai pas fait la méthode hydrate() qui prend la liste des champs et qui hydrate un nouvel objet Realisateur.

Quand tu changes la structure d'une table, tu n'as qu'a mettre à jour les champs dans la table liée

par d0m » 24 mai 2008, 14:27

ok merci.

Dans tous les cas si je veux préserver l'idépendance entre classe le plus possible il faudra sacrifier l'optimisation des requetes SQL pour rendre tout ça le plus modulaire possible, c'ets à dire
- aller chercher les infos du film dans la base
- puis aller chercher les infos des réalisateurs correspondants aux films pour chaque film
- puis pareil pour les acteurs?
c'est bien ça?

il manque l'implémentation possibles de plusieurs constructeurs comme en java....

par zeus » 24 mai 2008, 14:16

Alors, soit tu le fait à la "manière propel", c'est à dire que la classe Realisateur dispose de la liste des champs de la table en paramètres et dispose d'un accesseur qui te retourne cette liste.
De plus, elle propose une méthode "hydrate" qui prend un tableau sous la forme ("nom_champ" => "valeur")

Du coup, dans la classe Film, tu récupères la liste des champs, tu construit ta requête normalement, ensuite, tu ajoutes chaque champs de la table Réalisateur à l'aide de la liste récupérée de la classe.
Lorsque tu parses les résultats, il ne te reste plus qu'a récupérer les données du réalisateur et appeler la méthode hydrate pour le charger.

par Berzemus » 24 mai 2008, 13:29

c'est que j'ai lu un bouquin java l'autre jour.. c'est beau, mais c'est trop :sick:

par d0m » 24 mai 2008, 13:21

je voyais ça comme Zeu$.

Okay pour les accesseurs, c'est déjà en place.

Par contre donnons un exemple concret :

je faire la liste de tous les films avec les acteurs et le realisateur.

j'ai pour ça une fonction membre:
function public selectionner_films($connexion){
  $les_films = array();
  $resultat = $connexion->query(	"SELECT id,titre,id_realisateur,annee_sortie FROM films");
  while ($obj = $resultat->fetch_object()){
    //ici
  }
à l'emplacement ici je dois construire une instance de la classe film or pour cela il faut que je construise un objet de la classe realisateur avant pour le passer en paramètre du constructeur de Film.
Ce qui implique que dans la classe Film , j'utilise un constructeur de la classe realisateur et rend donc dependant la classe film de la classe realisateur.
Imaginons que plus tard j'ajoute des données personnelles au réalisateur (date de naissance,etc...) il faudra alors que je modifie la fonction de la classe Film.

Je ne vois pas comment remedier à cela peut être en construisant un film sans realisateur et en l'ajoutant par la suite? De même pour les acteurs.

@berzemus : je trouve aussi que c'est de l'abus de POO.
le type tableau est fait pour ça, contenir une "liste" d'objets de même nature et donc là je trouve approprié qu'un film contienne une liste d'acteurs. Bien sur il y a des fonction pour ajouter des acteurs, en supprimer en selectionner etc.. pour rendre cela plus fonctionnel.

par zeus » 24 mai 2008, 13:05

Je pense que tu vas un peu trop loin dans la logique POO.

La notion de Film inclu la notion de Réalisateur et d'Acteur. Il me semble donc normal que l'objet Film ait des objets Réalisateur et Acteur en interne, sans passer par une autre classe.

Par contre, là où je te rejoins, c'est que l'utilisateur ne devrait pas voir qu'il s'agit d'un tableau d'objet, il faut donc que tu mettes à disposition des accesseurs/mutateurs pour les "sous-objets".

Edit : je répondais à Berzemus, bien entendu ;)

par Berzemus » 24 mai 2008, 12:38

alors.. du côté DB, ça me semble bien normalisé, (y'a jamais plus d'un réalisateur par film?), donc c'est bon.

Pour ce qui est de tes classes.. un objet réalisateur, OK, ça c'est bon (donc une classe qui gère l'accès aux données "réalisateur".

Pour les acteurs, un tableau, c'est vrai que çà heurte. On est tout à coup dépendants de la structure des données (un tableau), et on manipule un tableau et non pas un objet. (on peut se demander ou se situe le problème la dedans, mais bon, c'est pas la poo lifestyle). Il te faut donc un objet acteurs.

Et pour faire bien, puisque l'on dit bien qu'un doit éviter de donner trop de rôles à un même objet, il faudrait rendre l'objet film indépendant, et en faire un 4ème qui se contentera de lier les 3: film, acteur et réalisateur. Ainsi, si un jour tu dois encore ajouter une table, un objet, tu n'auras pas à modifier film, acteur ou réalisateur, mais uniquement l'objet qui s'amuse à les réunir. Il faudra bien que l'interfacage entre ce 4ème objet et les 3 autres se fasse au niveau "objet", c'est à dire sans être influencé par la structure des données de leur contenu (prévoir un itérateur), ça facilite la maintenance, et c'est tout à fait POO lifestyle..

Enfin, il me semble.

passage de la modélisation à l'implémention : indépendance d

par d0m » 24 mai 2008, 11:01

bonjour,

je me frotte à un problème avec la POO.
Le problème se situe au moment de passer du modèle à l'implémentation :

prenons l'exemple de d'un videothèque.
il y les objets films, acteurs, realisateur
la base de données contient une table pour chacun avec :
- la table film contient l'id d'un realisateur en plus de son id, son titre,etc...
- un table de relation entre les films et les acteurs

En PHP5, je crée les classes film, acteur, realisateur.

C'est là que j'hésite :
ma logique en POO me dirais de mettre comme donnée membre au film :
- un entier id
- une chaine titre
- un objet de type réalisateur
- un tableau d'objet de type acteur

en fonction membre les accesseurs et :
- une fonction d'insertion en base de donnée de l'objet film
- une fonction de classe de selection des films dans la base de données

Le problème est que dans cette fonction de sélection il va me falloir également créer les instances acteurs et realisateur qui seront contenus dans le film et donc dans les requetes sql selectionner les champs des tables acteurs et realisateurs.
Et si on modifie la classe acteur, il faudra donc changer la classe film.

Le mieux serait peut être de ne mettre dans un objet film que les id des acteurs et realisateur ce qui permet de garder un indépendance en cas de modification d'une des classes. Mais en terme de modelisation ça me semble étrange.

comment faites vous dans votre implémentation?