IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JSF Java Discussion :

JSF est-il Anti Design Pattern ? [Débat]


Sujet :

JSF Java

  1. #41
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Euh, pour moi, ce sont les DAO qui utilisent le lazy loading (et là, j'inclu le bean métier).
    Le DTO n'est qu'une "vue" des DAO (partie "metier") mais ils sont conçus en fonction de l'utilisation finale (donc l'ihm)
    Effectivement, ils sont créés dans le conteneur d'ejb et implémentent Serializable pour "voyager"

    Ceci dit, sur la terminologie, on peut encore discuter... il y a certainement des puristes qui ne seront pas de mon avis
    Effectivement dire que le DAO est le metier n'est pas vraiment exact le DAO est la couche d'acces au données, et encapsule la façon d'acceder au support de persistance (BDD relationnel, fichier XML ...)

    Ensuite personnellement et la je suis loin d'etre sur de moi, je trouve que le DTO oblige une separation propres, il y a effectivement un probleme du au lazy laoding, dur de ramener un gros graph lorsque tout n'est pas necessaire meme si tu optimise via un join fetch.

    De toute façon le lazy loading oblige a initialiser les sous objets, donc plutot que le faire dans le vide autant le faire en peuplant un DTO, de plus toutes les informations ne sont pas forcement utile à l'IHM, ca permet de faire un filtre, enfin bref il y a du bon dans le DTO, mais je reconnais que je fais rarement des DTO ou alors il contiennent des objet metier, ceci dit je prefere cloner mes objet metier , l'utilisation d'un framework pour la creation d'un clone avec en parametre la profondeur de copie me semble utile.

  2. #42
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par FreshVic Voir le message
    Ensuite personnellement et la je suis loin d'etre sur de moi, je trouve que le DTO oblige une separation propres, il y a effectivement un probleme du au lazy laoding, dur de ramener un gros graph lorsque tout n'est pas necessaire meme si tu optimise via un join fetch.

    De toute façon le lazy loading oblige a initialiser les sous objets, donc plutot que le faire dans le vide autant le faire en peuplant un DTO, de plus toutes les informations ne sont pas forcement utile à l'IHM, ca permet de faire un filtre, enfin bref il y a du bon dans le DTO, mais je reconnais que je fais rarement des DTO ou alors il contiennent des objet metier, ceci dit je prefere cloner mes objet metier , l'utilisation d'un framework pour la creation d'un clone avec en parametre la profondeur de copie me semble utile.
    Utiliser des DTO ne résout pas le problème des "lazy initialization exceptions", puisque quand une entité possède des associations vers plusieurs autres entités, le mieux c'est de faire en sorte que ces associations ne soient chargées avec l'objet que quand c'est vraiment nécessaire, donc les configurer en mode LAZY. Pour chaque cas d'utilisation on peut avoir besoin d'une association et pas des autres, et là on doit normalement charger l'objet et initialiser uniqiuement l'association voulue à partir d'une requête avec "join fetch" et laisser juste des proxy pour les autres associations (pas besoin de ramener tout le graphe). Ceci est vrai que l'on utilise des DTO ou pas et permet d'éviter le problème des "n+1 select", donc d'avoir de meilleures performances.
    Maintenant le problème qui se pose c'est : une fois qu'au sein d'une transaction j'ai chargé mon objet persistent avec l'association nécessaire au cas d'utilisation, est-ce je dois le renvoyer tel quel vers la couche présentation ou dois-je plutôt en faire une copie champ par champ vers un DTO spécialement conçu pour faire voyager ses données à travers les couches de mon application ?
    Moi je réponds que je n'ai pas nécessairement besoin du DTO pour ça, parce que cela introduit de la duplication de code et aussi des problèmes de maintenance (voir mes posts précédents). J'ai besoin de DTO lorsque les données me viennent de plusieurs entités (cas d'aggréagtion déjà cité).
    Mais je comprends aussi le point de vue de azerr, notamment, dans ce sens que renvoyer les objets persistents à la couche présentation présente le risque de coupler cette couche au model et que des modifications du model entrainent des modifications dans différentes couches. Sauf que je pense que le problème se poserait quand même aussi avec des DTO, car une modification importante du modèle affecte généralement aussi les DTO associés et donc finalement la couche présentation...
    L'argument de la séparation des couches peut se justifier quand l'objet métier contient de la logique métier sensible qu'il vaudrait mieux cacher en utilisant un DTO, mais pour la plupart des autres objets persistents, le gain d'un DTO est infime, au contraire.
    Quoiqu'il en soit, je pense qu'il faut déconnecter le problème des DTO avec celui de la gestion du lazy loading.
    A+

  3. #43
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par FreshVic Voir le message
    Effectivement dire que le DAO est le metier n'est pas vraiment exact le DAO est la couche d'acces au données, et encapsule la façon d'acceder au support de persistance (BDD relationnel, fichier XML ...)
    Ce que je dis, c'est que le "métier" fait partie de la DAO (pas "est"), ce qui est un abus de langage pour un puriste, mais je trouve personnellement que séparer les 2 alors qu'ils sont aussi étroitement liés est gênant (d'où mon inclusion)
    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #44
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par manblaizo Voir le message
    Utiliser des DTO ne résout pas le problème des "lazy initialization exceptions", puisque quand une entité possède des associations vers plusieurs autres entités, le mieux c'est de faire en sorte que ces associations ne soient chargées avec l'objet que quand c'est vraiment nécessaire, donc les configurer en mode LAZY. Pour chaque cas d'utilisation on peut avoir besoin d'une association et pas des autres, et là on doit normalement charger l'objet et initialiser uniqiuement l'association voulue à partir d'une requête avec "join fetch" et laisser juste des proxy pour les autres associations (pas besoin de ramener tout le graphe). Ceci est vrai que l'on utilise des DTO ou pas et permet d'éviter le problème des "n+1 select", donc d'avoir de meilleures performances.
    Maintenant le problème qui se pose c'est : une fois qu'au sein d'une transaction j'ai chargé mon objet persistent avec l'association nécessaire au cas d'utilisation, est-ce je dois le renvoyer tel quel vers la couche présentation ou dois-je plutôt en faire une copie champ par champ vers un DTO spécialement conçu pour faire voyager ses données à travers les couches de mon application ?
    Moi je réponds que je n'ai pas nécessairement besoin du DTO pour ça, parce que cela introduit de la duplication de code et aussi des problèmes de maintenance (voir mes posts précédents). J'ai besoin de DTO lorsque les données me viennent de plusieurs entités (cas d'aggréagtion déjà cité).
    Mais je comprends aussi le point de vue de azerr, notamment, dans ce sens que renvoyer les objets persistents à la couche présentation présente le risque de coupler cette couche au model et que des modifications du model entrainent des modifications dans différentes couches. Sauf que je pense que le problème se poserait quand même aussi avec des DTO, car une modification importante du modèle affecte généralement aussi les DTO associés et donc finalement la couche présentation...
    L'argument de la séparation des couches peut se justifier quand l'objet métier contient de la logique métier sensible qu'il vaudrait mieux cacher en utilisant un DTO, mais pour la plupart des autres objets persistents, le gain d'un DTO est infime, au contraire.
    Quoiqu'il en soit, je pense qu'il faut déconnecter le problème des DTO avec celui de la gestion du lazy loading.
    A+
    Ben là, je ne suis pas d'accord avec toi, pour moi les DTO règlent le problème des lazy loading exception puisqu'ils sont là justement pour représenter les données utilisées (utiles pourrait-on dire)
    Il ne s'agit pas pour moi de faire une copie du bean metier (lié au DAO) vers un objet DTO par un utilitaire, mais bel et bien une lecture du graphe d'objets et du chargement d'un autre graphe d'objets (DTO) spécifique à la demande.
    Là où je te rejoins, c'est sur l'utilisation des "join fetch" qui permettent d'optimiser les requêtes, mais ça s'arrête là.

    Ça n'est évidement que mon avis...
    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #45
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Par défaut
    Je suis pas un expert hibernate mais l'attribut fetch=join permet de charger en une requete le sous objet via un left outer join.
    Tu dis que suivant les cas d'utilisation tu remonte le graphe d'objet correspondant au besoins, ca semble etre une bonne idée mais comment parametré cela en fonction du cas d'utilisation ? on a plusieurs cas d'utilisation pour un seul fichier de mapping donc si tu mets fetch=join tu remontera automatiquement le sous objet meme dans des cas ou ce n'est pas utile non ? d'ou l'interet du DTO , on aurait 1 DTO par cas d'utilisation.

    Je ne dis pas que le DTO regle le probleme du lazy loading, ce sont 2 choses differente certes mais l'initialisation du DTO (dans une session hibernate avec objet attaché a la session) permet de charger les données necessaire puisque le DTO represente les besoins du cas d'utilisation.

  6. #46
    Membre chevronné Avatar de heid
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    388
    Détails du profil
    Informations personnelles :
    Localisation : France, Indre et Loire (Centre)

    Informations forums :
    Inscription : Mai 2002
    Messages : 388
    Par défaut
    A mon avis ce sont deux problèmes différents :
    En DTO tu charge ton graphe dans tes objets pour la présentation.
    Sinon tu renvoi tes entités.

    Dans les deux cas tu dois prévoir avant l'envoi vers la présentation quelle sera le degré de "dispertion" (j'usqu'ou aller dans le chargement des relations) de ton graphe d'objet : les dto ET les entités sont en dehors du contexte de persistance.

    Le code que tu ajoutes pour créer ton graphe moi je le remplace par celui qui ira faire un join fetch avec les relations que je veux renvoyer et donc utilisables en dehors du contexte de persistance. Dans les deux cas ce sera du spécifique exemple (dans une applis de gestion) pour savoir si le controleur renvoi à la présentation les lignes produits de la commande ou si seul les données de la commande (date, montant total) sont nécessaires.

    Qu'en penses tu OButterlin ?

  7. #47
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    C'est justement pour ces raisons là que je ne fais plus la séparation entre mes entités persistantes et mes DTOs ... on va crier au loup là, mais essayons d'y réfléchir calmement:
    - Comme évoqué par azerr, ce n'est pas drôle du tout d'avoir à gérer un mirroir d'un graphe d'objets (mirrorer le graphe des entités persistentes pas un autre des DTOs). Pensez par exemple à la synchronisation (modification d'un coté entraine modification dans l'autre à la main, le refactoring ne sert à rien là), à la quantité du boiler-plate code, de la consommation en mémoire, etc.

    - Le problème du lazy fetch: si on passe par des DTOs séparés, ce serait stupide d'utiliser le lazy fetch du moment qu'on va systématiquement accèder aux attributs lors de la copie. Si par contre on fait du eager fetch, RAM quand tu nous tiens !

    Certains me diront qu'il est possible de ne copier dans les DTOs que ce que dont la couche contrôle/service en aura besoin ... sérieusement, cette solution vous paraît elle raisonnable ? les besoins changent tous le temps, c'est sacrément dur et long à coder, ça couple inutilement diverses couches et classes, etc. etc.

    - Les problèmes dû au lazy fetch peuvent être résolu facilement (grâce aux CMT dans un AS avant, et même dans un conteneur web maintenant grâce à Spring et à son support exceptionnel de JPA).

    @+

  8. #48
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par heid Voir le message
    A mon avis ce sont deux problèmes différents :
    En DTO tu charge ton graphe dans tes objets pour la présentation.
    Sinon tu renvoi tes entités.

    Dans les deux cas tu dois prévoir avant l'envoi vers la présentation quelle sera le degré de "dispertion" (j'usqu'ou aller dans le chargement des relations) de ton graphe d'objet : les dto ET les entités sont en dehors du contexte de persistance.

    Le code que tu ajoutes pour créer ton graphe moi je le remplace par celui qui ira faire un join fetch avec les relations que je veux renvoyer et donc utilisables en dehors du contexte de persistance. Dans les deux cas ce sera du spécifique exemple (dans une applis de gestion) pour savoir si le controleur renvoi à la présentation les lignes produits de la commande ou si seul les données de la commande (date, montant total) sont nécessaires.

    Qu'en penses tu OButterlin ?
    Ben moi j'suis d'accord avec ce que tu dis
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #49
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par djo.mos Voir le message
    - Comme évoqué par azerr, ce n'est pas drôle du tout d'avoir à gérer un mirroir d'un graphe d'objets (mirrorer le graphe des entités persistentes pas un autre des DTOs). Pensez par exemple à la synchronisation (modification d'un coté entraine modification dans l'autre à la main, le refactoring ne sert à rien là), à la quantité du boiler-plate code, de la consommation en mémoire, etc.
    C'est un inconvénient qui peut devenir un atout, tu peux modifier ton graphe d'objets métier DAO sans avoir à toucher aux applications qui l'utilisent (jusqu'à une certaine limite)

    Citation Envoyé par djo.mos Voir le message
    - Le problème du lazy fetch: si on passe par des DTOs séparés, ce serait stupide d'utiliser le lazy fetch du moment qu'on va systématiquement accèder aux attributs lors de la copie. Si par contre on fait du eager fetch, RAM quand tu nous tiens !
    Ben non, justement, on peut utiliser le lazy loading puisque c'est une méthode (ou un service) spécifique qui est appelée pour charger le graphe

    Citation Envoyé par djo.mos Voir le message
    Certains me diront qu'il est possible de ne copier dans les DTOs que ce que dont la couche contrôle/service en aura besoin ... sérieusement, cette solution vous paraît elle raisonnable ?
    Oui

    Citation Envoyé par djo.mos Voir le message
    - Les problèmes dû au lazy fetch peuvent être résolu facilement (grâce aux CMT dans un AS avant, et même dans un conteneur web maintenant grâce à Spring et à son support exceptionnel de JPA).
    @+
    Peux-tu détailler ?

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #50
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Ce que je dis, c'est que le "métier" fait partie de la DAO (pas "est"), ce qui est un abus de langage pour un puriste, mais je trouve personnellement que séparer les 2 alors qu'ils sont aussi étroitement liés est gênant (d'où mon inclusion)
    A+
    Citation Envoyé par OButterlin Voir le message
    Ben là, je ne suis pas d'accord avec toi, pour moi les DTO règlent le problème des lazy loading exception puisqu'ils sont là justement pour représenter les données utilisées (utiles pourrait-on dire)
    Il ne s'agit pas pour moi de faire une copie du bean metier (lié au DAO) vers un objet DTO par un utilitaire, mais bel et bien une lecture du graphe d'objets et du chargement d'un autre graphe d'objets (DTO) spécifique à la demande.
    Là où je te rejoins, c'est sur l'utilisation des "join fetch" qui permettent d'optimiser les requêtes, mais ça s'arrête là.

    Ça n'est évidement que mon avis...
    A+
    Je crois qu'on a petit problème de définition des concepts DAO, DTO,... on n'a pas l'air de parler de la même chose. Je vais essayer d'éclaircir comment je vois les choses, en allant dans le même sens que heid. Un DAO tel que le comprend et l'utilise, Data Access Object, c'est une abstraction de la façon dont l'application accède au stockage persistent (BDD, fichier XML...). Son implémentation peut être en Hibernate avec des session.save()..., en JPA ou utiliser du SQL pur, cela importe peu pour le reste de mon application du moment que j'utilise une interface pour abstraire le DAO. Donc les entités métier ne font pas partie de la couche DAO, mais elles ont persistées à travers la couche DAO.
    Pour ce qui est du DTO (Data Transfer Object), c'est un objet qui fait mirroir à l'objet persistent en reprenant la plupart de ses champs, avec getter/setter, dans le seul but transférer les données de l'objet persistent vers la couche présentation. C'était très utile avec les Entity Beans (EJB2 encore une fois) parce que c'était une bonne pratique de ne pas les renvoyer à la couche présentation, et donc il fallait copier leurs données dans un autre objet conçu pour cela, le DTO.
    Ce que je voulais dire à propos du lazy loading, c'est qu'avant de créer et remplir le DTO (par copie de l'objet persistent), il faut d'abord charger l'objet persistent lui-même ainsi que ses associations, et c'est donc à ce moment-là qu'il faut traiter l'éventuel problème de lazy loading, ce n'est pas l'utilisation d'un DTO qui changera quelque chose à cela.
    J'espère que cela clarifie un peu le point de vue que je défend.

    Citation Envoyé par FreshVic Voir le message
    Je suis pas un expert hibernate mais l'attribut fetch=join permet de charger en une requete le sous objet via un left outer join.
    Tu dis que suivant les cas d'utilisation tu remonte le graphe d'objet, ca semble etre une bonne idée mais comment parametré cela en fonction du cas d'utilisation ? on a plusieurs cas d'utilisation pour un seul fichier de mapping donc si tu mets fetch=join tu remontera automatiquement le sous objet meme dans des cas ou ce n'est pas utile non ?
    En fait, l'attribut fetch=join dans le fichier de mapping représente la façon dont l'association est initialisée quand on est mode EAGER. fetch=join veut dire l'objet associé sera chargé en faisant un "select ... join" dans le sql généré, donc on charge le tout en une seule requête. Par contre si fetch=select, cela signifie que l'objet principal est d'abord chargé par un premier select, puis l'objet associé est également chargé par un autre select, donc deux requêtes BDD pour avoir le même résultat.
    Par contre, ce que je défend c'est qu'on puisse configurer les associations en mode LAZY et les charger uniquement en fonction du cas d'utilisation. C'est-à-dire que pour un cas d'utilisation donné, je définis une requête qui sera utilisée par la méthode chargeant l'objet persistent, quelque chose du genre, en hibernate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FROM Hotel h JOIN FETCH h.rooms
    ceci me charge un objet Hotel avec l'ensemble de ses chambres associées, mais uniquement parce que dans mon cas d'utiisation j'ai besoin d'afficher les informations de l'hotel et celles des chambres correspondantes.
    Dans tous les autres cas d'utilisations où je n'ai pas besoin des chambres, je charge uniquement les infos de l'hotel :
    Voilà un peu comment je vois les choses.

  11. #51
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Par défaut
    Citation Envoyé par djo.mos Voir le message

    Certains me diront qu'il est possible de ne copier dans les DTOs que ce que dont la couche contrôle/service en aura besoin ... sérieusement, cette solution vous paraît elle raisonnable ? les besoins changent tous le temps, c'est sacrément dur et long à coder, ça couple inutilement diverses couches et classes, etc. etc.
    Au risque de passer pour un puriste que je ne suis pas , je dirais que c'est pourtant la solution ideale pour respecter la separation des couches.
    Des objet metier dans la couche de presentation, c'est pas geniale.

    De plus lorsque un graphe d'objet metier change, sachant qu'il est utilisé par l'ihm on va devoir modifier l'ensemble des classes de presentation qui utilise ce graphe, alors que la simple modification de la classe (methode) qui peuple le DTO a partir du graphe serait a mon avis plus simple.

    En gros on rajoute une couche qui fait l'interface entre la presentation et le service, cette couche prend les graphe d'objet et initialise les DTO et inversement, de cette façon on a une independance totale de la presentation vis a vis des objet metier:

    PRESENTATION
    ||
    DTO INITIALISATION
    ||
    METIER

    Donc dans le cas de modification du metier , une seule couche est impacter, c'est celle que je viens de nomme par manque d'imagination DTO INITIALISATION .

    Ce n'est qu'une suggestion, je n'ai encore jamais utilisé cette architecture mais je trouve qu'elle a quelque chose de seduisant.

    Mais je reconnais que le codage de cette couche est chiante à mourrir, mais niveau maintenabilité c'est ++

  12. #52
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Je suis d'accord pour les définitions

    Sinon, y'a juste un truc :
    Citation Envoyé par manblaizo
    Ce que je voulais dire à propos du lazy loading, c'est qu'avant de créer et remplir le DTO (par copie de l'objet persistent), il faut d'abord charger l'objet persistent lui-même ainsi que ses associations, et c'est donc à ce moment-là qu'il faut traiter l'éventuel problème de lazy loading, ce n'est pas l'utilisation d'un DTO qui changera quelque chose à cela.
    Si, ça fait une énorme différence à mon avis.
    On est bien d'accord que le lazy fetch, dans la théorie est une excellent chose, un truc à utiliser sans modération ? Si c'est le cas, pas la peine alors de citer ses avantages.

    Donc, en partant de là, et sachant bien que le lazy fetch est implémenté dans le proxy de l'objet persistent qui intercepte l'appel vers le getter d'une propriété lazy et effectue le reste.
    Si maintenant on s'amuse à copier les objets persistents dans des DTOs séparés, on va forcément perdre la notion de lazy fetch vu qu'on va accèder aux divers champs de l'objet persisté pour les copier dans le DTOs, invoquant implicitement les selects nécessaires.

    De cette façon, on n'a fait qu'augmenter le nombre de requêtes générées, alors qu'en mode eager on aurait pu réduite ce nombre.

    Voilà pourquoi à mon avis l'utilisation de DTOs séparés influe directement sur le lazy fetch.

  13. #53
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Par défaut
    Citation Envoyé par manblaizo Voir le message
    Je crois qu'on a petit problème de définition des concepts DAO, DTO,... on n'a pas l'air de parler de la même chose. Je vais essayer d'éclaircir comment je vois les choses, en allant dans le même sens que heid. Un DAO tel que le comprend et l'utilise, Data Access Object, c'est une abstraction de la façon dont l'application accède au stockage persistent (BDD, fichier XML...). Son implémentation peut être en Hibernate avec des session.save()..., en JPA ou utiliser du SQL pur, cela importe peu pour le reste de mon application du moment que j'utilise une interface pour abstraire le DAO. Donc les entités métier ne font pas partie de la couche DAO, mais elles ont persistées à travers la couche DAO.
    Pour ce qui est du DTO (Data Transfer Object), c'est un objet qui fait mirroir à l'objet persistent en reprenant la plupart de ses champs, avec getter/setter, dans le seul but transférer les données de l'objet persistent vers la couche présentation. C'était très utile avec les Entity Beans (EJB2 encore une fois) parce que c'était une bonne pratique de ne pas les renvoyer à la couche présentation, et donc il fallait copier leurs données dans un autre objet conçu pour cela, le DTO.


    Ce que je voulais dire à propos du lazy loading, c'est qu'avant de créer et remplir le DTO (par copie de l'objet persistent), il faut d'abord charger l'objet persistent lui-même ainsi que ses associations, et c'est donc à ce moment-là qu'il faut traiter l'éventuel problème de lazy loading, ce n'est pas l'utilisation d'un DTO qui changera quelque chose à cela.
    J'espère que cela clarifie un peu le point de vue que je défend.
    Tres juste.

    En fait, l'attribut fetch=join dans le fichier de mapping représente la façon dont l'association est initialisée quand on est mode EAGER. fetch=join veut dire l'objet associé sera chargé en faisant un "select ... join" dans le sql généré, donc on charge le tout en une seule requête. Par contre si fetch=select, cela signifie que l'objet principal est d'abord chargé par un premier select, puis l'objet associé est également chargé par un autre select, donc deux requêtes BDD pour avoir le même résultat.
    C'est bien ce que j'avais compris

    Par contre, ce que je défend c'est qu'on puisse configurer les associations en mode LAZY et les charger uniquement en fonction du cas d'utilisation. C'est-à-dire que pour un cas d'utilisation donné, je définis une requête qui sera utilisée par la méthode chargeant l'objet persistent, quelque chose du genre, en hibernate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FROM Hotel h JOIN FETCH h.rooms
    ceci me charge un objet Hotel avec l'ensemble de ses chambres associées, mais uniquement parce que dans mon cas d'utiisation j'ai besoin d'afficher les informations de l'hotel et celles des chambres correspondantes.
    Dans tous les autres cas d'utilisations où je n'ai pas besoin des chambres, je charge uniquement les infos de l'hotel :
    Voilà un peu comment je vois les choses.
    Effectivement ton raisonnement ce defend et me semble etre une bonne utilisation des requete HQL je ne pensais pas du tout a cette utilisation du HQL en fait je rechigne a faire du HQL je me contente le plus souvent possible des fichiers de mapping et de mes objets, ca me permets de voir qu'il y a effectivement pas mal d'avantage à personnaliser le parametrage en fonction du "cas d'utilisation" du coup je comprend mieux ce que tu voulais dire.

    Merci pour ces explications, j'essairais de m'en souvenir.
    Donc oui le DTO est bidon pour le probleme de lazy loading, sont utilité est ailleurs et continuera à faire couler bcp d'ancre.

  14. #54
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par djo.mos Voir le message
    Si maintenant on s'amuse à copier les objets persistents dans des DTOs séparés, on va forcément perdre la notion de lazy fetch vu qu'on va accèder aux divers champs de l'objet persisté pour les copier dans le DTOs, invoquant implicitement les selects nécessaires.
    Non, justement, si l'objet a été chargé en une seule requête avec ses objets dépendants, il n'y a plus besoin de nouveaux select pour initialiser ces dépendances. On a déjà tout en mémoire et il reste à savoir si on doit renvoyer ça directement à la couche présentation ou tout copier d'abord dans un DTO qui va être renvoyé.
    Donc le problème du lazy loading se règle en dehors de tout concept de DTO ou pas DTO.

  15. #55
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Citation Envoyé par FreshVic Voir le message
    Au risque de passer pour un puriste que je ne suis pas , je dirais que c'est pourtant la solution ideale pour respecter la separation des couches.
    Des objet metier dans la couche de presentation, c'est pas geniale.
    Non, pas des objets métier, des objets métier anémiques, des simple conteneurs de données (les fameux chaps en proivate + getters +setters ainsi que d'autres méthodes hyper simple ne faisant que travailler sur les champs internes), rien de spécial la dedans et ça ne casse aucunement la séparation de couches ...

    Citation Envoyé par FreshVic Voir le message
    De plus lorsque un graphe d'objet metier change, sachant qu'il est utilisé par l'ihm on va devoir modifier l'ensemble des classes de presentation qui utilise ce graphe, alors que la simple modification de la classe (methode) qui peuple le DTO a partir du graphe serait a mon avis plus simple.
    Je ne vois pas la différence: si on ajoute un champ à un objet persistents, on va devoir l'ajouter dans le DTO ainsiq ue dans le code du binding. de même pour la suppression d'un champ. ça ne sert qu'en cas de renommage, mais tu as toute la lourdeur en contre partie

    Citation Envoyé par FreshVic Voir le message
    Ce n'est qu'une suggestion, je n'ai encore jamais utilisé cette architecture mais je trouve qu'elle a quelque chose de seduisant.
    J'apprécie ta franchise, mais vraiment
    Parceque c'est vrai que sur le papier, c'est pas mal du tout. Essaies de mettre ça en pratique dans un projet de taille imposante (quelques dizaines d'entités) et tu verras

  16. #56
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Citation Envoyé par manblaizo Voir le message
    Non, justement, si l'objet a été chargé en une seule requête avec ses objets dépendants, il n'y a plus besoin de nouveaux select pour initialiser ces dépendances. On a déjà tout en mémoire et il reste à savoir si on doit renvoyer ça directement à la couche présentation ou tout copier d'abord dans un DTO qui va être renvoyé.
    Donc le problème du lazy loading se règle en dehors de tout concept de DTO ou pas DTO.

    Oui, je sais, je l'ai même dit qu'en mode eager ça règle le problème.
    Mais en pratique, le mode eager est tout simplement inutilisable. Rien qu'avec quelques entités avec des relations complexes entre eux multupliés par quelques centaines d'occurences et c'est fini de ta mémoire !

    Or les DTOs rendent ineffectif/inutilisable le lazy fetch.

  17. #57
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Par défaut
    Citation Envoyé par djo.mos Voir le message
    Non, pas des objets métier, des objets métier anémiques, des simple conteneurs de données (les fameux chaps en proivate + getters +setters ainsi que d'autres méthodes hyper simple ne faisant que travailler sur les champs internes), rien de spécial la dedans et ça ne casse aucunement la séparation de couches ...


    Je ne vois pas la différence: si on ajoute un champ à un objet persistents, on va devoir l'ajouter dans le DTO ainsiq ue dans le code du binding. de même pour la suppression d'un champ. ça ne sert qu'en cas de renommage, mais tu as toute la lourdeur en contre partie


    J'apprécie ta franchise, mais vraiment
    Parceque c'est vrai que sur le papier, c'est pas mal du tout. Essaies de mettre ça en pratique dans un projet de taille imposante (quelques dizaines d'entités) et tu verras

    J'ai editer mon post en rajoutant que je reconnaissais que le developpement de la couche d'initialisation des DTO etait chiante a mourir voir meme limite suicidaire, mais je pense que niveau maintenabilité c'est bcp mieux.
    L'ajout d'un champs coté metier n'impacte pas forcement, l'ajout d'un champs coté IHM et l'ajout d'un champs coté IHM ne necessite pas forcement l'ajout d'un champs coté metier (attribut calculé par exemple).

  18. #58
    Membre chevronné Avatar de heid
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    388
    Détails du profil
    Informations personnelles :
    Localisation : France, Indre et Loire (Centre)

    Informations forums :
    Inscription : Mai 2002
    Messages : 388
    Par défaut
    FreshVic je fait comme toi au niveau des requêtes : je met majoritairement en lazy et je fais des namedquerries spéciales en fonction des cas d'utilisation avec des join fetch. Ca marche très bien pour un cas simple mais ca me pose problème dans une approche plus complexe d'un méchanisme "objet".

    Pour le cas ou tu as un niveau de lien ca passe mais imagines un objet A qui est en *-* avec un B qui est en 1-* avec un C et en *-* avec un D. Lorsque tu charges A pour un traitement, tu dois prévoir 4 méthodes de chargement différentes???

    1 = charge , 0 = ne charge pas

    ABCD
    1000 => que A sans relation
    1100 => A et B
    1110 => A et B et les relation de B vers C
    1111 => Les 4 relations

    Cela pose un grosse contrainte car parfois dans un appel de chargement tu ne sais pas encore jusqu'ou tu ira dans les relations, d'ou le lazy loading et donc le problème des requêtes n+1...

    Le problème c'est que tout lazy ou tout eager me satisfait encore moins

    Une idée?

  19. #59
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par FreshVic Voir le message
    Effectivement ton raisonnement ce defend et me semble etre une bonne utilisation des requete HQL je ne pensais pas du tout a cette utilisation du HQL en fait je rechigne a faire du HQL je me contente le plus souvent possible des fichiers de mapping et de mes objets, ca me permets de voir qu'il y a effectivement pas mal d'avantage à personnaliser le parametrage en fonction du "cas d'utilisation" du coup je comprend mieux ce que tu voulais dire.
    En poussant juste un cran plus loin, tu as renvoyé un graphe d'objets persistant à ton contrôleur et toi (ou un autre) va maintenant afficher les données (tu as bien sûr optimiser tes accès db en vu d'une utilisation avec les fetch join)...
    Manque de bol, dans un sous-objet du graphe, tu références une liste (non initialisée bien sûr) et tu veux t'en servir pour afficher une information -> NullPointerException, dommage
    L'avantage du graphe d'objets DTO, c'est qu'en quelque sorte, tu réponds à un contrat. Dans l'exemple, évidement le sous-objet ne contient pas la liste, on ne risque donc pas l'exception.

    Je suis bien d'accord avec certains d'entre vous que faire des DTO pour des objets simples est lourd (pas forcément inutile), mais pour les autres, je trouve ça bien propre.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  20. #60
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Citation Envoyé par heid Voir le message
    Une idée?
    Perso, tout en lazy, pas de DTOs séparés, travailler dans un environnement managé (dans le cas de JPA) que ce soit dans un serveur d'application ou dans un conteneur web + Spring.

Discussions similaires

  1. JSF EL Singleton design pattern
    Par jad_jad dans le forum JSF
    Réponses: 5
    Dernier message: 09/09/2008, 12h23
  2. Réponses: 11
    Dernier message: 02/11/2006, 17h12
  3. [GRASP] Est-ce que j'utilise correctement les design pattern?
    Par Tourix dans le forum Design Patterns
    Réponses: 7
    Dernier message: 21/06/2006, 18h27
  4. Qu'est ce que c'est le design pattern ?
    Par weed dans le forum C++
    Réponses: 18
    Dernier message: 22/04/2006, 14h32
  5. qu'est-ce que les design pattern ?
    Par airseb dans le forum Design Patterns
    Réponses: 1
    Dernier message: 23/11/2004, 08h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo