J'ai récemment entendu des gens dire que les objets de transfert de données (DTO) sont un anti-pattern .
Pourquoi? Quelles sont les alternatives?
J'ai récemment entendu des gens dire que les objets de transfert de données (DTO) sont un anti-pattern .
Pourquoi? Quelles sont les alternatives?
Réponses:
Certains projets ont toutes les données deux fois . Une fois en tant qu'objets de domaine, et une fois en tant qu'objets de transfert de données.
Cette duplication a un coût énorme , donc l'architecture doit tirer un énorme avantage de cette séparation pour en valoir la peine.
Les DTO ne sont pas un anti-pattern. Lorsque vous envoyez des données via le câble (par exemple, vers une page Web lors d'un appel Ajax), vous voulez être sûr de conserver la bande passante en envoyant uniquement les données que la destination utilisera. En outre, il est souvent pratique pour la couche de présentation d'avoir les données dans un format légèrement différent de celui d'un objet métier natif.
Je sais que c'est une question orientée Java, mais dans les langages .NET, les types anonymes, la sérialisation et LINQ permettent de construire des DTO à la volée, ce qui réduit la configuration et la surcharge de leur utilisation.
DTO un AntiPattern dans EJB 3.0 dit:
La nature lourde des Entity Beans dans les spécifications EJB antérieures à EJB 3.0, a entraîné l'utilisation de modèles de conception tels que les objets de transfert de données (DTO). Les DTO sont devenus les objets légers (qui auraient dû être les beans entité eux-mêmes en premier lieu), utilisés pour envoyer les données à travers les niveaux ... maintenant, la spécification EJB 3.0 rend le modèle de bean Entity identique à l'Objet Java Plain old (POJO). Avec ce nouveau modèle POJO, vous n'aurez plus besoin de créer un DTO pour chaque entité ou pour un ensemble d'entités ... Si vous souhaitez envoyer les entités EJB 3.0 à travers le niveau, faites-les simplement implémenter java.io.
Je ne pense pas que les DTO soient un anti-pattern en soi, mais il y a des antipatterns associés à l'utilisation des DTO. Bill Dudney fait référence à l'explosion du DTO à titre d'exemple:
http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf
Il y a également un certain nombre d'abus des DTO mentionnés ici:
http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/
Ils proviennent de systèmes à trois niveaux (utilisant généralement EJB comme technologie) comme moyen de transmettre des données entre les niveaux. La plupart des systèmes Java modernes basés sur des frameworks tels que Spring adoptent une vue simplifiée alternative utilisant les POJO comme objets de domaine (souvent annotés avec JPA, etc.) dans un seul niveau ... L'utilisation de DTO ici est inutile.
Les puristes OO diraient que DTO est anti-pattern parce que les objets deviennent des représentations de table de données au lieu d'objets de domaine réel.
Certains considèrent les DTO comme un anti-pattern en raison de leurs abus possibles. Ils sont souvent utilisés quand ils ne devraient pas être / n'ont pas besoin de l'être.
Cet article décrit vaguement certains abus.
Si vous construisez un système distribué, les DTO ne sont certainement pas un anti-pattern. Tout le monde ne se développera pas dans ce sens, mais si vous avez (par exemple) une application Open Social fonctionnant entièrement avec JavaScript.
Il publiera une charge de données sur votre API. Celui-ci est ensuite désérialisé en une forme d'objet, généralement un objet DTO / Request. Cela peut ensuite être validé pour s'assurer que les données saisies sont correctes avant d'être converties en objet modèle.
À mon avis, c'est considéré comme un anti-modèle parce qu'il est mal utilisé. Si vous ne construisez pas un système distribué, il est probable que vous n'en ayez pas besoin.
L'intention d'un objet de transfert de données est de stocker des données provenant de différentes sources, puis de les transférer dans une base de données (ou une façade distante ) à la fois.
Cependant, le modèle DTO viole le principe de responsabilité unique , car le DTO stocke non seulement les données, mais les transfère également depuis ou vers la base de données / façade.
La nécessité de séparer les objets de données des objets métier n'est pas un anti-modèle, car il est probablement nécessaire de séparer de toute façon la couche de base de données .
Au lieu des DTO, vous devez utiliser les modèles d'agrégat et de référentiel, qui séparent la collection d'objets ( agrégat ) et le transfert de données ( référentiel ).
Pour transférer un groupe d'objets, vous pouvez utiliser le modèle Unité de travail , qui contient un ensemble de référentiels et un contexte de transaction; afin de transférer chaque objet dans l'agrégat séparément dans la transaction.
Le DTO devient une nécessité et non un ANTI-MOTIF lorsque tous les objets de votre domaine chargent les objets associés EAGERly.
Si vous ne créez pas de DTO, vous aurez des objets transférés inutiles de votre couche de gestion vers votre couche client / Web.
Pour limiter la surcharge dans ce cas, transférez plutôt les DTO.
La question ne devrait pas être «pourquoi», mais « quand ».
En définitive, c'est anti-pattern lorsque seul le résultat de son utilisation est plus coûteux - temps d'exécution ou maintenance. J'ai travaillé sur des projets ayant des centaines de DTO identiques aux classes d'entités de base de données. Chaque fois que vous vouliez ajouter un seul champ, vous ajoutez un identifiant comme quatre fois - à DTO, à entité, à la conversion de DTO en classes ou entités de domaine, la conversion inverse, ... Vous avez oublié certains des lieux et des données obtenus inconsistant.
Ce n'est pas anti-pattern quand vous avez vraiment besoin d'une représentation différente des classes de domaine - plus plate, plus riche, plus étroite, ...
Personnellement, je commence par la classe de domaine et je la fais circuler, avec une vérification appropriée aux bons endroits. Je peux annoter et / ou ajouter des classes "helper" pour faire des mappages, à des bases de données, à des formats de sérialisation comme JSON ou XML ... Je peux toujours diviser une classe en deux si j'en ressens le besoin.
Il s'agit de votre point de vue - je préfère regarder un objet de domaine comme un objet unique jouant différents rôles, au lieu de plusieurs objets créés les uns à partir des autres. Si le seul rôle d'un objet est de transporter des données, c'est DTO.
Je pense que les gens pensent que cela pourrait être un anti-modèle si vous implémentez tous les objets distants en tant que DTO. Un DTO n'est qu'un ensemble d'attributs et si vous avez de gros objets, vous transférez toujours tous les attributs même si vous n'en avez pas besoin ou que vous ne les utilisez pas. Dans ce dernier cas, préférez utiliser un modèle Proxy.