Entité à l'utilisation du DTO

15

J'ai essayé de trouver un flux pour une application Web à plusieurs niveaux de base et j'ai lu des informations contradictoires en ligne. Ce que j'essaie de comprendre, c'est s'il y a un avantage à continuer à utiliser des objets DTO de votre couche DAO vers Service grâce à l'utilisation d'une sorte de mappeur.

Le flux de base que je prévois est le suivant:

  1. Modèle / formulaire d'interface utilisateur -> Contrôleur
  2. Le contrôleur convertit le modèle en objet de domaine (entité)
  3. Objet de domaine -> Couche de service
  4. Objet de domaine -> DAO
  5. DAO -> Objet (s) de domaine
  6. Service -> UI
  7. L'interface utilisateur convertit le domaine en modèles d'interface utilisateur

Si le DTO était suivi, DAO transmettrait un DTO et non l'entité. Après avoir fait quelques lectures, il semble que le DTO soit légèrement disparu puisque (au moins en Java) les entités sont devenues des POJO annotés, ce qui signifie que leur empreinte mémoire est devenue très petite.

Est-ce le cas, ou faut-il utiliser des DTO pour encapsuler complètement les objets de domaine au sein de la couche DAO, et si tel est le cas, que passerait la couche service au DAO?

Merci beaucoup!

dardo
la source

Réponses:

20

Selon moi, passer un POJO persistant, comme par exemple un bean géré par JPA, n'est pas LA bonne pratique.

Pourquoi?

Je vois trois raisons principales:

  1. Problème potentiel avec les collections paresseuses. http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. L'entité doit contenir un comportement (contrairement à un modèle de domaine anémique ). Vous ne souhaiterez peut-être pas laisser votre interface utilisateur appeler un comportement inattendu.
  3. Dans le cas d'un modèle de domaine anémique, vous ne souhaiterez peut-être pas exposer la structure de votre modèle à l'interface utilisateur, car chaque nouvelle modification du modèle peut casser l'interface utilisateur.

Je préfère laisser ma couche de service convertir les entités en DTO correspondant dans les deux sens. DAO retourne toujours l'entité (ce n'est pas son travail d'assurer la conversion).

Mik378
la source
Donc, si je comprends bien, le service ne traite essentiellement que des objets DTO et agit comme intermédiaire à la fois de l'interface utilisateur et de DAO. De plus, au point 3, vous devez toujours convertir votre DTO en éléments d'interface utilisateur réalisables, donc une mise à jour de domaine ne casserait-elle pas encore l'interface utilisateur car DTO a également besoin d'une mise à jour.
dardo
1
Les éléments de l'interface utilisateur @dardo SONT DTO, ou au pire, doivent être convertis en DTO avant d'appeler certains services côté serveur. Les DTO ne sont pas susceptibles de changer souvent, il y a juste une adaptation de vos entités axée sur les besoins de l'interface utilisateur. En outre, la couche service doit se soucier à la fois: du DTO et des entités.
Mik378
Ah ok, il y a le hoquet que je ne comprenais pas. Le modèle de domaine anémique est assez courant là où je travaille, et j'essaie de changer un peu le paradigme pour encourager une couche de service plus fine. Merci encore!
dardo
@dardo Vous pouvez lire ce livre. (ou montrez-le à votre entreprise;))
Très
effectivement obtenu celui-ci sur Kindle, amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/… assez bien jusqu'à présent = D
dardo
13

L'une des raisons pour lesquelles je pense que cette discussion revient à plusieurs reprises, c'est parce que cela semble être une douleur intense de prendre un objet avec toutes les données dont vous avez besoin et de le convertir en un objet qui semble identique ou presque identique à celui vous remettez.

C'est vrai, c'est un PITA. Mais il y a plusieurs raisons (en plus de celles énumérées ci-dessus) pour le faire.

  • Les objets de domaine peuvent devenir très lourds et contenir beaucoup d'informations inutiles pour l'appel. Ce ballonnement ralentit l'interface utilisateur en raison de toutes les données transmises, rassemblées / non contrôlées et analysées. Lorsque vous considérez qu'un FE aura de nombreux liens faisant référence à vos services Web et étant appelé avec AJAX ou une autre approche multi-thread, vous rendrez rapidement votre interface utilisateur lente. Tout cela se traduit par l'évolutivité générale des services Web
  • La sécurité peut facilement être compromise en exposant trop de données. Au minimum, vous pouvez exposer les adresses e-mail et les numéros de téléphone des utilisateurs si vous ne les supprimez pas du résultat DTO.
  • Considérations pratiques: Pour qu'un objet défile en tant qu'objet de domaine persistant ET qu'un DTO, il devrait avoir plus d'annotations que de code. Vous aurez un certain nombre de problèmes avec la gestion de l'état de l'objet lors de son passage à travers les couches. En général, il s'agit beaucoup plus d'un PITA à gérer que de simplement faire l'ennui de copier des champs d'un objet de domaine vers un DTO.

Mais, vous pouvez le gérer assez efficacement si vous encapsulez la logique de traduction dans une collection de classes de conversion

Jetez un œil à lambdaJ où vous pouvez faire 'convertir (domainObj, toDto)' il y a une surcharge de ceci pour une utilisation avec des collections. Voici un exemple de méthode de contrôleur qui l'utilise. Comme vous pouvez le voir, ça n'a pas l'air si mal.

    @GET
    @Path("/{id}/surveys")
    public RestaurantSurveys getSurveys(@PathParam("id") Restaurant restaurant, @QueryParam("from") DateTime from, @QueryParam("to") DateTime to) {

        checkDateRange(from, to);

        MultiValueMap<Survey, SurveySchedule> surveysToSchedules = getSurveyScheduling(restaurant, from, to);
        Collection<RestaurantSurveyDto> surveyDtos = convert(surveysToSchedules.entrySet(), SurveyToRestaurantSurveyDto.getInstance());
        return new RestaurantSurveys(restaurant.getId(), from, to, surveyDtos);

    }
Christian Bongiorno
la source
Merci pour la contribution, et ma pensée va dans le même sens =)
dardo