Entidad para el uso de DTO

15

He estado tratando de encontrar un flujo para una aplicación web básica por niveles, y he estado leyendo información conflictiva en línea. Lo que estoy tratando de averiguar es si hay una ventaja de seguir usando objetos DTO de su capa DAO a Servicio mediante el uso de algún tipo de mapeador.

El flujo básico que preveo es el siguiente:

  1. Modelo / formulario de IU -> Controlador
  2. El controlador convierte el modelo en objeto de dominio (entidad)
  3. Objeto de dominio -> Capa de servicio
  4. Objeto de dominio -> DAO
  5. DAO -> Objeto (s) de dominio
  6. Servicio -> UI
  7. La interfaz de usuario convierte el dominio en modelos de interfaz de usuario

Si se siguió DTO, DAO devolvería un DTO, no la Entidad. Después de leer un poco, parece que DTO se ha vuelto ligeramente difunto ya que (al menos en Java) las entidades se han convertido en POJO anotados, lo que significa que su huella de memoria se ha vuelto muy pequeña.

¿Es este el caso, o deberían usarse DTO para encapsular completamente los objetos de dominio dentro de la capa DAO y, si este es el caso, qué pasaría la capa de servicio al DAO?

¡Gracias un montón!

Dardo
fuente

Respuestas:

20

Según yo, pasar un POJO persistente, como por ejemplo un bean administrado por JPA, no es LA buena práctica.

¿Por qué?

Veo tres razones principales:

  1. Posible problema con colecciones perezosas. http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. La entidad debe contener comportamiento (a diferencia de un modelo de dominio anémico ) Es posible que no desee que su IU llame a un comportamiento inesperado.
  3. En el caso de un modelo de dominio anémico, es posible que no desee exponer la estructura de su modelo a la interfaz de usuario, ya que cada nuevo cambio en el modelo puede romper la interfaz de usuario.

Prefiero dejar que mi capa de servicio convierta entidades en el DTO correspondiente en ambas direcciones. DAO sigue devolviendo entidad (no es su trabajo asegurar la conversión).

Mik378
fuente
Entonces, si estoy entendiendo esto correctamente, el servicio esencialmente trata solo con objetos DTO y actúa como intermediario tanto de UI como de DAO. Además, en el punto 3, todavía tiene que convertir su DTO en elementos de interfaz de usuario factibles, por lo que una actualización de dominio aún no rompería la interfaz de usuario debido a que DTO también necesita una actualización.
dardo
1
Los elementos de la interfaz de usuario de @dardo SON DTO, o en el peor de los casos, deben convertirse a DTO antes de llamar a algunos servicios en el lado del servidor. No es probable que los DTO cambien a menudo, solo hay una adaptación de sus entidades centradas en las necesidades de la interfaz de usuario. Además, la capa de servicio debería preocuparse por ambos: DTO y entidades.
Mik378
Ah ok, está el hipo que no entendía. El modelo de dominio anémico es bastante común donde trabajo, y estoy tratando de cambiar un poco el paradigma para fomentar una capa de servicio más delgada. ¡Gracias de nuevo!
dardo
@dardo Puedes leer este libro. (o muéstralo a tu empresa;)) Gran gran libro: amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378
en realidad tengo este en kindle, amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/… bastante bueno hasta ahora = D
dardo
13

Una de las razones por las que creo que esta discusión surge repetidamente es porque parece un gran dolor de cabeza tomar un objeto con todos los datos que necesita y convertirlo en un objeto que se vea idéntico o casi idéntico al que estás entregando

Es verdad, es una PITA. Pero hay algunas razones (además de las enumeradas anteriormente) para hacerlo.

  • Los objetos de dominio pueden volverse muy pesados ​​y contener mucha información inútil para la llamada. Esta hinchazón ralentiza la interfaz de usuario debido a todos los datos transmitidos, ordenados / desglosados ​​y analizados. Cuando considere que una FE tendrá numerosos enlaces que hacen referencia a sus servicios web y que se le llame con AJAX o algún otro enfoque de subprocesos múltiples, rápidamente hará que su IU sea lenta. Todo esto llega a la escalabilidad general de los servicios web
  • La seguridad puede verse comprometida fácilmente al exponer demasiados datos. Como mínimo, podría exponer las direcciones de correo electrónico y los números de teléfono de los usuarios si no los elimina del resultado DTO.
  • Consideraciones prácticas: para que 1 objeto desfile como un objeto de dominio persistente Y un DTO, debería tener más anotaciones que código. Tendrá varios problemas con la administración del estado del objeto a medida que pasa a través de las capas. En general, esto es mucho más de una PITA para administrar que simplemente hacer el tedio de copiar campos de un objeto de dominio a un DTO.

Pero puede administrarlo de manera bastante efectiva si encapsula la lógica de traducción en una colección de clases de convertidor

Eche un vistazo a lambdaJ donde puede hacer 'convertir (domainObj, toDto)', hay una sobrecarga de esto para usar con colecciones. Aquí hay un ejemplo de un método de controlador que lo utiliza. Como puede ver, no se ve tan 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
fuente
Gracias por el aporte, y mi pensamiento está en la misma línea =)
dardo