Quick links: Content - sections - sub sections
EN FR
Quick Search Advanced search
 
Page

  [Opened] [Résolu] "squelette" jdao?

Posted by flav on 09/06/2010 18:01

Lorsque l'on crée un module charger d'offrir des méthodes sur un objet créé par un autre module, on écrit un jdao. Par exemple, j'ai déjà un module article. Si je veux un module de gestion du statut d'un article,je crée un jdao avec une primarytable pointant sur la table article, et j'ajoute la propriété article. Cependant, je souhaite que ce module gère aussi les statuts des commentaires. Bon, ba, je réécrit un jDAO en plus, et rebelotte. C'est lourd. Y'a t-il une meilleure solution?

Par exemple, envoyer le contenu de datasources de l'objet article ou commentaire au module. Ce module fabriquerait des DAOs à l'aide d'un "squelette de DAO". Ce "squelette" serait un XML similaire à un DAO, à ceci près qu'il ne contiendrais pas de primarytable, puisque cette donnée doit par exemple être fournie par le module "article" ou "commentaires". Un genre de DAO "sans tête". Destiné à pouvoir "prendre plusieurs visages", c'est à dire à utiliser le datasource d'un autre DAO?

  [Opened] "squelette" jdao?

Reply #1 Posted by flav on 09/06/2010 18:06

Laurentj :

Ce que tu veux faire en gros, si j'ai bien compris, c'est tout simplement de l'héritage objet. Et ça tombe bien, un dao c'est un objet. Ne pas oublier non plus qu'il est possible de redéfinir un dao (sans toucher à l'original) via le mécanisme d'overload de jelix.

Ah ba oui, tout simplement! Merci!

Résolu!

  [Opened] "squelette" jdao?

Reply #2 Posted by flav on 09/06/2010 19:51

Euh... Je me suis embrouillé tout seul.

Il ne s'agit plus de la solution du ticket http://developer.jelix.org/ticket/1169 dans lequel je suggérais un système de greffe. Or en postant ce sujet sur le forum je suis effectivement revenu sur cette idée "usine à gaz". La citation de laurentj provient du ticket .

Pour les greffes, usine à gaz. Ce que tu veux faire en gros, si j'ai bien compris, c'est tout simplement de l'héritage objet. Et ça tombe bien, un dao c'est un objet. Ne pas oublier non plus qu'il est possible de redéfinir un dao (sans toucher à l'original) via le mécanisme d'overload de jelix.

Donc pas de "greffe". Mais je maintiens l'idée (différente du ticket) qu'il pourrait être intéressant de créer un nouveau "dao" ou "squelette de dao" utilisant des propriétés non défini ailleurs et dépendant du "datasource" d'un autre dao, afin de pouvoir s'adapter à plusieurs type d'objets. Faire de l'héritage objet aurait pu être une solution. Mais là il ne s'agit plus d'étendre les propriété d'un dao existant, il s'agirait plutôt de compiler un nouveau DAO à partir des "datasources" d'un autre DAO.

Ou mieux, la compilation de ce "squelette DAO" fournirait des classes génériques, mais le jDaoSelecteur grâce auquel on récupère les datasources, et uniquement les datasources, serait un paramètre necessaire à l'instanciation de ces classes.

Ainsi ces classes "DAO like" ne serait plus destinées à une table précisément, mais à la table ou aux tables d'un autre DAO.

Exemple :

  • Je crée mon module articles, mon dao articles, et mes méthodes.
  • Je crée mon module commentaire, mon dao commentaires, et mes méthodes.
  • Je crée mon module statuts, et mon "squelette" dao statuts, et mes méthodes.

Et ce, au lieu d'ajouter les propriété statuts aux daos articles et commentaires. Statut est un module facultatif définissant des propriétés et des méthodes, mais pas forcément pour "articles" et "commentaires".

Est-il déjà possible de faire cela proprement ?

Des exemples?

Ou faut-il imaginer un système de squelette dao permettant de le faire ? Et même si on considère que c'est mieux de faire de l'héritage objet. Qu'on instancie d'abord le DAO articles, puis, grace aux events, qu'on ensuite passe la main au module "statuts". N'est il pas dommage de devoir se passer de l'aspect déclaratif qu'offre initialement jDao pour le faire ?

Alors oui, on peut passer par jDb. Mais avec jDAO, on pourrait après simple lecture d'un XML savoir quelles propriété(s) (est)sont ajoutée(s) par le modules statuts. Ce qui rendrait le code plus maintenable.

Enfin je crois...

  [Opened] "squelette" jdao?

Reply #3 Posted by flav on 09/06/2010 20:05

Mais c'est peut-être simplement moi qui ai du mal à concevoir mes modules...

  [Opened] "squelette" jdao?

