Les services doivent-ils toujours renvoyer des DTO ou peuvent-ils également renvoyer des modèles de domaine?

Je (re) conçoit 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 des 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) dans toutes les couches et nous utilisons les DTO uniquement comme modèles de vue (dans le contrôleur, le modèle de domaine de retour de service et le modèle de vue de contrôleur transmis à la vue).

Je vais lire d’innombrables articles sur l’utilisation, la non-utilisation, la cartographie et le passage 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 que je ne renvoie pas les modèles de domaine des services aux contrôleurs. Si je retourne un modèle de domaine, il n’est toujours pas transmis à 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’autre part, cela ne semble pas correct lorsque le modèle de domaine quitte la couche métier (couche service). Parfois, le service doit renvoyer un object de données non défini dans le domaine, puis append un nouvel object au domaine non mappé ou créer un object POCO (c’est moche car certains services renvoient des modèles de domaine, certains retourner efficacement les DTO).

La question est la suivante: si nous utilisons ssortingctement des modèles de vue, est-il acceptable de renvoyer les modèles de domaine aux contrôleurs, ou devrions-nous toujours utiliser les DTO pour la communication avec la couche de service? Dans l’affirmative, est-il acceptable d’ajuster les modèles de domaine en fonction des besoins des services? (Franchement, je ne le pense pas, puisque les services devraient consumr ce que le domaine a.) Si nous devions nous en tenir ssortingctement aux DTO, devraient-ils être définis dans la couche de service? (Je le pense.) Parfois, il est clair que nous devons utiliser les DTO (par exemple, lorsque le service exécute beaucoup de logique métier et crée de nouveaux objects), s) – il ne semble pas très logique 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 d’autres articles) est très similaire à mon problème, mais il ne répond pas à cette question. 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.

Clause de non-responsabilité: Je n’ai pas l’intention d’utiliser un modèle uniquement parce qu’il existe et qu’il est sophistiqué. D’autre part, j’aimerais utiliser de bons modèles et pratiques de conception, car cela aide à concevoir l’application dans son ensemble. des préoccupations, même en utilisant un modèle particulier n’est pas “nécessaire”, du moins pour le moment.

Comme toujours, merci.

il ne se sent pas bien lorsque le modèle de domaine quitte la couche métier (couche service)

Est-ce que tu as l’impression que tu es en train de tirer les sortingpes correctement? Selon Martin Fowler: la couche de service définit la limite de l’application, elle encapsule le domaine. En d’autres termes, il protège le domaine.

Parfois, le service doit renvoyer un object de données non défini dans le domaine

Pouvez-vous fournir un exemple de cet object de données?

Si nous devons nous en tenir ssortingctement aux DTO, devraient-ils être définis dans la couche de service?

Oui, car la réponse fait partie de votre couche de service. Si elle est définie “ailleurs”, la couche de service doit alors faire référence à “ailleurs”, ajoutant une nouvelle couche à votre lasagne.

est-il possible de renvoyer les modèles de domaine aux contrôleurs ou devrions-nous toujours utiliser les DTO pour la communication avec la couche de service?

Un DTO est un object réponse / requête, 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), la couche de présentation est étroitement liée à votre domaine. Toute modification du domaine nécessite que vous modifiiez vos contrôleurs.

il semble que cela n’aurait aucun sens de créer un DTO identique au modèle de domaine)

C’est l’un des inconvénients de DTO pour les nouveaux yeux. En ce moment, vous pensez à la duplication de code , mais au fur et à mesure que votre projet se développe, cela prendrait beaucoup plus de sens, spécialement dans un environnement d’équipe où différentes équipes sont affectées à différentes couches.

DTO peut append une complexité supplémentaire à votre application, mais vos couches le sont également. DTO est une fonctionnalité coûteuse de votre système, ils ne sont pas gratuits.

Pourquoi utiliser un DTO

Cet article fournit à la fois un avantage et un inconvénient en utilisant un DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html

Résumé comme suit:

Quand utiliser

  • Pour les grands projets.
  • La durée de vie du projet est de 10 ans et plus.
  • Application stratégique et stratégique.
  • Grandes équipes (plus de 5)
  • Les développeurs sont répartis géographiquement.
  • Le domaine et la présentation sont différents.
  • Réduire les échanges de données généraux (l’objective initial de DTO)

