2010-10-11 16 views
18

J'ai une application MVC2 n-tier (DAL, domaine, service, web MVC) en utilisant une approche DDD (Domain Driven Design), ayant un modèle de domaine avec référentiels. Ma couche de service utilise un modèle de requête/réponse , dans lequel les objets Request et Response contiennent des objets DTO (Data Transfer Objects) pour rassembler les données d'une couche à la suivante et le mappage est effectué via l'aide d'AutoMapper. Ma question est la suivante: quelle forme devrait normalement prendre un DTO? Peut-il avoir imbriqué/complexe DTO aussi bien ou devrait-il être strictement une plate projection? Ou peut-être un mélange des deux? En outre, quelles sont les principales raisons d'avoir un DTO plat par rapport à un DTO plus complexe/imbriqué?Forme DTO: plate, complexe/imbriquée, ou un mélange des deux

Par exemple, supposons que j'avais un domaine tel que:

public class Employee 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public Company Company { get; set; } 
} 
public class Company 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
} 

Il existe trois façons différentes que j'ai pensé de modéliser l'objet Response.

Option 1 - l'option plus sec:

public class GetEmployeeResponse 
{ 
    public class EmployeeDTO { get; set; } // contains a CompanyDTO property 
} 

De la recherche que je l'ai fait, il serait inapproprié pour un DTO de prendre une forme similaire à l'objet de domaine (s) comme démontré ci-dessus .

Option 2 - une projection aplatie du domaine (anti-DRY):

public class GetEmployeeResponse 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string CompanyName { get; set; } 
    public string CompanyAddress { get; set; } 
    public string CompanyCity { get; set; } 
    public string CompanyState { get; set; } 
} 

Ceci est plus simple, comme un DTO devrait apparemment être, mais en fin de compte fait pour plus DTO.

Option 3 - un mélange des deux:

public class GetEmployeeResponse 
{ 
    public EmployeeDTO Employee { get; set; } 
    public CompanyDTO Company { get; set; } 
} 

Cela permet le code d'être un peu plus sec, réutilisable et facile à gérer, et ne pas exposer ma structure de domaine à l'utilisateur final . L'autre avantage principal est que d'autres réponses, comme GetCompanyResponse pourraient simplement retourner CompanyDTO, sans avoir à faire une copie de toutes ces propriétés, semblable à l'option 2. Que pensez-vous? Quelle option avez-vous prise et/ou avez-vous utilisée pour vous? Si ces demandes/réponses sont exposées ultérieurement en tant que méthodes de service WCF, votre réponse change-t-elle?

+1

Pourquoi construire une application MVC n-tier en premier lieu? Je ne dis pas que c'est faux. Juste être curieux quel avantage vous obtenez en mettant des services entre votre modèle de domaine et le niveau Web –

+1

Je veux juste répondre à un commentaire spécifique que vous avez fait: "faire une copie de toutes ces propriétés". Une fois que votre système atteint un certain seuil de complexité, il peut être préférable d'avoir un modèle de lecture dédié qui est dénormalisé au niveau de la base de données (soit par des vues, soit à votre configuration ORM). Quand j'ai commencé à faire cela, cela m'a permis de construire des modèles de domaines beaucoup plus complexes parce que je n'avais pas à m'inquiéter du coût de l'hydratation pour les requêtes.Je veux dire, pourquoi hydrater plusieurs modèles si vous allez juste les dénormaliser? Laissez la DB faire cela. C'est ce que c'est bon de toute façon. – Ryan

+0

@Szymon Il y a BEAUCOUP d'avantages à avoir un niveau de service. Pour moi, le plus grand avantage est que je peux mettre toute la sécurité dans une couche et ne pas laisser couler dans mes contrôleurs. – Ryan

Répondre

11

Ma préférence personnelle serait d'essayer de rester aussi plat que possible avec seulement les données requises étant transférées. Après avoir dit que j'ai utilisé le DTO profondément imbriqué dans le passé parce que cela avait du sens à l'époque et correspondait aux exigences. donc je suppose que cela se résume à "ça dépend". À la fin de la journée, allez avec ce qui est logique pour l'application à portée de main. Il est inutile d'essayer de faire passer les données du klaxon dans une convention DTO qui ne correspond pas à ce que vous cherchez à obtenir.

+0

Aka - Ne jetez pas le bon sens par la fenêtre juste pour obtenir un motif de conception ambigu et vague (DTO). ;) Comment stockez-vous des informations hiérarchiques (catégories de produits) dans un DTO plat? – jfar

+0

@jfar Un des facteurs que je regarde, est le bavardage de l'application. S'il y a beaucoup de trafic sur le réseau (ie le client demande beaucoup de petites informations) juste pour afficher la page d'information, je chercherais à la consolider en une demande d'information et à renvoyer les données dans un format qui conviendrait . –

+0

@jfar Si cela correspondait à la je voudrais probablement dénormaliser, de sorte que vous avez inclus la catégorie dans le cadre du produit. Comme je l'ai dit dans ma réponse, je préfère le garder aussi plat que possible, mais cela ne veut pas dire qu'il devrait être plat comme une crêpe. Si un DTO hiérarchique facilite l'écriture et la maintenance du code dans la langue de votre choix, alors je choisirais cette route comme je l'ai fait dans le passé en utilisant des services Web avec MS InfoPath. Essayer d'aplatir le DTO n'a pas de sens dans ce cas. les besoins en données de l'application définissent le DTO. –