Reply #4 Posted by foxmask on 09/07/2010 00:01

Est-il déjà possible de faire cela proprement ?

Oui c'est possible.

le module status serait à l'identique de celui de jTags.

jTags gère des tags, comme sur ce forum, et peut-être pluggé aussi bien sur un billet d'un blog que sur un thread ici. cf les 2 DAO. Pour cela dans le code on utilisera un "scope" différent selon son utilisation dans le module de son choix et c'est terminé.


@GitHub - Forum HaveFnuBB! powered by Jelix - Le Booster Jelix !

  [Opened] "squelette" jdao?

Reply #5 Posted by flav on 09/07/2010 00:34

Merci!!

Tu viens de faire passer mon mal de crâne! :-)

  [Opened] [RESOLU] "squelette" jdao?

Reply #6 Posted by laurentj on 09/07/2010 09:36

On pourrait effectivement avoir un mécanisme d'heritage dans jDao, permettant à un DAO d'hériter d'un autre DAO. En théorie, l'implémentation ne serait pas très compliqué, puisque l'on pourrait générer des objets dao utilisant l'héritage objet.

Cependant, il y a plusieurs soucis dans l'implémentation même.

Le premier, c'est la vérification des fichiers daos xml (date de modification), pour savoir si il faut régénérer les classes ou pas. Actuellement, les fichiers n'ont pas de dépendances entre eux. Donc on ne check qu'un fichier. Mais si on ajoute une dépendance, ça veut dire qu'à chaque requête http, il faut vérifier le dao demandé, puis aller vérifier les daos dont il hérite. Mais il faut aussi alors lire ces daos pour savoir si eux même héritent d'autres fichiers, checker ensuite les descendants etc.

Bref, c'est le genre de truc qui peut prendre énormément de temps, et pour rien en plus si au final rien n'a été modifié. Impensable de faire ça en prod. Bien sûr, on peut désactiver le check en prod, mais bon, je ne suis pas sûr que tout le monde optimise sa conf jelix en prod. La meilleure solution pour profiter de l'héritage, serait d'avoir une génération des classes, non pas à la volée, mais à la main, avec une commande en ligne (comme propel ou doctrine finalement).

Deuxième soucis : l'intérêt de faire ça. En aucune manière le module originale dans lequel il y a le dao ne pourra profiter automatiquement des nouvelles propriétés. En effet, le sélecteur qu'il utilise pour utiliser son dao pointe vers son dao. à moins donc de modifier les sources du module, il ne pourra donc utiliser le nouveau dao. C'est pour cela que j'ai fait ce système d'overload, pour pouvoir redéfinir un dao. Mais ce système a une lacune, puisqu'effectivement, un module ne peut overloader un fichier d'un autre module. Une solution serait d'apporter un système d'injection de dépendance/inversion de contrôle. Mais bon, ça peut changer pas mal les choses.

Une solution, c'est qu'un module soit conçu de manière à être extensible. Pour cela, il peut utiliser le système d'évènement : il balance des évènements à des moments précis pour récupérer des données ou objets qu'il utilisera. Le module jauth ou mieux encore, jcommunity, l'utilise abondamment (et jtags aussi ? je sais plus). Il peut aussi avoir un système de plugins...

  [Opened] "squelette" jdao?

Reply #7 Posted by flav on 09/07/2010 18:17

jtags ne le fais pas. Il utilise une table indépendante. Et une donnée "scope" permet d'attribuer un tag à un type d'objet. En fait je m'étais simplement résigné en acceptant d'utiliser cette méthode. Mais...

Nouvelle tentative

En somme, si on reformule le problème autrement, avec jDao, on a pour une table, un module de "définition". Aucun autre module n'est en mesure d'ajouter des colonne a une table, sauf en passant par jDB (sans connaissance préalable de la table visée).

On veut qu'un module tiers puisse ajouter une colonne à une table sans dépendre du module définissant la table, et sans que le module définissant ne dépende du module tiers. (Bien que pour fonctionner le module tiers doit pouvoir utiliser une table existante -> pour celà il appartient au développeur d'envisager une stratégie avec jEvents) On admet que le module original ne pourra en aucun cas accéder à la colonne, puisque ce n'est pas son DAO qui est chargé de la définir. C'est alors au module tiers, nécessitant d'avoir pour paramètre au moins la table du module original, qui pourra gérer la nouvelle colonne. Mais comme on est des gros intégristes de la maintenabilité, on veut à tout prix utiliser jDao!

L'idée qui pourrait être intéressante serait de séparer les "datasources" (ou au moins la "primarytable") et le reste du DAO en deux parties distinctes. A première vue, ça peut être un peu lourd. En tout cas ça demanderait de lourdes modifications.

