Сущность для использования DTO

15

Я пытался создать поток для базового многоуровневого веб-приложения и читал противоречивую информацию в Интернете. Я пытаюсь выяснить, есть ли преимущество в том, чтобы все еще использовать объекты DTO от вашего DAO до уровня Service через использование какого-то рода мапперов.

Основной поток, который я предвижу, выглядит следующим образом:

  1. Модель пользовательского интерфейса -> Контроллер
  2. Контроллер преобразует модель в доменный объект (объект)
  3. Доменный объект -> Сервисный уровень
  4. Доменный объект -> DAO
  5. DAO -> Доменный объект (ы)
  6. Сервис -> Интерфейс
  7. Пользовательский интерфейс преобразует домен в модели пользовательского интерфейса

Если следовать DTO, DAO вернет DTO, а не Организацию. После некоторого чтения кажется, что DTO немного перестал существовать, поскольку (по крайней мере, в Java) объекты стали аннотированными POJO, что означает, что их объем памяти стал очень маленьким.

Так ли это, или следует использовать DTO для полной инкапсуляции объектов домена на уровне DAO, и, если это так, что бы уровень обслуживания передавал DAO?

Огромное спасибо!

Dardo
источник

Ответы:

20

По моему мнению, передача персистентного POJO, как, например, боб, управляемый JPA, не является хорошей практикой.

Почему?

Я вижу три основные причины:

  1. Потенциальная проблема с ленивыми коллекциями. http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. Сущность должна содержать поведение (в отличие от модели домена Anemic ). Возможно, вы не захотите, чтобы ваш пользовательский интерфейс вызывал неожиданное поведение.
  3. В случае анемичной доменной модели вы можете не захотеть предоставлять структуру вашей модели пользовательскому интерфейсу, поскольку каждое новое изменение в модели может нарушать пользовательский интерфейс.

Я предпочитаю, чтобы мой уровень обслуживания преобразовывал сущности в соответствующие DTO в обоих направлениях. DAO по-прежнему возвращает сущность (это не его задача - обеспечить преобразование).

Mik378
источник
Так что, если я правильно понимаю, сервис по сути имеет дело только с объектами DTO и действует как посредник как UI, так и DAO. Кроме того, в пункте 3 вам все еще необходимо преобразовать DTO в работающие элементы пользовательского интерфейса, поэтому обновление домена не нарушит пользовательский интерфейс, поскольку DTO также нуждается в обновлении.
Дардо
1
Элементы пользовательского интерфейса @dardo являются DTO или, в худшем случае, должны быть преобразованы в DTO перед вызовом некоторых служб на стороне сервера. DTO вряд ли будет часто меняться, есть только адаптация ваших организаций, ориентированная на потребности пользовательского интерфейса. Кроме того, уровень обслуживания должен заботиться как о DTO, так и об организациях.
Mik378
Ах, хорошо, это сбой, который я не поняла. Модель анемичной области довольно распространена там, где я работаю, и я пытаюсь немного изменить парадигму, чтобы стимулировать более тонкий уровень обслуживания. Еще раз спасибо!
Дардо
@dardo Вы можете прочитать эту книгу. (или покажите это своей компании;)) Отличная отличная книга: amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378
на самом деле получил его на Kindle, amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/… пока неплохо = D
dardo
13

Одна из причин, по которой я думаю, что эта дискуссия повторяется неоднократно, заключается в том, что мне кажется, что очень трудно получить объект со всеми необходимыми данными и преобразовать его в объект, который выглядит идентичным или почти идентичным ты сдаешь.

Это правда, это ПИТА. Но для этого есть несколько причин (помимо перечисленных выше).

  • Доменные объекты могут быть очень тяжелыми и содержать много бесполезной информации для вызова. Это раздувание замедляет пользовательский интерфейс из-за того, что все данные передаются, маршалируются / разбираются и анализируются. Если вы считаете, что у FE будет множество ссылок, относящихся к вашим веб-сервисам и вызываемых с помощью AJAX или другого многопоточного подхода, вы быстро замедлит свой пользовательский интерфейс. Все это попадает в общую масштабируемость веб-сервисов
  • Безопасность можно легко поставить под угрозу, подвергая слишком много данных. Как минимум, вы можете указать адреса электронной почты и номера телефонов пользователей, если не исключите их из результата DTO.
  • Практические соображения: для 1 объекта, который будет выглядеть как постоянный объект домена и DTO, он должен иметь больше аннотаций, чем код. У вас будет множество проблем с управлением состоянием объекта, когда он проходит через слои. В общем, управлять PITA гораздо проще, чем просто копировать поля из объекта домена в DTO.

Но вы можете управлять им достаточно эффективно, если инкапсулируете логику перевода в коллекцию классов преобразователей.

Взгляните на lambdaJ, где вы можете выполнить команду 'convert (domainObj, toDto)', но есть перегрузка для использования с коллекциями. Вот пример метода контроллера, который использует его. Как видите, все выглядит не так плохо.

    @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);

    }
Кристиан Бонджорно
источник
Спасибо за вклад, и мои мысли в том же духе =)
dardo