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

VB.NET Discussion :

POCO dans la couche DAL vs DTO


Sujet :

VB.NET

  1. #1
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut POCO dans la couche DAL vs DTO
    Bonjour à vous tous,

    cela fait un bout de temps que je lis les différentes discussions sur l'utilisation de POCO - DTO.

    J'ai bien lu les différents articles provenant de cette discussion :
    Ma question provient de cette discussion, où il est dit :
    Citation Envoyé par rv26t Voir le message

    Citation Envoyé par Kropernic Voir le message
    Après l'article :
    Vu que mettre des méthodes dans un DTO, c'est mal, je vais utiliser les objets de la couche BLL et faire un POCO.
    Du coup, ça donne :


    • Un DTO est un conteneur le plus léger possible et à ce titre, il ne contient que des propriétés et un constructeur.
    • La couche BLL consomme les méthodes de la couche DAL et reçoit en retour un DTO ou une liste de DTO.
    • La couche GUI consomme les méthodes de la couche BLL et reçoit en retour un POCO ou une liste de POCO.

    Où est-ce que je me plante ?
    Sur le 3ème point.

    La couche GUI consomme les méthodes de la couche BLL et reçoit en retour un DTO ou une liste de DTO. Seul le DTO transite entre les couches.


    Même si vous avez un POCO dans votre BLL vous ne transmettez que le DTO.
    Le POCO est une classe de votre BLL qui contiend un DTO (ou liste de DTO) et les méthodes qui les manipules. (Le POCO s'occupe de la partie logique métier uniquement, quand il a fait son travail, il renvoie le DTO)
    Mais j'ai du mal à comprendre, si mon POCO est l'objet métier qui contient toutes les méthodes métiers et que seul mon DTO doit passer dans les différentes couches. Comment peut-on interagir sur le DTO via la GUI ?

    Moi j'aurais stocké le POCO dans la GUI pour pouvoir appeler les différentes méthodes de mon POCO dans celle-ci.

    Bref je me perd, comme beaucoup visiblement sur la notion de POCO vs DTO et leurs utilisations

  2. #2
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Avec le recul, après avoir relu quelques fois les articles (si j'ai bien compris), je réalise qu'en fait un POCO n'est sensé servir qu'à la validation des données.

    Dans la BLL, il devrait donc en théorie y avoir encore un (ou plusieurs?) autre type d'objet à côté des POCO pour s'occuper du reste.

    Séparation que personnellement je passe à la trappe. Sur un très gros projet, je peux éventuellement envisagé l'utilité mais de mon côté, j'ai un objet BLL qui contient les méthodes de validation, les méthodes de persistances, les méthodes utilitaires, etc. .

    Voilà par exemple, une classe de la couche BLL du projet que je suis en train de développer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    Public Class Opening
        Public Property DTO As POP_DTO.Opening
     
        Public Sub Save()
            POP_DAL.Opening.Save(Me.DTO)
        End Sub
     
        Public Sub Delete()
            POP_DAL.Opening.Delete(Me.DTO)
        End Sub
     
    End Class
     
    Public Class Openings
        Public Property DTO As List(Of POP_DTO.Opening)
     
        Public Sub New()
            Me.DTO = New List(Of POP_DTO.Opening)
        End Sub
     
        Public Shared Function FetchAll(str_id As Byte, Optional year As Short = -1) As Openings
            If year = -1 Then
                year = Today.Year
            End If
     
            Dim ops As New Openings
            For Each d As POP_DTO.Opening In POP_DAL.Opening.GetAll(str_id, year)
                ops.DTO.Add(d)
            Next
            Return ops
        End Function
     
        Public Shared Function FetchByDates(str_id As Byte, debut As DateTime, Optional year As Short = -1) As Openings
            If year = -1 Then
                year = Today.Year
            End If
     
            Dim ops As New Openings
            For Each d As POP_DTO.Opening In POP_DAL.Opening.GetByDates(str_id, year, debut)
                ops.DTO.Add(d)
            Next
            Return ops
        End Function
     
        Public Shared Function FetchByWeek(str_id As Byte, week As Byte, Optional year As Short = -1) As Openings
            If year = -1 Then
                year = Today.Year
            End If
     
            Dim ops As New Openings
            For Each d As POP_DTO.Opening In POP_DAL.Opening.GetByWeek(str_id, year, week)
                ops.DTO.Add(d)
            Next
            Return ops
        End Function
     
        Public Function GetById(id As Integer) As Opening
            If (From o As POP_DTO.Opening In Me.DTO
                Where o.Id = id
                Select o).Count > 0 Then
                Dim op As New Opening
                op.DTO = (From o As POP_DTO.Opening In Me.DTO
                            Where o.Id = id
                            Select o).First
                Return op
            Else
                Return Nothing
            End If
        End Function
     
        Public Function GetByDate(d As DateTime) As Opening
            If (From o As POP_DTO.Opening In Me.DTO
                Where o.Debut.Date = d.Date
                Select o).Count > 0 Then
                Dim op As New Opening
                op.DTO = (From o As POP_DTO.Opening In Me.DTO
                            Where o.Debut.Date = d.Date
                            Select o).First
                Return op
            Else
                Return Nothing
            End If
        End Function
     
        Public Function GetByDay(d As System.DayOfWeek) As Opening
            If (From o As POP_DTO.Opening In Me.DTO
                 Where o.Debut.DayOfWeek = d
                 Select o).Count > 0 Then
                Dim op As New Opening
                op.DTO = (From o As POP_DTO.Opening In Me.DTO
                            Where o.Debut.DayOfWeek = d
                            Select o).First
                Return op
            Else
                Return Nothing
            End If
        End Function
    End Class
    N.B. : Je dois encore ajouter une méthode Save() et Delete() dans la classe Openings mais elle ne fera qu'appeler en boucle les méthodes correpondante dans la classe Opening à priori. Ca m'évitera d'avoir 2 procédures stockées différentes au niveau de la DB (une recevant un seul objet et une recevant recevant une liste d'objet).

    Bref, une classe au singulier qui contient un (seul) DTO et les méthodes de persistance vers la DB (ici il n'y a pas de méthodes utilitaire mais il pourrait y en avoir). Et une classe au pluriel qui contient une liste de DTO's, les méthodes de récupération depuis la DB et des méthodes utilitaire pour sélectionner un DTO précis de la liste.

    J'espère que ça aide :-/

  3. #3
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    A force de relire ce poste je me dis qu'en réalité rien n'interdit de stocker un POCO dans la GUI du moment qu'on ne le fait pas transiter d'une couche à une autre...
    Je suis dans le bon?

    EDIT : On a posté en même temps, je lis ta réponse

  4. #4
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    J'ai oublié de préciser...

    Au final, ma couche GUI instancie des objets de la couche BLL et utilise leur propriété DTO pour passer les données à afficher aux composants visuels.

  5. #5
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Merci pour tes interventions.

    J'ai bien compris ton nouveau modèle de donnée.

    Citation Envoyé par Kropernic Voir le message
    ...mais de mon côté, j'ai un objet BLL qui contient les méthodes de validation, les méthodes de persistances, les méthodes utilitaires, etc.
    C'est justement ça qui me gène personnellement, c'est d'avoir les méthodes/variables métier en dehors de mon DTO car tout l'avantage d'avoir une collection d'objet POCO serait d'avoir aussi accès à la logique métier.

    J'ai vraiment du mal à m'exprimer sur ce nouveau sujet mais en gros j'ai du mal à comprendre l'avantage de séparer autant les couches métier car cela oblige à tout coder 2 fois.
    Suivant cet article : Quelle est la différence entre un DTO et un POCO ?

    Je devrais faire un objet PersonRepository qui me retournerait des POCO person mais donc aurait les mêmes méthodes que ma couche DAL comme GetColPersonsByAge mais ces dernières méthodes ne serait qu'une surcharge qui bouclerait sur la collection de DTO pour en faire une collection de POCO. Du coup je me retrouve avec deux énumérations de collection juste pour séparer l'accès au donnée de la logique métier.
    Et au final je ne manipulerais que des POCO car c'est principalement dont j'ai besoin dans l'application pour valider les données, les transformées et les décorer.

    Cela oblige aussi dans le POCO de recoder toutes les propriétés du DTO pour y avoir accès directement comme dans la réponse de tomlev dans une de tes discussions ce que je trouve très peu pratique comme toi.
    Citation Envoyé par Kropernic Voir le message
    C'est pas faux.

    J'espérais juste pouvoir m'en passer car si mon modèle évolue, je devrai alors faire les modifs à 2 endroits. Une fois dans DTO et une fois dans BLL. C'est un peu dommage je trouve.
    Dans l'article il est dit :
    Pourquoi devrais-je faire tout ça ?
    Mais, je pense que la plupart des développeurs. NET seront amenés à utiliser des POCO et des Repositories (mais pas de DTO) via les ORM (NDT : mapping objet-relationnel). Entity Framework, NHibernate, et beaucoup de ces ORM exigent ou partent du principe que l'architecture est de type POCO.
    Du coup j'ai fortement envie de fusionner le repository et le DAL ainsi que le POCO et le DTO.

    J'avoue être complétement largué sur l'avantage d'autant de séparation.

    Si ma DAL me renvoyait directement mon POCO, plus besoin de repository.

  6. #6
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Billets dans le blog
    3
    Par défaut
    Ce sujet fait couler beaucoup d'encre ! Il n'y a pas de réponse toute tranchée.

    Effectivement dans certains cas, comme l'utilisation d'un ORM, on part du principe que derrière on utilise des POCO. Les DTO étant utilisés conjointement avec une DAL ordinale classique.

    Le fait d'avoir DAL + DTO + POCO double effectivement le travail puisqu'il faut coder 2 fois les mêmes propriété. Une alternative serait de dériver les POCO des DTO. Ainsi, le POCO expose les propriétés du DTO et lui ajoute la validation. On a également accès aux méthodes de persistence du DTO. Mais dans ce cas, on se retrouve dans une situation hybride.

    L'avantage de séparer les DTO et les POCO peut s'expliquer notament parce que d'un point de vue "logique", on a effectivement besoin de valider les données avant de les persister. Le fait d'avoir le cheminement suivant :
    UI --> Business --> POCO --> DTO --> DAL
    oblige à passer par la validation (POCO) et donc de déclencher une exception en amont de toute opération de persistence.

    Si on fusionne la couche POCO et la couche DTO, il faut s'obliger à appeler la/les méthodes de validation avant de persister les objets. C'est un peu comme si on était un peu plus "laxiste" vis à vis de la validation, car si demain un développeur oublie d'appeler la/les méthodes, il pourra persister des données potentiellement erronnées... Pour éviter cela on peut imaginer implémenter une interface (IValidation) par exemple qui serait appelée par le Business avant de passer à la main à la couche fusionnnée POCO/DTO.

    Il faut également considérer que sur des projets manipulant des objets complexes, il peut être utile de séparer la couche POCO de la couche DTO afin de s'y retrouver un peu plus facilement, et d'isoler la validation du reste. Mais sur des projets plus simples ça peut rajouter une couche pour pas grand chose.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  7. #7
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Tout le monde semble d'accord pour dire qu'un POCO ne sert qu'à la validation.

    Voici mon approche (mais cela tient peut-être du fait que j'ai les 2 casquettes là où je bosse) :

    Pourquoi m'embêter (pour rester poli) à valider les données avant de les envoyer vers la DB car de toute façon, si une donnée n'est pas valide, elle sera rejetée par la DB. Autant alors traité l'erreur retournée (cad informer l'utilisateur que la donnée X n'est pas bonne) et puis voilà.

    Pour ma part, s'il y a besoin de valider les données dans l'applicatif, c'est que le DBA a mal fait son job derrière pour la DB.**
    Personnellement, dans mes DB, je choisis les types de données adéquats et s'ils n'existent pas, je les fabrique.

    Bête exemple tout simple (avec MSSQLSRV) :
    Dernièrement, j'ai eu besoin de stocker dans une table un numéro de semaine. Non seulement j'utilise pour cette colonne le type tinyint afin de minimiser le stockage sur le disque mais en plus, je lui ajoute une contrainte check vérifiant que le nombre introduit est bien supérieur à 0 et inférieur à 54. De ce fait, plus besoin de valider le numéro de semaine encoder dans l'applicatif. La donnée en DB ne sera JAMAIS erronée.

    **Je me rends compte en écrivant ces lignes que cela n'est vrai que pour les applications avec persistances dans un SGDBR ou équivalent. Si on persiste par exemple dans un fichier texte, ça pue un peu... Quoi que avec le XML, on peut définir un template (XLT je crois) pour définir le format et donc les contraintes de validation... Quid de type de persistance nécessitant réellement une validation applicative ?

  8. #8
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2012
    Messages
    206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 206
    Par défaut
    J'ai envie de répondre c'est un peu comme sur internet lorsque tu stock des info tu vérifies en client (javascript, HTML5) et en serveur (php ou autre). Tu vérifies en client pour éviter d'attendre l'envoie et le retour de la requête et tu vérifie en partie serveur si quelqu'un à intercepter ton paquet pour le modifier ou si il a perdu des bout en route.

    La c'est un peu la même chose si tu as une erreur tu enverras pas ta requête et donc tu ne surchargeras pas ton serveur inutilement.

    Et pis avec ce que tu dis le dba peu se dire la même chose le développeur a pas fait son boulot il vérifie pas ce qu'il m’envoie.

  9. #9
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par chaparo Voir le message
    J'ai envie de répondre c'est un peu comme sur internet lorsque tu stock des info tu vérifies en client (javascript, HTML5) et en serveur (php ou autre). Tu vérifies en client pour éviter d'attendre l'envoie et le retour de la requête et tu vérifie en partie serveur si quelqu'un à intercepter ton paquet pour le modifier ou si il a perdu des bout en route.

    La c'est un peu la même chose si tu as une erreur tu enverras pas ta requête et donc tu ne surchargeras pas ton serveur inutilement.

    Et pis avec ce que tu dis le dba peu se dire la même chose le développeur a pas fait son boulot il vérifie pas ce qu'il m’envoie.
    C'est pas faux oui...

    Ca vient probablement du fait que dans ma boîte, c'est moi le dev ET le dba. Du coup, j'ai pas envie de le travail deux fois. Alors bien sûr, j'fais un minimum hein. Du genre par exemple le champ de saisie pour le nombre de semaine dont je parlais précédemment, j'ai mis un contrôle NumericUpDown avec la propriété Minimum sur 1 et Maximum sur 53. Mais bon, je ne (presque) plus de validation au niveau objet.

    Mais tu as raison !

  10. #10
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Par défaut
    Bonjour,

    Attention le DTO n'est pas une couche, c'est l'ensemble de données qui transite entre les couches.
    Le but étant de transférer entre les couches un objet de données minimal (pour être performant, notement lors de la lecture en BDD)

    Après la structure des couches applicatives n'a rien a voir avec les DTO.
    Vous pouvez très bien définir la structure de vos couches applicatives suivant la taille et le complexité de votre projet. Puis utiliser les DTO (pour être performent) ou pas (pour rester plus simple).

    @Kropernic
    Citation Envoyé par Kropernic Voir le message
    Tout le monde semble d'accord pour dire qu'un POCO ne sert qu'à la validation.
    Et de toute autre logique métier.

    Citation Envoyé par Kropernic Voir le message
    Pourquoi m'embêter (pour rester poli) à valider les données avant de les envoyer vers la DB car de toute façon, si une donnée n'est pas valide, elle sera rejetée par la DB. Autant alors traité l'erreur retournée (cad informer l'utilisateur que la donnée X n'est pas bonne) et puis voilà.
    Parceque là en terme de performance, ce n'est pas terrible.
    [Edit]Déjà dit pendant que j'écrivais[/Edit]

    @DotNetMat
    Citation Envoyé par DotNetMatt Voir le message
    Le fait d'avoir DAL + DTO + POCO double effectivement le travail puisqu'il faut coder 2 fois les mêmes propriété. Une alternative serait de dériver les POCO des DTO. Ainsi, le POCO expose les propriétés du DTO et lui ajoute la validation. On a également accès aux méthodes de persistence du DTO. Mais dans ce cas, on se retrouve dans une situation hybride.

    L'avantage de séparer les DTO et les POCO peut s'expliquer notament parce que d'un point de vue "logique", on a effectivement besoin de valider les données avant de les persister. Le fait d'avoir le cheminement suivant :
    UI --> Business --> POCO --> DTO --> DAL
    oblige à passer par la validation (POCO) et donc de déclencher une exception en amont de toute opération de persistence.
    Il me semble que vous avez mélangé les termes DTO et Repository, non ?

    @Sankasssss
    Ce qu'il faut percevoir dans l'article c'est que les DTO sont indépendant du reste.
    Avec la programmation en couche (DAL<->BLL (qui peut être décomposé en POCO et Repository)<->UI), les DTO représente un ensemble de données qui transites entre elles (pour être performant).

    Donc mon avis est d'utiliser les éléments dont on à besoin, comme le fait Kropernic.
    Il faut prendre les avantages de ces principes, mais ne pas vouloir à tout prix coller à ceux-ci (au risque de se créer du travail pour rien).

    Personnellement dans les DTO j'ai trouvé une solution pour ne pas utiliser forcément les outils plus conventionnels (dataset, etc) et travailler coté performance.
    Mais je n'utilise pas la structure POCO et Repository parceque justement pour l'instant je n'ai que peu de manipulation métier.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  11. #11
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Par défaut
    Je poste a nouveau,
    Mon précédant message était général

    ici je répond plus précisément à 2 remarques

    Citation Envoyé par Sankasssss Voir le message
    Je devrais faire un objet PersonRepository qui me retournerait des POCO person mais donc aurait les mêmes méthodes que ma couche DAL comme GetColPersonsByAge mais ces dernières méthodes ne serait qu'une surcharge qui bouclerait sur la collection de DTO pour en faire une collection de POCO. Du coup je me retrouve avec deux énumérations de collection juste pour séparer l'accès au donnée de la logique métier.
    Et au final je ne manipulerais que des POCO car c'est principalement dont j'ai besoin dans l'application pour valider les données, les transformées et les décorer.
    Pour la lecture effectivement c'est juste un autre appel. (c'est aussi ce qui m'embète)
    Pour l'enregistrement non
    Ex : avec les tests que j'avais fait par rapport aux exemple des tutos.
    Une DAL maison sous forme de DLL qui renvoie des DTO (avec des méthodes génériques).
    La BLL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Public Class BLLPerson
        Private PersDb As PersonDB = New PersonDB
     
        Public Function LitPersonneEMail(ByVal eMail As String) As PersonDTO
            Return PersDb.GetPersonByEmail(eMail)
        End Function
     
        Public Function LitPersonnes() As List(Of DTOBase)
            Return PersDb.GetAll()
        End Function
     
        Public Sub EnregistrePersonne(ByVal dtop As PersonDTO, ByVal inserer As Boolean)
            ' validation données
     
            'enregistre
            PersDb.EnregPerson(dtop, inserer)
        End Sub
     
    End Class
    Une partie DAL application
    La lecture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Public Class PersonDB
        Inherits clsDALAppli
     
        Public Function GetPersonByEmail(ByVal email As String) As PersonDTO
            Const K_REQUETTE As String = "select * from personnes where email = ?"
            Try
                DALApp.AjouteParam("email", DbType.String, email)
                Return DALApp.GetSingleDTO(Of DTOParser_Person)(K_REQUETTE)
            Catch ex As Exception
                '...
            End Try
            Return Nothing
        End Function
    L'enregistrement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
        ' avec le DTO 1 seul paramètre
        Public Sub EnregPerson(ByVal UnePersonne As PersonDTO, ByVal Ins As Boolean)
            Const K_REQUETTE_INSERT As String = "insert into personnes ([PersonId], [City], [Email], [ImAddress], [ImType], [LanguageId], [NamePers], [NickName], [Password], [PhoneHome], [PhoneMobile], [State], [TimeZoneId], [UtcCreated], [UtcModified], [ZipCode], [SpeakFrench]) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "
            Dim req As String = "update personnes set City=?, [Email]=?, [ImAddress]=?, [ImType]=?, [LanguageId]=?, [NamePers]=?, [NickName]=?, [Password]=?, [PhoneHome]=?, [PhoneMobile]=?, [State]=?, [TimeZoneId]=?, [UtcCreated]=?, [UtcModified]=?, [ZipCode]=?,SpeakFrench=? where PersonId = ?"
            Dim res As Integer
            If Ins Then req = K_REQUETTE_INSERT
            Try
                DALApp.EffaceListParam()
                If Ins Then DALApp.AjouteParam("PersonId", DbType.Int32, UnePersonne.PersonId)
                DALApp.AjouteParam("City", DbType.String, UnePersonne.City)
                DALApp.AjouteParam("Email", DbType.String, UnePersonne.Email)
                DALApp.AjouteParam("ImAddress", DbType.String, UnePersonne.ImAddress)
                DALApp.AjouteParam("ImType", DbType.Int32, UnePersonne.ImType)
                DALApp.AjouteParam("LanguageId", DbType.Int32, UnePersonne.LanguageId)
                DALApp.AjouteParam("NamePers", DbType.String, UnePersonne.NamePers)
                DALApp.AjouteParam("NickName", DbType.String, UnePersonne.NickName)
                DALApp.AjouteParam("Password", DbType.String, UnePersonne.Password)
                DALApp.AjouteParam("PhoneHome", DbType.String, UnePersonne.PhoneHome)
                DALApp.AjouteParam("PhoneMobile", DbType.String, UnePersonne.PhoneMobile)
                DALApp.AjouteParam("State", DbType.String, UnePersonne.State)
                DALApp.AjouteParam("TimeZoneId", DbType.Int32, UnePersonne.TimeZoneId)
                DALApp.AjouteParam("UtcCreated", DbType.Date, "20/05/2013")
                DALApp.AjouteParam("UtcModified", DbType.Date, "31/05/2013")
                DALApp.AjouteParam("ZipCode", DbType.Int32, 6)
                DALApp.AjouteParam("SpeakFrench", DbType.Boolean, True)
                If Not Ins Then DALApp.AjouteParam("PersonId", DbType.Int32, UnePersonne.PersonId)
     
                DALApp.ExecuterCommande(req, res)
            Catch ex As Exception
     
            End Try
     
        End Sub
    Utilisation en UI
    Lecture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            Dim p As PersonDTO = Persbll.LitPersonneEMail("Email")
    Citation Envoyé par Sankasssss Voir le message
    Cela oblige aussi dans le POCO de recoder toutes les propriétés du DTO pour y avoir accès directement comme dans la réponse de tomlev dans une de tes discussions ce que je trouve très peu pratique comme toi.
    Non, les méthodes reçoivent ou renvoient des dtos, on peut les manipuler
    On peut placer une propriété de type DTO dans le POCO, et on peut accéder aux propriétés internes du DTO.


    En utilisant les exemple ci-dessus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Dim p As PersonDTO = Persbll.LitPersonneEMail("Email")
            MessageBox.Show(p.PersonId)
    C'est une propriété du dto et je ne les ais pas redéfinies dans la BLL (ou POCO si je les avais utilisés).

    un ensemble de dto et de propriétés de celui-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Dim ListPers As List(Of DTOBase)
            ListPers = Persbll.LitPersonnes()
            For Each UnePersonne As PersonDTO In ListPers
                MessageBox.Show(UnePersonne.NamePers & " " & UnePersonne.NickName & " " & UnePersonne.SpeakFrench)
            Next
    Une mise à jour (par exemple celui lu auparavant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            p.City = "City"
            Persbll.EnregistrePersonne(p, False)
    Par contre à partir du moment ou l'on veut modifier les données du DTO avant de les passer à l'UI là il faut redéfinir le nouvel objet de données. (le tuto n'aborde pas ce cas) Il reste très vague sur toute autre logique métier.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  12. #12
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Je vous remercie tous pour vos excellentes participations qui m'ont permis d'y voir plus clair et d'être sûr que j'avais correctement compris ce fameux modèle qui parait lourd au premier abord.

    Concernant :
    Citation Envoyé par DotNetMatt Voir le message
    oblige à passer par la validation (POCO) et donc de déclencher une exception en amont de toute opération de persistence.
    pour ma part, dans mon model actuel (que je cherche à remplacer pour de meilleurs performances) où j'encapsule une dataRow (que l'on pourrait assimilé à un mélange POCO / DTO) afin d'avoir l'auto complétion de VS, je controle aussi les données en amont de la BD :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        Public Property pD_DOSSIER_NI() As Integer
            Get
                If IsDBNull(myRow("AFTNI")) Then Return 0
                Return myRow("AFTNI")
            End Get
            Set(ByVal value As Integer)
                If value < -9999999 Or value > 9999999 Then Throw New ArgumentException("Doit être comprit entre -9999999 et 9999999.", "DOSSIER_NI")
                If Not IsDBNull(myRow("AFTNI")) Then
                    If value = myRow("AFTNI") Then Exit Property
                End If
                myRow("AFTNI") = value
     
            End Set
        End Property
    Donc ma précédente idée de mélanger POCO et DTO passerait aussi (en modifiant juste le la méthode de validation vu que déclencher une exception n'est pas la meilleur chose à faire).

    @rv26t :

    Merci pour ton modèle, je vais regarder à ça.

    Concernant :
    Citation Envoyé par rv26t Voir le message
    Non, les méthodes reçoivent ou renvoient des dtos, on peut les manipuler
    On peut placer une propriété de type DTO dans le POCO, et on peut accéder aux propriétés internes du DTO.


    En utilisant les exemple ci-dessus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Dim p As PersonDTO = Persbll.LitPersonneEMail("Email")
            MessageBox.Show(p.PersonId)
    C'est une propriété du dto et je ne les ais pas redéfinies dans la BLL (ou POCO si je les avais utilisés).

    un ensemble de dto et de propriétés de celui-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Dim ListPers As List(Of DTOBase)
            ListPers = Persbll.LitPersonnes()
            For Each UnePersonne As PersonDTO In ListPers
                MessageBox.Show(UnePersonne.NamePers & " " & UnePersonne.NickName & " " & UnePersonne.SpeakFrench)
            Next
    Une mise à jour (par exemple celui lu auparavant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            p.City = "City"
            Persbll.EnregistrePersonne(p, False)
    Par contre à partir du moment ou l'on veut modifier les données du DTO avant de les passer à l'UI là il faut redéfinir le nouvel objet de données. (le tuto n'aborde pas ce cas) Il reste très vague sur toute autre logique métier.
    C'est ici que je coince à nouveau. Pour moi c'est sur un repository qui renvoie une liste de POCO et non DTO que je dois travailler. Aussi non je perds ma logique métier et toutes ces décorations qui me sont indispensable pour pouvoir faire des requêtes Linq sur la collection de POCO. Du coup le repository me retournant mes POCO ne sert plus à grand chose vu que l'on utilise la couche DAL et les DTO.

    Corrige moi si je me trompe mais même si je travaillais sur une collection de POCO, les seules éléments à transiter d'une couche à une autre resterait le DTO? Mais dans ce cas je suis obligé de garder le double codage des propriétés pour un affichage.

    Bon là je pense que j'ai besoin de relire cela quelque fois et de passer une bonne nuit à ingurgiter toutes ces infos.

    Demain je vais tester le système dans ça totalité sur un petit projet pour voir à l'utilisation car je vais présenter ces méthodes à l'ensemble du service d'ici peu pour voir si l'on adopte ce modèle (ou un dérivé).

  13. #13
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Par défaut
    Citation Envoyé par Sankasssss Voir le message
    @rv26t :

    Merci pour ton modèle, je vais regarder à ça.
    Attention c'est juste un ensemble de tests simplifiés pour cerner un peu les principes.
    Cela me fait penser que dans ma méthode EnregistrePersonne j'aurai pu utiliser la propriété IsNew du DTO, plutôt que de passer un paramètre.
    J'ai aussi un petit souci avec les génériques, mais qui n'empêche pas le fonctionnament.


    Citation Envoyé par Sankasssss Voir le message
    C'est ici que je coince à nouveau. Pour moi c'est sur un repository qui renvoie une liste de POCO et non DTO que je dois travailler. Aussi non je perds ma logique métier et toutes ces décorations qui me sont indispensable pour pouvoir faire des requêtes Linq sur la collection de POCO. Du coup le repository me retournant mes POCO ne sert plus à grand chose vu que l'on utilise la couche DAL et les DTOs.
    Attention, dans le tuto il n'indique jamais qu'un repository renvoie une liste de POCOs. Il travaille avec les DTOs. Personnellement j'aurais fait un seul POCO avec une propriété collection de dTOs.

    La, je ne vois pas suffisamment ce que tu envisages pour te donner une orientation. Ou plutôt je vois, mais le tuto ne donne pas la solution pour comment utiliser l'ensemble Repository et POCO.
    C'est aussi cet ensemble POCO et Repository qui m'embète. D'ou ma propre utilisation sans POCO/Repository. On va dire BLL plus classique.

    Par contre d'après ce qu'il me semble comprendre,
    un POCO peut avoir (pas forcément tout) :
    • Une propriété "collection de DTOs" (pour faire des requête Linq, ...) ;
    • Une propriété DTO (simple) ;
    • Des méthodes qui renvoient directement un DTO ou une liste de DTOs ;
    • Des méthodes qui utilisent les propriétés DTO (simple ou collection) pour éviter l'accès BDD tant que cela n'est pas utile.


    Ainsi dans le POCO on peut utiliser la logique métier sur le DTO (ou la collection de DTOs).
    Mais par exemple avec linq on peut créer un nouvel objet collection qui peut être différent de la collection DTO (structurellement je parle), et c'est là que le flou et les ennuis commencent (par contre, cela reste vrai qu'elle que soit l'architecture), après cela n'est pas forcément génant, on sais ce que l'on fait.

    Citation Envoyé par Sankasssss Voir le message
    Corrige moi si je me trompe mais même si je travaillais sur une collection de POCO, les seules éléments à transiter d'une couche à une autre resterait le DTO? Mais dans ce cas je suis obligé de garder le double codage des propriétés pour un affichage.
    Normalement je ne verrais qu'un seul POCO qui peut renvoyer un DTO ou une "collection de DTOs" donc pas de double codage des propriétés. (comme dans mon exemple).
    Et effectivement seul le dTO (ou collection de DTOs) transite entre les couches.

    C'est lié avec la remarque précédente (et ce que peut contenir le POCO), et à mon avis il faut "travailler"/"étudier les possibilités" dans ce sens là.
    Voir si tu utilises une BLL "classique" ou si tu la décompose en BLL "POCO/Repository"

    Note que ce ne sont que des remarques et suggestions personnelles. Espérant que cela t'aidera.

    Citation Envoyé par Sankasssss Voir le message
    Demain je vais tester le système dans ça totalité sur un petit projet pour voir à l'utilisation car je vais présenter ces méthodes à l'ensemble du service d'ici peu pour voir si l'on adopte ce modèle (ou un dérivé).
    C'est une très bonne approche pour ce faire une idée. Faudra nous présenter les grandes lignes (enfin si ce n'est pas confidentiel).

    Note : à ce que j'ai lu linq n'est pas l'idéal pour les performances.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  14. #14
    Membre Expert

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 067
    Par défaut
    Tout dépend du projet aussi, le faite d'utiliser un ORM te mènera naturellement vers l'utilisation des POCO.
    Personnellement j'ai une préférence pour l'utilisation de POCO, je n'utilise pratiquement jamais de DTO, j'aime bien que mon objet corresponde le plus à l'utilisation que je vais en faire plutôt que deux objets un pour le transit des données et l'autre pour le côté métier.
    Mais bon tout ça dépend du projet cible, sa taille, son utilisation...

  15. #15
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 436
    Par défaut
    Bonjour à tous ! Après 15 jours d'absence, me revoilà pour mettre mon grain de sel un peu partout

    Perso, je n'utilise plus les POCO depuis l'apparition des Portable Class Library : je préfère avoir une DLL qui pourra s'intégrer un peu partout qui peut valider soit un DTO soit une interface (un DTO implémente 1,N interfaces) du coup je peux valider une partie ou l'intégralité d'un DTO, d'un model Silverlight, d'un model WindowsPhone etc.

    Réutilisabilité côté client serveur et multi projet. Bien entendu on peut aussi faire ça avec les POCO. Mais pour valider un model qui reste côté projet UI, mes HelperValidation ou ServiceValidation apporte beaucoup plus.

  16. #16
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Citation Envoyé par rv26t Voir le message
    Attention c'est juste un ensemble de tests simplifiés pour cerner un peu les principes.
    T'inquiète j'avais bien compris.

    Citation Envoyé par rv26t Voir le message
    Cela me fait penser que dans ma méthode EnregistrePersonne j'aurai pu utiliser la propriété IsNew du DTO, plutôt que de passer un paramètre.
    J'ai aussi un petit souci avec les génériques, mais qui n'empêche pas le fonctionnament.
    Je suis aussi (enfin j'étais, avant une modification dans mes priorités) occupé à transposer le modèle des articles (VB.net oblige) et ce faisant, je me rend compte de certaine limite, comme la gestion des transactions. Du coup j'ai déjà adapté la couche DAL qui ne gère plus la fermeture des connexions.

    Citation Envoyé par rv26t Voir le message
    Attention, dans le tuto il n'indique jamais qu'un repository renvoie une liste de POCOs. Il travaille avec les DTOs. Personnellement j'aurais fait un seul POCO avec une propriété collection de dTOs.
    Pourtant c'est ce que j'avais ressenti en lisant :
    Citation Envoyé par Rudy Lacovara dans Quelle est la différence entre un DTO et un POCO ?
    En général, j'utilise un Repository. Pour cet exemple, j'ai utilisé une classe PersonRepository qui encapsule la logique pour obtenir un nouvel objet personne, obtenir un personDTO de la DAL, puis affecter person.Data = personDTO. Même chose pour la sauvegarde.
    un objet personne étant l'objet métier, donc le POCO qui encapsule via Data son DTO.

    Citation Envoyé par rv26t Voir le message
    La, je ne vois pas suffisamment ce que tu envisages pour te donner une orientation. Ou plutôt je vois, mais le tuto ne donne pas la solution pour comment utiliser l'ensemble Repository et POCO.
    Pour être sûr que l'on se comprenne bien, je cherche à avoir une collection d'objet métier (POCO) afin de pouvoir garder la logique métier et travailler dessus.
    Par exemple si mon POCO implémente le pattern état, on aura donc des propriétés supplémentaire gardant l'état de la personne en mémoire et définissant le comportement de mon POCO.
    Mais si à chaque fois que je transfère mon DTO d'une couche à une autre je perds mon état, il doit être recalculé à chaque action sur ce dernier ce que je ne trouve pas pratique.

    Malheureusement non, le tuto ne montre pas l'utilisation du modèle et je pense que c'est là qu'il y a un fameux manque même si je me rend bien compte qu'il n'y a pas qu'un type d'utilisation, tout dépend bien sur comme il a été dit plusieurs fois dans la discussion, notamment par youtpout978, de la taille du projet et de son orientation (traitement de nuit? interface utilisateur? service? etc...). Il n'y a malheureusement pas de recette miracle. (ou heureusement aussi non on s'ennuierait).

    Citation Envoyé par rv26t Voir le message
    C'est aussi cet ensemble POCO et Repository qui m'embète. D'ou ma propre utilisation sans POCO/Repository. On va dire BLL plus classique.

    Par contre d'après ce qu'il me semble comprendre,
    un POCO peut avoir (pas forcément tout) :
    • Une propriété "collection de DTOs" (pour faire des requête Linq, ...) ;
    • Une propriété DTO (simple) ;
    • Des méthodes qui renvoient directement un DTO ou une liste de DTOs ;
    • Des méthodes qui utilisent les propriétés DTO (simple ou collection) pour éviter l'accès BDD tant que cela n'est pas utile.


    Ainsi dans le POCO on peut utiliser la logique métier sur le DTO (ou la collection de DTOs).
    J'ai une impression que tu mélanges deux concepts ici, le repository et le POCO car pour moi, le repository n'est qu'une couche d'accès permettant de retourner des POCO en chargeant la DAL qui va lui fournir les DTO à encapsuler dans le POCO.

    En gros le repository pour moi est une sorte de contrôleur, ou plutôt de fabrique métier.

    Un POCO peut bien sur avoir tous les éléments que tu as cité :
    • Une propriété "collection de DTOs" (pour faire des requête Linq, ...) ;
    • Une propriété DTO (simple) ;
    • Des méthodes qui renvoient directement un DTO ou une liste de DTOs ;
    • Des méthodes qui utilisent les propriétés DTO (simple ou collection) pour éviter l'accès BDD tant que cela n'est pas utile.

    vu que c'est mon objet métier.
    Par exemple mon POCO personne peut contenir des méthodes lui retournant par exemple une list(Of RendezVous), RendezVous étant aussi un objet métier encapsulant son RendezVousDTO

    Citation Envoyé par rv26t Voir le message
    Mais par exemple avec linq on peut créer un nouvel objet collection qui peut être différent de la collection DTO (structurellement je parle), et c'est là que le flou et les ennuis commencent (par contre, cela reste vrai qu'elle que soit l'architecture), après cela n'est pas forcément génant, on sais ce que l'on fait.
    Oui bien sur, c'est là la force de Linq, on pourrait faire un distinct sur différent critère nous retournant une nouvelle liste qui n'est plus du type d'origine. Mais l'avantage avec une entrée de POCO (comme je les vois ^^) serait aussi de pouvoir directement faire une requête Linq pour voir les peronnes ayant été absent à 4 rendezVous (On est d'accord que ce n'est pas la meilleur approche et qu'il vaudrait mieux, pour des raison de performance, faire ça sur la BD) ou pour reprendre mon exemple de pattern état, nous sortir un groupement sur un état donné qui lui a été défini par plusieurs valeurs de personne.

    Citation Envoyé par rv26t Voir le message
    Note que ce ne sont que des remarques et suggestions personnelles. Espérant que cela t'aidera.
    C'est une très bonne approche pour ce faire une idée. Faudra nous présenter les grandes lignes (enfin si ce n'est pas confidentiel).
    T'inquiète, c'est bien comme cela que je prends toutes participations à une discussion et je peux te dire que cela m'est grandement bénéfique. J'ai déjà une idée plus claire de ce que je pense avoir compris.
    Je verrai où cela m’amène et si j'ai quelque chose de concret ce sera peut-être l'occasion de mon premier billet de blog, mais on en est encore loin.

    Citation Envoyé par youtpout978 Voir le message
    Personnellement j'ai une préférence pour l'utilisation de POCO, je n'utilise pratiquement jamais de DTO, j'aime bien que mon objet corresponde le plus à l'utilisation que je vais en faire plutôt que deux objets un pour le transit des données et l'autre pour le côté métier.
    Mais bon tout ça dépend du projet cible, sa taille, son utilisation...
    C'est un peu ce que je pensais en début de discussion car cela ressemble à mon modèle actuel a deux niveaux, un POCO et un DAL.
    Comme dit plus haut je vais quand même essayer le modèle complet sur un petit projet pas important pour bien le comprendre et voir ce qu'il pourrait m'apporter sur des plus gros projet.

    Citation Envoyé par Kikuts Voir le message
    Perso, je n'utilise plus les POCO depuis l'apparition des Portable Class Library : je préfère avoir une DLL qui pourra s'intégrer un peu partout qui peut valider soit un DTO soit une interface (un DTO implémente 1,N interfaces) du coup je peux valider une partie ou l'intégralité d'un DTO, d'un model Silverlight, d'un model WindowsPhone etc.

    Réutilisabilité côté client serveur et multi projet. Bien entendu on peut aussi faire ça avec les POCO. Mais pour valider un model qui reste côté projet UI, mes HelperValidation ou ServiceValidation apporte beaucoup plus.
    Je pense que l'on transgresse de nouveau le terme DTO dans ce cas vu que c'est censé être l'objet le plus léger possible il ne devrait pas implémenter d'interface et donc avoir une partie métier. Donc dans ce cas ce que tu considère comme DTO est en fait un POCO donc ton modèle correspond à celui de youtpout978 non ?

    Je vais me renseigner sur les Portable Class Library car je ne connais pas ce terme.


    Décidément ces articles n'ont pas fini de nous faire écrire

  17. #17
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Par défaut
    Bonjour, sans vouloir polluer le topic je suis impressionné par le niveau. Ça m'aurait bien aidé d'avoir ces notions de modèles ou de couches quand j'ai démarré mon projet il y a 3 ans mais là je dois dire que je ne comprends pas tout. Je suis juste un amateur et je programme après le boulot quand j'en ai le temps. J'ai du trouver l'architecture de mon programme tous seul et en même temps ça m'a permis de bien comprendre ce que je faisais. A priori dans le monde professionnel vous utilisez tous un ou plusieurs modèles plus ou moins ressemblant sur le principe et sur l'utilisation que vous en faite. Bref je ne pourrais rien apporter de plus a la discussion. Je voulais juste vous remercier pour m'avoir apporté de l'aide quand j'avais besoin et ça m'a motivé pour enfin venir au bout de 2 programmes qui ont demandé beaucoup d'effort mais je suis plus que satisfait du résultat. Donc merci a vous tous.

  18. #18
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Citation Envoyé par BasicZX81 Voir le message
    A priori dans le monde professionnel vous utilisez tous un ou plusieurs modèles plus ou moins ressemblant sur le principe et sur l'utilisation que vous en faite.
    Oui et non. Quand un problème est standard, les réponses le sont aussi. Or l'interfaçage avec une base de données est un problème standard avec des répercussions sur tout le programme. Mais ce besoin n'est pas présent dans toutes les applications.

  19. #19
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Par défaut
    Citation Envoyé par Sankasssss Voir le message
    J'ai une impression que tu mélanges deux concepts ici, le repository et le POCO car pour moi, le repository n'est qu'une couche d'accès permettant de retourner des POCO en chargeant la DAL qui va lui fournir les DTO à encapsuler dans le POCO.

    En gros le repository pour moi est une sorte de contrôleur, ou plutôt de fabrique métier.
    C'est plutôt que j'avais bien perçu le but de chacun d'eux, mais pas l'interaction entre les 2 et comment les utiliser ensembles. (vu que j'en avais pour l'instant pas spécialement besoin, je n'avais pas trop cherché) Maintenant c'est très clair, et effectivement cela semble très intéressant. Merci.


    Citation Envoyé par Sankasssss Voir le message
    Pourtant c'est ce que j'avais ressenti en lisant :
    Envoyé par Rudy Lacovara dans Quelle est la différence entre un DTO et un POCO ?
    En général, j'utilise un Repository. Pour cet exemple, j'ai utilisé une classe PersonRepository qui encapsule la logique pour obtenir un nouvel objet personne, obtenir un personDTO de la DAL, puis affecter person.Data = personDTO. Même chose pour la sauvegarde.
    un objet personne étant l'objet métier, donc le POCO qui encapsule via Data son DTO.
    Je suis bien d'accord avec toi,
    Ce qui peut être représenté par son exemple de code :
    (Article de Rudy Lacovara "Quelle est la différence entre un DTO et un POCO ?" chapitre "Alors qu'est-ce qu'un POCO ?" 2ème exemple de code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Alimenter l'instance à partir de la base de données :
    Person person = PersonRepository.GetPersonByEmail(email);
    Mais dans le cas d'une liste de DTO (GetPersonList();), je pensais toujours utiliser un POCO qui encapsule une collection DTO (mais j'y reviens plus loin)
    Ce qui m'avait orienté dans ce sens est cette définition :
    (Article de Rudy Lacovara "Quelle est la différence entre un DTO et un POCO ?" chapitre "Qu'est-ce qu'un Data Transfer Object (DTO) ?" fin du 2ème paragraphe)
    Parce qu'il fait un excellent conteneur de données, léger et fortement typé, lorsque vous souhaitez déplacer les données de votre DAL (NDT : couche d'accès aux données) à votre BAL ou entre les je-ne-sais-quelles couches de votre architecture n-tiers.
    Citation Envoyé par Sankasssss Voir le message
    Pour être sûr que l'on se comprenne bien, je cherche à avoir une collection d'objet métier (POCO) afin de pouvoir garder la logique métier et travailler dessus.
    Par contre on est bien d'accord qu'un POCO est un ensemble de propriétés + les méthodes qui les manipulent. C'est là qu'utiliser une collection de POCO me dérange.

    Seulement là tu dupliques toutes les méthodes du POCO pour chaque élément de la collection (sauf si tu les déclare Shared, perso je n'aime pas trop), et je ne pense pas que ce soit le but.
    D'ou mon idée d'un POCO qui encapsule une liste de DTO.
    Note que cela est vrai uniquement lorsque l'on reste dans des manipulations de données simple et que l'on passe la liste DTO à l'UI.

    Citation Envoyé par Sankasssss Voir le message
    Par exemple si mon POCO implémente le pattern état, on aura donc des propriétés supplémentaire gardant l'état de la personne en mémoire et définissant le comportement de mon POCO.
    Mais si à chaque fois que je transfère mon DTO d'une couche à une autre je perds mon état, il doit être recalculé à chaque action sur ce dernier ce que je ne trouve pas pratique.
    ...
    Oui bien sur, c'est là la force de Linq, on pourrait faire un distinct sur différent critère nous retournant une nouvelle liste qui n'est plus du type d'origine. Mais l'avantage avec une entrée de POCO (comme je les vois ^^) serait aussi de pouvoir directement faire une requête Linq pour voir les peronnes ayant été absent à 4 rendezVous (On est d'accord que ce n'est pas la meilleur approche et qu'il vaudrait mieux, pour des raison de performance, faire ça sur la BD) ou pour reprendre mon exemple de pattern état, nous sortir un groupement sur un état donné qui lui a été défini par plusieurs valeurs de personne.
    Justement, c'est là que le modèle DTO commence a être mis à mal.
    A partir du moment où l'on commence à travailler sur l'objet DTO et à le transformer le modèle DTO ne correspond plus.
    A partir de ce niveau il faut faire d'autres choix.
    Par exemple passage de DTO entre DAL et BLL, et utilisation de POCO et Repository. L'UI ne recevant pas de DTO (sauf cas simple) mais d'autres objets (tiré des POCO).
    Cela génère pas mal de questions sur comment concevoir, notamment au niveau des propriétés pour le POCO.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  20. #20
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    je sens qu'on s'enlise mais ca a du bon car ça m'oblige à relire les articles non stop pour être sûr que je ne suis pas à coté de la plaque...

    Citation Envoyé par rv26t Voir le message
    Par contre on est bien d'accord qu'un POCO est un ensemble de propriétés + les méthodes qui les manipulent. C'est là qu'utiliser une collection de POCO me dérange.

    Seulement là tu dupliques toutes les méthodes du POCO pour chaque élément de la collection (sauf si tu les déclare Shared, perso je n'aime pas trop), et je ne pense pas que ce soit le but.
    Pourquoi mettre des méthodes en shared puisqu'elles doivent travailler sur les données contenues dans le DTO? Elles ne pourraient plus le faire si elles étaient en Shared.

    Par exemple avec le code donné par Rudy Lacovara dans son article :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    public class Person : BALBase
    {
            // Data
            // Cette propriété existe pour tous les objets de la BAL, et elle est
            // du type DTO correspondant. Il s'agit du mécanisme
            // que nous utilisons pour mettre en oeuvre un héritage "a un"
            // (NDT : aussi appelé composition) au lieu d'un héritage "est un".
            public PersonDTO Data { get; set; }
     
     
            // Person - constructeur par défaut
            public Person() {this.Data = new PersonDTO();}
            // Person - prend un DTO
            public Person(PersonDTO dto) {this.Data = dto;}
     
     
            // Validation
            public override List<ValidationError> Validate()
            {
                // Appelle toutes les fonctions de validation
                Val_Name();
                Val_Email();
                Val_Password();
                Val_TimeZone();
                Val_City();
                Val_State();
                Val_ZipCode();
                Val_ImType();
     
                // Si la liste ValidationErrors est vide, alors
                // nous avons passé la validation avec succès.
                return this.ValidationErrors;
            }
     
     
            // Méthodes de validation :
            // Il y a seulement 2 exigences sur les méthodes de validation.
            // - Elles doivent gérer l'ajout d'une erreur de validation à la
            //   liste ValidationErrors si elles trouvent une erreur.
            // - Vous devez ajouter manuellement l'appel à toutes les méthodes de
            //   validation à la fonction Validate().
            // Lorsque vous créez un objet ValidationError, souvenez-vous
            // que le premier paramètre est le nom exact du champ
            // qui a la mauvaise valeur, et le message d'erreur ne doit pas
            // contenir le nom du champ, mais plutôt le tag <FieldName>,
            // qui sera remplacé par l'interface utilisateur ou par l'application appelante.
     
     
            // Val_Name
            public bool Val_Name()
            {
                // Nom requis
                if (this.Data.Name == DTOBase.String_NullValue)
                {
                    this.ValidationErrors.Add(new ValidationError("Person.Name", "<FieldName> est requis"));
                    return false;
                }
                else
                {
                    return true;
                }
            }
     
            // Vous avez compris l'idée. Je ne mets pas le reste du code de 
            // validation pour que vous ne deveniez pas aveugle en lisant toutes ces lignes.
    }

    On peut voir que la logique de validation s'applique sur le DTO correspondant au POCO, et en plus la remarque dans le code est clair :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            // Data
            // Cette propriété existe pour tous les objets de la BAL, et elle est
            // du type DTO correspondant. Il s'agit du mécanisme
            // que nous utilisons pour mettre en oeuvre un héritage "a un"
            // (NDT : aussi appelé composition) au lieu d'un héritage "est un".
            public PersonDTO Data { get; set; }
    Il parle bien d'un héritage un à un, donc un DTO à toujours son équivalent POCO qui l'encapsule.

    Donc pour moi le POCO est bien un objet servant à contenir la logique métier du DTO qui ne peut pas en avoir.

    C'est vraiment dommage qu'il n'y ai pas plus d'exemple sur le net (ou qu'il soit si dur d'en trouver). en plus les définitions que l'on trouve sont elle aussi très basique et n'en disent pas beaucoup plus. Les diverses discussions mélangent sans cesse DTO et POCO vu que les ORM n'utilisent que des POCO sans DTO comme dans cet article : Utilisation d'entités POCO (Entity Framework)

Discussions similaires

  1. Domain-Driven Design: DAL, DAO, DTO, POCO, Repo et contextes
    Par Finality dans le forum Entity Framework
    Réponses: 1
    Dernier message: 19/07/2012, 13h10
  2. Réponses: 9
    Dernier message: 23/04/2012, 17h36
  3. Dessiner dans une couche d'un JLayeredPane ?
    Par eikichi972 dans le forum 2D
    Réponses: 2
    Dernier message: 05/12/2008, 05h05
  4. Quel code dans la couche services ?
    Par speedster dans le forum Spring
    Réponses: 9
    Dernier message: 24/04/2007, 11h01
  5. Exploitation de GregorianCalendar, Date dans une couche DAO
    Par wdionysos dans le forum Collection et Stream
    Réponses: 8
    Dernier message: 10/01/2006, 19h04

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