Une autre idée serait d'avoir deux types distincts de DAO. Le premier c'est l'actuel. Le DAO pouvant définir la table. L'autre, destiné au module tiers, ne fonctionnerait qu'en se greffant à un autre DAO. Mais ça fait deux compilations distinctes. Ce dao, plus abstrait récupèrerait les datasources d'un autre DAO et éventuellement des propriétés de celui ci, si on lui demande. Exemple:

Une nouvelle fonction jDaoGraft::get($abstract_dao, $src_dao {,$propriétés})

  • où abstract_dao est le sélecteur d'un "abstract_DAO" (ne définissant pas de table)
  • $src_dao est le sélecteur d'un dao classique (table source)
  • $propriétés=false par défaut, {une array listant les propriétés définie pas dao_src mais utiles pour dao_abstract. Si $propriétés=='*', toutes les propriétés sont récupérés.} => Surtout pas en fait. ça ferait un nombre énorme de contexte pour la compilation du cache. Contentons nous d'imaginer le paramètre propriété comme une valeur booléenne. Si true tout les records sont récupérés, sinon aucun.

On a alors un nouveau DAO compilé à partir de deux fichiers, et strictement deux, car il n'est pas possible de faire jDaoGraft::get($abstract_dao,$abstract_dao), ça n'aurait pas de sens (donc pas d'héritage à plusieurs niveaux possible). Le nom du fichier nouvellement compilé tiendrait compte des deux sélecteurs (avec le suffixe '-all' si $propriété=true).

Je ne pense pas que ce serait compliqué à faire. La question, est : Est-ce vraiment intéressant ? je pense que oui. à débattre. Notamment pour "modulariser" un projet qui ne l'est pas, ou mal. Ou simplement pour éviter de se retrouver avec 200 tables de 2 colonnes par projet, tout en adoptant une philosophie très modulaire, et donc potentiellement très maintenable/réutilisable/lisible/etc...

  [Opened] "squelette" jdao?

Reply #8 Posted by flav on 09/09/2010 16:14

Nan c'est lourd en fait.

Désolé. Je me contredis à chaque post. C'est parce que je suis en train de concevoir le core de jSpip (adaptation d'une BD spip par et pour des modules jelix). Je pense avoir trouvé une solution plus intéressante, qui pourra servir de base à d'autre projets pour gagner un niveau d'abstraction sur la définition des objets d'un cms : Un XML définissant les objets en leur attribuant des fonctionnalités. Chaque fonctionnalité correspondrait à un module, et chacun de ces modules ajouterait dans une global tableau l'ensemble des colonnes, des jointures, et des méthodes requises. Exemple cms_objet.xml liste les fonctionnalités des brèves des articles et des forums. Ces objets sont abstraits et ne sont définis par aucun DAO. Il pourrait très bien ne pas exister, le monde continuerait de tourner. On doit pouvoir les supprimer/modifier/ajouter par la simple édition du cms_objets.xml.

A priori aucune proposition de modification du core de jelix, puisqu'il s'agit d'une conception très particulière d'application (pas généraliste).

Cependant ce XML doit aboutir à un objet compilé pour le cache. Inconcevable en effet de régénérer les classes à chaque fois. J'ai donc besoin d'un compilateur qui, à partir d'une array est capable de me fournir des classes d'E/S sur BD, et stockant le résultat dans un fichier 'cache' dont le nommage tient compte du contexte. Or c'est exactement ce que fait jDAO D'où ma prise de tête pour ne pas faire un copier-coller du code. Ce serait dommage.

En fait le plus simple, et le plus souple serait une fonction du genre :

AbstractJdao($context_id, $definition)

  • Où $definition serait l'équivalent d'un DAO mais sous forme d'array.
  • Et $context_id permettrait le nommage du fichier pour le cache. Exemple : 'article'.

Mais ce contexte peut aussi tenir compte du module afin de pouvoir être appelé en dehors de celui ci. On pourrait alors inventer un nouveau type de selecteur 'AbstractJdao' sous la forme 'module~context_id'?

On aurait alors :

AbstractJdao($selector, $definition)

à ajouter dans le core de jelix ?

  [Opened] "squelette" jdao?

Reply #9 Posted by flav on 09/21/2010 23:39

En fait, le problème est mal formulé. Je mélange ici une stratégie de developpement particulière que je suis en train de concevoir avec le developemment de jelix. Après mûre réfléxion (et un peu de repos), j'ai une proposition d'amélioration pour jelix beaucoup plus simple et logique qui me permettrais d'avancer, et qui mérite réfléxion.

Je reposte un deuxième sujet afin de ne pas obliger les lecteurs à se bousiller les yeux pour rien.

 
Page
  1. [RESOLU] "squelette" jdao?