2016-03-01 1 views
3

Mon équipe développe une application web api en utilisant le framework d'entité, Le Gui est développé par une équipe séparée.Séparation de modèles dans une application web api

Ma question est de savoir comment les modèles devraient être définis? Devrions-nous avoir deux projets - un pour les modèles de domaine (entités de base de données) et un pour Dtos qui sont sérialisables?

D'où devrait sortir l'analyse de Dto vers les modèles de domaine et quand devrait-elle se faire dans le sens opposé?

De plus, il est parfois nécessaire d'envoyer toutes les données aux clients. Faut-il créer un D pour ces cas? Ou devrais-je retourner un modèle de domaine?

Répondre

3

De manière générale, il est préférable de ne pas laisser vos entités (modèles de base de données) s'échapper de votre couche de base de données. Cependant, comme pour tout ce qui concerne les logiciels, cela peut avoir ses inconvénients. Un tel inconvénient est qu'il commence à augmenter la complexité de votre couche de données car il implique de cartographier vos entités à leur DTO dans votre couche de base de données, laissant finalement des dépôts qui sont pleins de méthodes similaires retournant différents types DTO. Certaines personnes pensent également que l'exposition de IQueryables à partir de votre couche de données est également une mauvaise chose lorsque vous commencez à faire couler des abstractions vers différentes couches - bien que cela ait toujours semblé un peu extrême. Personnellement, je privilégie ce que je pense être une approche plus pragmatique et je préfère utiliser un outil comme AutoMapper pour mapper automatiquement mes entités à mes DTO dans la couche logique métier.

Par exemple:

// Initial configuration loaded on start up of application and cached by AutoMapper 
AutoMapper.Mapper.CreateMap<BlogPostEntity, BlogPostDto>(); 

// Usage 
BlogPostDto blogPostDto = AutoMapper.Mapper.Map<BlogPostDto>(blogPostEntity); 

AutoMapper a également la possibilité de configurer la cartographie plus complexe, bien que vous devriez essayer d'éviter cela si possible en collant à flatter DTO.

En outre, une autre grande fonctionnalité d'AutoMapper est la possibilité de projeter automatiquement vos entités aux DTO. Il en résulte beaucoup plus propre SQL où seules les colonnes dans votre DTO sont interrogeables:

public IEnumerable<BlogPostDto> GetRecentPosts() 
{ 
    IEnumerable<BlogPostDto> blogPosts = this.blogRepository.FindAll().Project(this.mappingEngine).To<BlogPostDto>().ToList(); 

    return blogPosts; 
} 

De plus, parfois toutes les données sont nécessaires pour être envoyées aux clients .. Si un Dto être créé pour les cas comme bien? Ou devrais-je retourner un modèle de domaine?

Les DTO doivent être créés pour ceux-ci. En fin de compte, vous ne voulez pas que votre client dépende de votre schéma de données, ce qui est exactement ce qui se passera si vous exposez vos entités.

Alternatives: Commande/Interrogation Ségrégation

Il me appartient de souligner également qu'il existe aussi d'autres alternatives à une architecture en couches typique, comme l'approche de commande/requête Ségrégation où vous modélisez vos commandes et requêtes via un médiateur. Je ne vais pas entrer dans trop de détails car c'est un tout autre sujet, mais c'est un que je préférerais définitivement sur une approche en couches discutée ci-dessus. Cela entraînerait la mise en correspondance de vos entités avec vos DTO directement dans la commande ou la requête modélisée.

Je recommande de jeter un oeil à Mediatr pour cela. L'auteur, Jimmy Bogard qui a également créé AutoMapper a également this video talking sur le même sujet.

1

J'ai eu des exigences similaires dans plusieurs projets et dans la plupart des cas nous nous sommes séparés au moins trois couches:

Database couche

Les objets de base de données sont simples un à l'une des représentations de la base de données les tables. Rien d'autre.

couche domaine

La couche de domaine définit des objets d'entités qui constituent un objet de gestion complète. Dans notre définition, une entité agrège toutes les données directement associées à l'entité et ne peut pas être considérée comme une entité dédiée. Un exemple: Dans une application qui gère les factures, vous avez une table invoice et invoice_items. La logique métier lit les deux tables et combine les données dans un objet entité Invoice.

couche application

Dans la couche d'application, nous définissons des modèles pour tous genre de données que nous voulons envoyer au client. Le passage des objets d'entité de domaine pour gagner du temps est tentant mais strictement interdit. Le risque de publier des données qui ne devraient pas être publiées est trop élevé. De plus, vous gagnez plus de liberté en ce qui concerne la conception de votre API. C'est ce qui vous aide à adapter votre dernière exigence (envoyer toutes les données au client): Juste construit un nouveau modèle qui agrège les données de tous les objets de domaine que vous devez envoyer.

Il s'agit de l'ensemble minimal de couches que nous utilisons dans tous les projets. Il y a eu des centaines de cas où nous avons été très heureux d'avoir plusieurs couches d'abstraction qui nous ont donné suffisamment de possibilités pour améliorer et mettre à l'échelle une application.

+0

Mais les objets de domaine ne seraient-ils pas similaires aux objets de données? Parce que dans les modèles de tables facture aura une liste d'éléments de factures ou quelque chose de similaire, ai-je tort? –

+0

Oui, dans la plupart des cas, les objets de domaine et de base de données seront presque similaires mais pas identiques. Nous avons quelques cas où nous modifions ou optimisons un peu les données de la couche de domaine. Par exemple, la base de données stocke le taux d'imposition d'un «produit» uniquement s'il diffère du taux d'imposition par défaut. Mais dans la couche application, nous ne voulons pas rechercher le taux de taxe par défaut à chaque fois que nous traitons un produit, donc nous ajoutons le taux de taxe par défaut dans la couche de domaine. C'est pourquoi le type de données de Product.TaxRate dans la couche de domaine est 'double 'mais dans la couche de base de données il est' double?'. – krani

+1

Donc vos cartes sont Dto -> Domaine -> Base de données Base de données -> domaine -> Dto N'est-ce pas trop de mappings pour une simple opération get par exemple? –