Quand ne pas utiliser

  • Projet de taille petite à moyenne (5 membres maximum)
  • La durée de vie du projet est d’environ 2 ans.
  • Aucune équipe distincte pour l’interface graphique, backend, etc.

Arguments contre DTO

  • Duplication du code.
  • Coût du temps de développement, débogage. (utiliser les outils de génération DTO http://entitiestodtos.codeplex.com/ )
  • Vous devez synchroniser les deux modèles tout le temps.
  • Coût de développement: Une cartographie supplémentaire est nécessaire. (utilisez les mappeurs automatiques comme https://github.com/AutoMapper/AutoMapper )
  • Pourquoi les objects de transfert de données sont-ils un anti-pattern?

Arguments avec DTO

  • Sans DTO, la présentation et le domaine sont étroitement liés. (Cela convient aux petits projets.)
  • Stabilité de l’interface / API
  • Peut fournir une optimisation pour la couche de présentation en renvoyant un DTO contenant uniquement les atsortingbuts absolument requirejs. En utilisant linq-projection , vous n’avez pas besoin de tirer une entité entière.
  • Pour réduire les coûts de développement, utilisez des outils de génération de code

Dans mon expérience, vous devriez faire ce qui est pratique. “Le meilleur design est la conception la plus simple qui fonctionne” – Einstein. Avec ça, l’esprit …

Si nous utilisons ssortingctement des modèles de vue, est-il possible de renvoyer les modèles de domaine aux contrôleurs, ou devrions-nous toujours utiliser les DTO pour la communication avec la couche de service?

Absolument ça va! Si vous avez des entités de domaine, des DTO et des modèles de vue, y compris des tables de firebase database, 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 parfaitement. La seule exception à cette règle réside dans le fait que l’application est dissortingbuée et que la couche de service réside sur un autre serveur. Dans ce cas, les DTO doivent envoyer des messages pour des raisons de sérialisation.

Dans l’affirmative, est-il acceptable d’ajuster les modèles de domaine en fonction des besoins des services? (Franchement, je ne le pense pas, car les services devraient consumr quel domaine).

En général, je suis d’accord et je dis 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 nous devons nous en tenir ssortingctement aux DTO, devraient-ils être définis dans la couche de service? (Je le pense.)

Si vous décidez de les utiliser, je serai d’accord et je dirai que la couche Service est l’endroit idéal car elle renvoie les DTO à la fin de la journée.

Bonne chance!

il semble que votre application soit suffisamment vaste et complexe, car vous avez décidé de passer par l’approche DDD. Ne renvoyez pas vos entités de poco ou des entités de domaine et objects 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 objects de modèle de visualisation ou de transfert de données doivent figurer dans la couche Service, car ils doivent être mappés sur les membres du modèle de domaine et inversement. alors pourquoi avez-vous besoin de DTO? Dans les applications complexes avec beaucoup de scénarios, vous devez séparer les préoccupations de domaine et les 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 DTO. il est donc préférable de créer votre DTO en 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 DTO par votre couche de service lorsque vous parlez à votre référentiel dans la couche de service avec les membres du modèle de domaine, que vous les mappez sur DTO et que vous retournez au contrôleur MVC et inversement.

est-il acceptable d’ajuster les modèles de domaine en fonction des besoins des services? un service ne s’adresse qu’aux méthodes de référentiel et de domaine et aux services de domaine, vous devez résoudre le problème de votre domaine en fonction de vos besoins et ce n’est pas la tâche du service de dire au domaine ce dont vous avez besoin.

Si nous devons nous en tenir ssortingctement aux DTO, devraient-ils être définis dans la couche de service? oui essayez d’avoir DTO ou ViewModel en service plus tard car ils doivent être mappés sur les membres du domaine dans la couche service et il n’est pas judicieux de placer DTO dans les contrôleurs de votre application (essayez d’utiliser le modèle Request Response dans votre couche Service) !

Jusqu’à présent, nous utilisons des modèles de domaine (principalement des entités) dans toutes les couches, et nous utilisons les DTO uniquement comme modèles de vue (dans le contrôleur, le modèle de domaine renvoie le service et le contrôleur crée le modèle).

Puisque le modèle de domaine fournit la terminologie ( langage ubiquitaire ) pour l’ensemble de votre application, il est préférable d’utiliser largement le modèle de domaine.

La seule raison d’utiliser ViewModels / DTO est une implémentation du modèle MVC dans votre application pour séparer View (n’importe quel type de couche de présentation) et Model (modèle de domaine). Dans ce cas, votre présentation et votre modèle de domaine sont faiblement couplés.

Parfois, le service doit renvoyer un object de données non défini dans le domaine, puis append un nouvel object au domaine non mappé ou créer un object POCO (c’est moche car certains services renvoient des modèles de domaine, certains retourner efficacement les DTO).

Je suppose que vous parlez de services de logique applicative / métier / de domaine.

Je vous suggère de renvoyer les entités du domaine lorsque vous le pouvez. S’il est nécessaire de retourner des informations supplémentaires, il est acceptable de renvoyer DTO contenant plusieurs entités de domaine.

Parfois, les personnes qui utilisent des frameworks tiers, qui génèrent des proxy par-dessus les entités du domaine, rencontrent des difficultés pour exposer les entités du domaine à partir de leurs services, mais ce n’est qu’une mauvaise utilisation.

La question est la suivante: si nous utilisons ssortingctement des modèles de vue, est-il acceptable de renvoyer les modèles de domaine aux contrôleurs, ou devrions-nous toujours utiliser les DTO pour la communication avec la couche de service?

Je dirais qu’il suffit de renvoyer des entités de domaine dans 99,9% des cas.

Pour simplifier la création de fichiers DTO et leur mappage, vous pouvez utiliser AutoMapper .

Je suggérerais d’parsingr ces deux questions:

  1. Vos couches supérieures (c.-à-d. Afficher et afficher les modèles / contrôleurs) consumnt-elles les données d’une manière différente de celle de la couche de domaine? S’il y a beaucoup de cartographie en cours ou même de logique, je suggère de revoir votre conception: elle devrait probablement être plus proche de la manière dont les données sont réellement utilisées.

  2. Quelle est la probabilité que vous modifiiez profondément vos couches supérieures? (par exemple, permuter ASP.NET pour WPF). Si cela est très différent et que votre architecture n’est pas très complexe, vous feriez mieux d’exposer autant d’entités de domaine que possible.

J’ai bien peur que ce soit un sujet assez vaste et que cela dépend vraiment de la complexité de votre système et de ses exigences.

Je suis en retard à cette fête, mais c’est une question si commune et importante que je me suis senti obligé de répondre.

Par “services”, vous voulez dire la “couche d’application” décrite par Evan dans le livre bleu ? Je suppose que vous le faites, auquel cas la réponse est qu’ils ne devraient pas retourner les DTO. Je suggère de lire le chapitre 4 du livre bleu intitulé “Isoler le domaine”.

Dans ce chapitre, Evans dit ceci à propos des couches:

Partitionnez un programme complexe en couches. Développez une conception cohérente dans chaque couche et qui ne dépend que des couches ci-dessous.

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 de dépendre d’une couche d’une couche supérieure augmente la complexité, ce qui diminue la maintenabilité.

En appliquant cela à votre question, les DTO sont en réalité un adaptateur qui concerne la couche Interface utilisateur / Présentation. Rappelez-vous que la communication à distance / inter-processus est exactement le but d’un DTO (il convient de noter que Fowler fait également valoir que les DTO ne font pas 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, elle dépend d’une couche supérieure et votre complexité augmente. Je peux garantir que cela augmentera la difficulté de maintenir votre logiciel.

Par exemple, si votre système s’interface avec plusieurs autres systèmes ou types de clients, chacun nécessitant son propre DTO? Comment savoir quelle DTO une méthode de votre service d’application doit renvoyer? Comment pourriez-vous même résoudre ce problème si votre langue de 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?

En termes pratiques, il s’agit d’une étape qui aboutira à une architecture de spaghetti. J’ai vu ce genre de dévolution et ses résultats dans ma propre expérience.

Où je travaille actuellement, les services de notre couche Application retournent des objects de domaine. Nous ne considérons pas cela comme un problème car la couche Interface (c.-à-d. Interface utilisateur / présentation) dépend de la couche Domaine, qui est 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 objects de domaine qu’en tant que valeurs de retour en lecture seule obtenues par des appels à la couche application

b) les méthodes sur les services de la couche application acceptent en entrée uniquement les parameters d’entrée (valeurs de données) ou d’object “bruts” (pour réduire le nombre de parameters si nécessaire) définis dans cette couche. Plus précisément, les services d’application n’acceptent jamais les objects 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 objects de domaine aux DTO. Là encore, les DTO restnt concentrés sur les adaptateurs contrôlés par la couche d’interface.