Je (re) conçois des applications à grande échelle, nous utilisons une architecture multicouche basée sur DDD.
Nous avons MVC avec couche de données (implémentation de référentiels), couche de domaine (définition du modèle de domaine et interfaces - référentiels, services, unité de travail), couche de service (implémentation de services). Jusqu'à présent, nous utilisons des modèles de domaine (principalement des entités) sur toutes les couches, et nous utilisons les DTO uniquement comme modèles de vue (dans le contrôleur, le service renvoie le (s) modèle (s) de domaine et le contrôleur crée le modèle de vue, qui est passé à la vue).
J'ai lu d'innombrables articles sur l'utilisation, la non-utilisation, le mappage et la transmission des DTO. Je comprends qu'il n'y a pas de réponse définitive, mais je ne suis pas sûr que ce soit correct ou non de renvoyer les modèles de domaine des services aux contrôleurs. Si je retourne le modèle de domaine, il n'est toujours jamais passé à la vue, car le contrôleur crée toujours un modèle de vue spécifique à la vue - dans ce cas, cela semble légitime. D'un autre côté, cela ne se sent pas bien lorsque le modèle de domaine quitte la couche métier (couche de service). Parfois, le service doit renvoyer un objet de données qui n'a pas été défini dans le domaine, puis nous devons soit ajouter un nouvel objet au domaine qui n'est pas mappé, soit créer un objet POCO (c'est moche, car certains services renvoient des modèles de domaine, certains renvoyer effectivement les DTO).
La question est la suivante: si nous utilisons strictement des modèles de vue, est-il acceptable de renvoyer les modèles de domaine jusqu'aux contrôleurs, ou devrions-nous toujours utiliser les DTO pour la communication avec la couche de service? Si tel est le cas, est-il possible d'ajuster les modèles de domaine en fonction des besoins des services? (Franchement, je ne pense pas, car les services devraient consommer ce que le domaine a.) Si nous devons nous en tenir strictement aux DTO, devraient-ils être définis dans la couche de service? (Je pense que oui.) Parfois, il est clair que nous devrions utiliser des DTO (par exemple, lorsque le service exécute beaucoup de logique métier et crée de nouveaux objets), parfois il est clair que nous devrions utiliser uniquement des modèles de domaine (par exemple, lorsque le service Membership renvoie un utilisateur anémique ( s) - il semble que cela n'aurait pas beaucoup de sens de créer un DTO identique au modèle de domaine) - mais je préfère la cohérence et les bonnes pratiques.
Article Domain vs DTO vs ViewModel - Comment et quand les utiliser? (et aussi quelques autres articles) est très similaire à mon problème, mais il ne répond pas à cette (ces) question (s). Article Dois-je implémenter des DTO dans un modèle de référentiel avec EF? est également similaire, mais il ne traite pas de DDD.
Avertissement: Je n'ai pas l'intention d'utiliser un modèle de conception uniquement parce qu'il existe et est sophistiqué, d'un autre côté, j'aimerais utiliser de bons modèles et pratiques de conception également parce que cela aide à concevoir l'application dans son ensemble, aide à la séparation des préoccupations, même le fait d'utiliser un modèle particulier n'est pas "nécessaire", du moins pour le moment.
Comme toujours, merci.
la source
Réponses:
Vous donne l'impression de tirer les tripes, n'est-ce pas? Selon Martin Fowler: la couche de service définit les limites de l'application, elle encapsule le domaine. En d'autres termes, il protège le domaine.
Pouvez-vous donner un exemple de cet objet de données?
Oui, car la réponse fait partie de votre couche de service. S'il est défini «ailleurs», alors la couche de service doit faire référence à «ailleurs», ajoutant une nouvelle couche à vos lasagnes.
Un DTO est un objet de réponse / demande, cela a du sens si vous l'utilisez pour la communication. Si vous utilisez des modèles de domaine dans votre couche de présentation (MVC-Controllers / View, WebForms, ConsoleApp), alors la couche de présentation est étroitement couplée à votre domaine, toute modification dans le domaine vous oblige à changer vos contrôleurs.
C'est l'un des inconvénients du DTO pour les nouveaux yeux. À l'heure actuelle, vous pensez à la duplication de code , mais à mesure que votre projet se développe, cela aurait beaucoup plus de sens, en particulier dans un environnement d'équipe où différentes équipes sont affectées à différentes couches.
DTO peut ajouter une complexité supplémentaire à votre application, tout comme vos couches. DTO est une fonctionnalité coûteuse de votre système, ils ne sont pas gratuits.
Pourquoi utiliser un DTO
Cet article présente à la fois l'avantage et l'inconvénient d'utiliser un DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html
Résumé comme suit:
Quand utiliser
Quand ne pas utiliser
Arguments contre DTO
Arguments avec DTO
la source
Il semble que votre application soit suffisamment grande et complexe car vous avez décidé de passer par l'approche DDD. Ne renvoyez pas vos entités poco ou ce que l'on appelle des entités de domaine et des objets de valeur dans votre couche de service. Si vous voulez faire cela, supprimez votre couche de service car vous n'en avez plus besoin! Les objets de modèle de vue ou de transfert de données doivent vivre dans la couche Service, car ils doivent être mappés aux membres du modèle de domaine et vice versa. Alors pourquoi avez-vous besoin d'un DTO? Dans une application complexe avec de nombreux scénarios, vous devez séparer les préoccupations du domaine et vos vues de présentation, un modèle de domaine peut être divisé en plusieurs DTO et plusieurs modèles de domaine peuvent être réduits en un DTO. Il est donc préférable de créer votre DTO dans une architecture en couches, même si ce serait le même que votre modèle.
Devrions-nous toujours utiliser les DTO pour la communication avec la couche de service? Oui, vous devez renvoyer le DTO par votre couche de service car vous avez parlé à votre référentiel dans la couche de service avec les membres du modèle de domaine et les mapper au DTO et revenir au contrôleur MVC et vice versa.
Est-il acceptable d'ajuster les modèles de domaine en fonction des besoins des services? Un service ne concerne que les méthodes de référentiel et de domaine et les services de domaine, vous devez résoudre l'entreprise de votre domaine en fonction de vos besoins et ce n'est pas la tâche de service de dire au domaine ce qui est nécessaire.
Si nous devons nous en tenir strictement aux DTO, doivent-ils être définis dans la couche de service? Oui, essayez d'avoir DTO ou ViewModel juste en service plus tard, car ils devraient être mappés aux membres du domaine dans la couche de service et ce n'est pas une bonne idée de placer DTO dans les contrôleurs de votre application (essayez d'utiliser le modèle de demande de réponse dans votre couche de service), bravo !
la source
D'après mon expérience, vous devriez faire ce qui est pratique. «Le meilleur design est le design le plus simple qui fonctionne» - Einstein. Avec cela, c'est l'esprit ...
Absolument c'est ok! Si vous avez des entités de domaine, des DTO et des modèles de vue, y compris les tables de base de données, tous les champs de l'application sont répétés à 4 endroits. J'ai travaillé sur de grands projets où les entités de domaine et les modèles de vue fonctionnaient très bien. La seule exception à cela est que l'application est distribuée et que la couche de service réside sur un autre serveur, auquel cas les DTO doivent envoyer via le câble pour des raisons de sérialisation.
En général, je suis d'accord et je dirais non parce que le modèle de domaine est généralement le reflet de la logique métier et n'est généralement pas façonné par le consommateur de cette logique.
Si vous décidez de les utiliser, je serais d'accord et je dirais que la couche Service est l'endroit idéal car elle renvoie les DTO à la fin de la journée.
Bonne chance!
la source
Je suis en retard à cette fête, mais c'est une question tellement courante et importante que je me suis senti obligé de répondre.
Par "services", vous entendez la "couche d'application" décrite par Evan's dans le livre bleu ? Je suppose que vous le faites, auquel cas la réponse est qu'ils ne devraient pas renvoyer les DTO. Je suggère de lire le chapitre 4 du livre bleu, intitulé «Isoler le domaine».
Dans ce chapitre, Evans dit ce qui suit à propos des couches:
Il y a de bonnes raisons pour cela. Si vous utilisez le concept d' ordre partiel comme mesure de la complexité du logiciel, le fait d' avoir une couche dépend d'une couche au-dessus augmente la complexité, ce qui diminue la maintenabilité.
En appliquant cela à votre question, les DTO sont vraiment un adaptateur qui concerne la couche Interface utilisateur / Présentation. N'oubliez pas que la communication à distance / inter-processus est exactement le but d'un DTO (il convient de noter que dans cet article, Fowler fait également valoir que les DTO font partie d'une couche de service, bien qu'il ne parle pas nécessairement le langage DDD).
Si votre couche d'application dépend de ces DTO, cela dépend d'une couche au-dessus d'elle-même et votre complexité augmente. Je peux vous garantir que cela augmentera la difficulté de maintenir votre logiciel.
Par exemple, que se passe-t-il si votre système s'interface avec plusieurs autres systèmes ou types de clients, chacun nécessitant leur propre DTO? Comment savoir quel DTO une méthode de votre service d'application doit renvoyer? Comment résoudriez-vous même ce problème si la langue de votre choix ne permet pas de surcharger une méthode (méthode de service, dans ce cas) basée sur le type de retour? Et même si vous trouvez un moyen, pourquoi violer votre couche d'application pour prendre en charge un problème de couche de présentation?
Concrètement, c'est un pas sur une route qui se terminera par une architecture spaghetti. J'ai vu ce genre de décentralisation et ses résultats dans ma propre expérience.
Là où je travaille actuellement, les services de notre couche d'application renvoient des objets de domaine. Nous ne considérons pas cela comme un problème car la couche Interface (ie UI / Presentation) dépend de la couche Domain, qui se trouve en dessous . En outre, cette dépendance est réduite à un type de dépendance "référence uniquement" car:
a) la couche d'interface ne peut accéder à ces objets de domaine qu'en tant que valeurs de retour en lecture seule obtenues par des appels à la couche d'application
b) les méthodes sur les services de la couche application n'acceptent en entrée que l'entrée "brute" (valeurs de données) ou les paramètres d'objet (pour réduire le nombre de paramètres si nécessaire) définis dans cette couche. Plus précisément, les services d'application n'acceptent jamais les objets de domaine comme entrée.
La couche d'interface utilise des techniques de mappage définies dans la couche d'interface elle-même pour mapper des objets du domaine vers les DTO. Encore une fois, cela permet aux DTO de rester concentrés sur les adaptateurs contrôlés par la couche d'interface.
la source
En retard à la fête, mais je suis confronté exactement au même type d'architecture et je penche vers «uniquement les DTO du service». C'est principalement parce que j'ai décidé de n'utiliser que des objets / agrégats de domaine pour maintenir la validité dans l'objet, donc uniquement lors de la mise à jour, de la création ou de la suppression. Lorsque nous recherchons des données, nous utilisons uniquement EF comme référentiel et mappons le résultat aux DTO. Cela nous permet d'optimiser les requêtes de lecture et de ne pas les adapter aux objets métier, en utilisant souvent des fonctions de base de données car elles sont rapides.
Chaque méthode de service définit son propre contrat et est donc plus facile à maintenir dans le temps. J'espère.
la source
Étant donné que Domain Model fournit une terminologie ( Ubiquitous Language ) pour l'ensemble de votre application, il est préférable d'utiliser largement le Domain Model.
La seule raison d'utiliser ViewModels / DTO est une implémentation du modèle MVC dans votre application pour séparer
View
(tout type de couche de présentation) etModel
(modèle de domaine). Dans ce cas, votre présentation et votre modèle de domaine sont faiblement couplés.Je suppose que vous parlez de services Application / Business / Domain Logic.
Je vous suggère de renvoyer les entités de domaine lorsque vous le pouvez. S'il est nécessaire de renvoyer des informations supplémentaires, il est acceptable de renvoyer un DTO qui contient plusieurs entités de domaine.
Parfois, les personnes qui utilisent des frameworks de troisième partie, qui génèrent des proxys sur des entités de domaine, rencontrent des difficultés pour exposer les entités de domaine à partir de leurs services, mais ce n'est qu'une mauvaise utilisation.
Je dirais qu'il suffit de renvoyer des entités de domaine dans 99,9% des cas.
Afin de simplifier la création de DTO et de mapper vos entités de domaine dans ces derniers, vous pouvez utiliser AutoMapper .
la source
Si vous retournez une partie de votre modèle de domaine, cela devient une partie d'un contrat. Un contrat est difficile à changer, car des choses en dehors de votre contexte en dépendent. En tant que tel, vous rendriez une partie de votre modèle de domaine difficile à modifier.
Un aspect très important d'un modèle de domaine est qu'il est facile à changer. Cela nous rend flexibles aux exigences changeantes du domaine.
la source
Je suggère d'analyser ces deux questions:
Vos couches supérieures (c'est-à-dire afficher et visualiser les modèles / contrôleurs) consomment-elles les données d'une manière différente de ce que la couche de domaine expose? S'il y a beaucoup de cartographie en cours ou même de logique impliquée, je suggérerai de revoir votre conception: elle devrait probablement être plus proche de la façon dont les données sont réellement utilisées.
Quelle est la probabilité que vous changiez profondément vos couches supérieures? (par exemple, échange d'ASP.NET pour WPF). Si cela est très différent et que votre architecture n'est pas très complexe, vous feriez peut-être mieux d'exposer autant d'entités de domaine que possible.
Je crains que ce soit un sujet assez vaste et que cela dépend vraiment de la complexité de votre système et de ses exigences.
la source
D'après mon expérience, à moins que vous n'utilisiez un modèle d'interface utilisateur OO (comme des objets nus), exposer les objets de domaine à l'interface utilisateur est une mauvaise idée. En effet, à mesure que l'application se développe, les besoins de l'interface utilisateur changent et obligent vos objets à s'adapter à ces modifications. Vous finissez par servir 2 maîtres: UI et DOMAIN, ce qui est une expérience très douloureuse. Croyez-moi, vous ne voulez pas être là. Le modèle d'interface utilisateur a pour fonction de communiquer avec l'utilisateur, le modèle DOMAIN pour contenir les règles métier et les modèles de persistance s'occupent de stocker efficacement les données. Ils répondent tous à des besoins différents de l'application. Je suis en train d'écrire un article de blog à ce sujet, je l'ajouterai quand ce sera fait.
la source