Право на використання DTO


15

Ви намагалися знайти потік для базового багаторівневого веб-додатку та читали конфліктну інформацію в Інтернеті. Я намагаюся з’ясувати, чи є перевага в тому, щоб все-таки використовувати об’єкти DTO від вашого рівня DAO до сервісу через використання якогось картографу.

Основний потік, який я передбачаю, такий:

  1. Модель / форма користувальницького інтерфейсу -> Контролер
  2. Контролер перетворює модель в об’єкт домену (сутність)
  3. Об'єкт домену -> Службовий шар
  4. Об'єкт домену -> DAO
  5. DAO -> Об'єкти доменів
  6. Сервіс -> інтерфейс користувача
  7. UI перетворює Домен в моделі інтерфейсу користувача

Якщо DTO дотримувався, DAO поверне DTO, а не Entity. Після деякого читання здається, що DTO став дещо невдалим, оскільки (принаймні, на Java) суб'єкти стали коментувати POJO, тобто їх пам’ять стала дуже маленькою.

Це так, чи повинні використовувати DTO для повного інкапсулювання доменних об'єктів у шарі DAO, і якщо це так, то який би службовий шар перейшов до DAO?

Дякую купу!

Відповіді:


20

На мою думку, передача стійкого POJO, як, наприклад, квасоля, якою керує JPA, не є ДОБРОЮ практикою.

Чому?

Я бачу три основні причини:

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

Я вважаю за краще дозволити моєму сервісному рівню перетворювати об'єкти у відповідні DTO в обох напрямках. DAO як і раніше повертається суб'єктом (не його завдання забезпечити конверсію).


Тож якщо я правильно це розумію, сервіс по суті має справу лише з об'єктами DTO і виступає посередником і інтерфейсу користувача, і DAO. Крім того, у пункті 3 вам все одно доведеться перетворити свій DTO в працездатні елементи інтерфейсу, тому що оновлення домену все ще не порушило інтерфейс користувача, оскільки DTO також потребує оновлення.
Дардо

1
Елементи інтерфейсу @dardo ARE 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

Однією з причин, на яку я думаю, що ця дискусія виникає неодноразово, це тому, що здається серйозним болем у дупі взяти об’єкт зі всіма необхідними даними та перетворити його в об'єкт, який виглядає ідентичним або майже ідентичним тому, ти передаєш

Це правда, це ПІТА. Але є кілька причин (крім перерахованих вище) для цього.

  • Об'єкти домену можуть бути дуже важкими і містять багато непотрібної інформації для дзвінка. Цей наліт уповільнює інтерфейс користувача через всі дані, передані, маршальовані / необмежені та проаналізовані. Якщо ви вважаєте, що ЗП матимуть численні посилання, що стосуються ваших веб-сервісів та дзвінків за допомогою AJAX або якогось іншого багатопотокового підходу, ви швидко зробите ваш інтерфейс повільним. Все це доходить до загальної масштабованості веб-сервісів
  • Безпеку можна легко поставити під загрозу, викривши занадто багато даних. Як мінімум, ви можете відкрити адреси електронної пошти та номери телефонів користувачів, якщо не усунути їх з результату DTO.
  • Практичні міркування: Щоб 1 об'єкт парадував як збережений доменний об'єкт AND DTO, він повинен мати більше приміток, ніж код. У вас виникне будь-яка кількість проблем із керуванням станом об’єкта під час його проходження через шари. Взагалі, це набагато більше, ніж PITA для управління, а потім просто виконувати набір копіювання полів з об’єкта домену в DTO.

Але ви можете досить ефективно керувати ним, якщо інкапсулювати логіку перекладу у колекцію класів перетворювачів

Погляньте на lambdaJ, де ви можете зробити "конвертувати (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);

    }

Дякую за вклад, і моє мислення йде по тих же лініях =)
Дардо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.