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

Autres Discussion :

DAL - BLL et objets "Composés"


Sujet :

Autres

  1. #1
    Membre habitué Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Points : 174
    Points
    174
    Par défaut DAL - BLL et objets "Composés"
    Bonjour à tous,

    Je me triture le méninges depuis quelques temps sur ce que dois renvoyé la couche DAL.
    Je suis bien concient que dans la DAL ou dois faire globalement les opérations CRUD.

    Mais comment gère-t-on le cas d'objets composés?
    Prenons un exemple:
    Un fournisseur livre des commandes.
    Donc j'ai bien les classes Fournisseur et Commande.
    Dans la classe Fournisseur j'ai une données membre List<Commande>.

    De cette façon une instance de Fournisseur "connait" ses Commandes.
    Ensuite, une Commande doit connaitre le Fournisseur qui la livre. On passe bien une Commande à un Fournisseur défini, on ne la jette pas en l'air et les articles sont livrés.
    Donc dans la classe Commande je dois bien avoir une référence vers le Fournisseur qui la livre.

    On obtient donc cette relation bilatérale:
    Fournisseur 1 <------->* Commande


    Ma question est: Comment et dans quelle couche vous faites ces associations? DAL? BLL?
    Est-ce que la méthode de la DAL GetFournisseurById, renvoie le fournisseur avec sa collection de commande "alimentée" ou elle ne renvoie que le fournisseur (sans ses commandes)? Dans ce dernier cas, ce sera donc la BLL qui sera en charge d'alimenter la collection des Commande du fournisseur avec la liste des commandes obtenues depuis la méthode DAL GetCommandeByFournisseur(string idFournisseur).

    Faites-vous ce genre de relations? Ou bien, vous ne conservez que l'identifiant du fournisseur de la classe Commande et dans la classe Fournisseur vous conservez la collection des Commandes?

    Je vous remercie d'avance pour vos réponses.

    PS: Si quelqu'un avait un exemple concret et global de ce genre de cas, je suis totalement preneur.

  2. #2
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Points : 3 510
    Points
    3 510
    Billets dans le blog
    2
    Par défaut
    Les règles que j'utilise sont issues du DDD (Domain Driven Design). Et pour bien comprendre il faut en revenir à la sémantique et donc.......à une vision UML des relations entre tes classes (UML ou autre mais c'est pour utiliser des termes standards, pour que l'on se comprenne).

    Donc l'idée est que les choses dépendent non pas des multiplicités que tu as au bout de tes relations mais avant tout de la nature de ces relations. Je veux donc dire est-ce que la relation est de type : association simple, agrégation ou composition ?
    Ensuite, dans le cas d'association de type composition ou agrégation, tu pars de l'objet composite (celui qui est du côté du losange) et le DAL de cet objet (ok, cette classe), va récupérer l'objet lui-même (ton findById) et les relations de type composition ou agrégation. Tu peux faire cela automatiquement si tu as un ORM en déclarant les relations "eager" (mais si tu as un ORM, les déclarer "lazy" marchera quand même tant que tu restes dans un contexte transactionnel).
    Pour les objets qui sont des "composants" (pas du côté du losange), tu n'as a priori pas de DAL car ils sont toujours récupérés dans le contexte de leur composite, quand tu récupères le composite. Si la logique de ton application fait que tu as besoin de DAL pour ces composants, tu auras toujours la PK du composite en paramètre.
    Pour les objets qui n'ont pas de relations d'agrégation ou composition, le DAL ne récupère que les relations qui ont une multiplicité égale à 1 et ce sur un seul niveau (car tu pourrais suivre ce résonnement de proche en proche et alors tu risques de ramener trop d'objets, voir la base en entier ). Pour les autres cas (0..1, 1..*, 1..N), tu as des findLesTrucsDeMonMachin(pkMachin) pour toute relation.
    Dans le cas de relations bi-directionnelles, là c'est en fonction de la logique de ton application que tu mettras un findLesTrucsDeMonMachin dans les 2 DAL (les DAL des classes aux extrémités de ta relation) ou uniquement dans l'une d'elles. Mais là aussi, si tu as un ORM, tu n'as pas trop à te soucier de ça sauf à regarder les perfs et donc voir s'il faut déclarer des relations eager ou lazy.

    J'espère t'avoir un peu éclairé....

  3. #3
    Membre habitué Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Points : 174
    Points
    174
    Par défaut
    Merci,

    Je comprend bien le concept. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class DAOCommande{
    ....
    public Commande GetByID(string numCommande){
    //renvoi la commande et ses lignes
    }
    }
    En revanche, pour l'obtention des lignes de commandes je serais passé par la méthode DAOLigneCommande.GetLignesDeCommande(String numCommande)

    Maintenant je ne comprends pas comment tu évites la propagation pour les multiplicités 1 dont tu fais mention
    Pour les objets qui n'ont pas de relations d'agrégation ou composition, le DAL ne récupère que les relations qui ont une multiplicité égale à 1 et ce sur un seul niveau (car tu pourrais suivre ce résonnement de proche en proche et alors tu risques de ramener trop d'objets, voir la base en entier ).
    Comment tu implémentes cela?

    J'aurais fait des appels aux DAO "voisins", comme je l'aurais fait avec la méthode DAOLigneCommande.GetLignesDeCommande(String numCommande).
    Donc pas "d'arret" aux voisins directs.

    Je tiens à préciser que je ne peux pas utiliser d'ORM. L'architecture de la BD ne respecte pas la notion de clé étrangère sur clé primaire. Donc Entity Framework ne génère pas de "Propriété de navigation".

    Encore merci.

  4. #4
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 918
    Points
    2 918
    Par défaut
    Bonjour,

    Quelques remarques :

    • Domain Driven Design utilise le pattern Repository (similaire à ton DAO). En général, un Repository ne va pas en appeler un autre puisqu'il se cantonne aux limites d'un Agrégat et ne retourne des objets que d'un type de Racine d'Agrégat. Difficile d'expliquer tout sans rentrer dans les détails, mais un Agrégat est une délimitation métier et, idéalement, transactionnelle dans ton modèle du domaine. La tête de l'agrégat, l'objet métier par lequel on est obligé de passer pour accéder aux objets qu'il agrège, est appelé Racine d'Agrégat.

    • Si un Repository n'en appelle pas un autre, en revanche rien n'interdit à un objet appelant de coordonner plusieurs appels à des Repository différents pour reconstituer le graphe d'objets dont il a finalement besoin. En effet, une Racine d'Agrégat peut en référencer une autre - une bonne pratique est de ne pas modéliser cela via une propriété de navigation mais grâce à un simple ID.

    • Il est souvent déconseillé d'avoir des relations bi-directionnelles entre objets. Cela amène des problèmes de synchronisation des propriétés des 2 objets. En général, il existe un sens naturel de la relation qu'on peut détecter en regardant quel objet est chargé le premier en mémoire au cours des use cases. Typiquement, les racines d'agrégat sont souvent accédées en premier et on a souvent une référence à la racine sur laquelle on raisonne, il n'y a donc pas besoin d'une association allant d'un objet d'un agrégat vers sa racine.

    • Entity Framework Database First ne permet peut-être pas de modéliser des entités à partir de tables qui n'ont pas de foreign keys, mais je pense que c'est faisable en Code First. En tout cas, NHibernate le permet. Non pas que ça soit une très bonne idée : sans intégrité référentielle, la cohérence des données n'est pas garantie et les performances peuvent être affaiblies (à moins qu'on ait créé des index non reliés à des FK).


    Voilà, c'est une approche parmi d'autres Je la trouve pas mal car on évite d'avoir des dizaines de DAO qui s'appellent les uns les autres et ça oblige à penser son modèle du domaine en termes de grappes d'objets fonctionnellement cohérentes. Un autre bénéfice est que ça permet de contrôler les règles métier et invariants très facilement en un seul endroit puisque l'agrégat est le point d'accès unique aux objets qu'il contient.

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