Что такое объект передачи данных?

218

Что такое объект передачи данных?

В MVC есть модели классов DTO, и если нет, то в чем различия и нужны ли нам оба?

Ярон Наве
источник
@ yegor256 и тот факт, что эта книга в этой статье знает, как извлечь данные из API, а также как хранить данные в БД и, таким образом, нарушать SRP, хорошо?
Бетлиста

Ответы:

223

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

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

Другое использование DTO может заключаться в инкапсуляции параметров для вызовов методов. Это может быть полезно, если метод принимает более 4 или 5 параметров.

При использовании шаблона DTO вы также должны использовать ассемблеры DTO. Ассемблеры используются для создания DTO из доменных объектов, и наоборот.

Преобразование из Доменного объекта в DTO и обратно может быть дорогостоящим процессом. Если вы не создаете распределенное приложение, вы, вероятно, не увидите каких-либо значительных преимуществ от шаблона, как объясняет здесь Мартин Фаулер

Бенни Халлетт
источник
7
«DTO создает отличные модели в шаблоне MVC», но разве модель не должна содержать все данные объекта и DTO оптимизироваться с частью данных? Если у меня есть модель A и мне нужно передать ее двум подсистемам, будут ли A_DTO_1 и A_DTO_2 с соответствующими полями каждой из них? «DTO могут заключаться в инкапсуляции параметров для вызовов методов» -> Таким образом, каждый класс, который переносит параметры, является DTO, даже если это не распределенная система? Разве модели в MVC не являются объектом домена?
Ярон Наве
2
Отвечая на ваш первый вопрос, я не думаю, что говорили об одном и том же. Модель в MVC не обязательно должна быть классом из вашей доменной модели. Сказав это, это вполне может быть. Использование DTO удаляет все ненужные вещи. Все зависит от архитектуры, которую вы собираетесь. Я не уверен, как именно ответить на ваш второй вопрос. Независимо от того, идет ли речь о проводе или нет, это все же объект, который инкапсулирует кучу данных для передачи между (подсистемами), поэтому я бы сказал, что это DTO.
Бенни Халлетт
12
«Другое использование DTO может заключаться в инкапсуляции параметров для вызовов методов. Это может быть полезно, если метод принимает более 4 или 5 параметров». На самом деле это анти-паттерн, называемый классом Полтергейста или Цыганского Универсала. Если вашему методу нужно 4 аргумента, тогда передайте ему 4, не создавайте класс, просто чтобы переместить объект в метод или класс.
Wix
2
@ Wix, хорошая мысль. Однако я бы сказал, что это нормально, если это семантически правильно (скажем, если вы передаете класс настроек со свойствами, а не сами свойства в качестве значений). Чего не следует делать, так это выдвигать все аргументы ради передачи одного объекта, так как они вполне могут быть не связаны и вызывать ночные кошмары в дальнейшем.
Арам Кочарян
3
DTO не должны использоваться для инкапсуляции параметров для вызовов методов (что сделает их LocalDTO), они были представлены в контексте удаленных интерфейсов: martinfowler.com/bliki/LocalDTO.html
Rui
28

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

голуб
источник
22

DTO - это тупой объект - он просто содержит свойства и имеет геттеры и сеттеры, но никакой другой логики какого-либо значения (кроме, может быть, реализации сравнения () или равно ()).

Обычно модельные классы в MVC (при условии .net MVC здесь) являются DTO или коллекциями / агрегатами DTO

Эрик Петроэль
источник
3
То, что вы описываете, является LocalDTO: martinfowler.com/bliki/LocalDTO.html
Rui
3
Один из случаев, когда полезно использовать что-то вроде DTO, - это существенное несоответствие между моделью на уровне представления и моделью базового домена. В этом случае имеет смысл сделать презентацию специфическим фасадом / шлюзом, который сопоставляется с моделью предметной области и представляет интерфейс, удобный для презентации.
Амитабха
14

В общем случае объекты значения должны быть неизменными. Как объекты Integer или String в Java. Мы можем использовать их для передачи данных между уровнями программного обеспечения. Если программные слои или службы работают в разных удаленных узлах, например в среде микросервисов или в устаревшем Java Enterprise App. Мы должны сделать почти точные копии двух классов. Здесь мы встретили DTO.

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

В устаревших Java Enterprise Systems DTO могут содержать различные EJB-компоненты.

Я не знаю, является ли это лучшей практикой или нет, но я лично использую объекты Value в своих проектах Spring MVC / Boot, например:

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

Уровень контроллера не знает, что это за сущности. Он связывается с объектами формы и представления значений . Объекты формы имеют аннотации проверки JSR 303 (например, @NotNull) и объекты значений представления имеют аннотации Джексона для настраиваемой сериализации. (например, @JsonIgnore)

Уровень сервиса связывается с уровнем репозитория с помощью Entity Objects. На объектах сущности есть аннотации JPA / Hibernate / Spring Data. Каждый уровень связывается только с нижним уровнем. Межуровневая связь запрещена из-за циклической / циклической зависимости.

User Service ----> XX CANNOT CALL XX ----> Order Service

Некоторые ORM Frameworks имеют возможность проецирования с использованием дополнительных интерфейсов или классов. Таким образом, репозитории могут возвращать объекты View напрямую. Там для вас не нужны дополнительные преобразования.

Например, это наш пользовательский объект:

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}

Но вы должны вернуть список пользователей с нумерацией страниц, в который входят только имя, имя, фамилия. Затем вы можете создать объект View Value для проекции ORM.

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

Вы можете легко получить постраничный результат из слоя хранилища. Благодаря весне вы также можете использовать только интерфейсы для проекций.

List<UserListItemView> find(Pageable pageable);

Не волнуйтесь, для других операций преобразования BeanUtils.copyметод работает просто отлично.

Fırat KÜÇÜK
источник
11
  1. Для меня лучший ответ на вопрос, что такое DTO, состоит в том, что DTO - это простые объекты, которые не должны содержать никакой бизнес-логики или реализации методов, которые потребовали бы тестирования .
  2. Обычно ваша модель (использующая шаблон MVC) представляет собой интеллектуальные модели, и они могут содержать множество / несколько методов, которые выполняют некоторые различные операции специально для этой модели (не бизнес-логика, это должно быть на контроллерах). Однако, когда вы передаете данные (например, вызываете конечную точку REST ( GET/ POST/ что угодно) откуда-либо, или используете веб-сервис с использованием SOA и т. Д.), Вы не хотите передавать объект большого размера с кодом, который не нужен для конечная точка будет потреблять данные и замедлять передачу.
Тиаго Бургос
источник
Почему бизнес-логика должна быть в контроллерах?
AlexioVay
6

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

Из Википедии :

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

Дэн
источник
3
Объект значения не является DTO .
coderpc
0

Объект передачи данных (DTO) описывает «объект, который переносит данные между процессами» (Википедия) или «объект, который используется для инкапсуляции данных и отправки их из одной подсистемы приложения в другую» (ответ Stack Overflow).

Мостафа Каземи
источник
0

DefN

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

Напротив, динамическая модель или «пакет свойств» решает проблему моделирования записи данных, когда производственный процесс создается во время выполнения.

Цвар

DTO может моделироваться полями или свойствами, но кто-то изобрел очень полезный контейнер данных, называемый Cvar. Это ссылка на значение. Когда DTO моделируется с помощью того, что я называю ссылочными свойствами , модули могут быть настроены на совместное использование памяти кучи и тем самым совместно работать над ней. Это полностью исключает передачу параметров и связь O2O из вашего кода. Другими словами, DTO, имеющие ссылочные свойства, позволяют коду достигать нулевой связи .

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

Источник: http://www.powersemantics.com/

Динамические DTO - необходимый компонент для динамического программного обеспечения. Чтобы создать динамический процесс, один шаг компилятора должен привязать каждую машину в сценарии к ссылочным свойствам, которые определяет сценарий. Динамическое DTO создается путем добавления Cvars в коллекцию.

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

Раздоры

Примечание: поскольку Wix пометил использование DTO для организации параметров как «анти-шаблон», я дам авторитетное мнение.

    return View(model);  // MVC disagrees

Моя совместная архитектура заменяет шаблоны проектирования. См. Мои веб-статьи.

Параметры обеспечивают непосредственное управление машиной стека кадров. Если вы используете непрерывный контроль и, следовательно, не нуждаетесь в немедленном контроле, ваши модули не нуждаются в параметрах. Моя архитектура не имеет. Внутрипроцессная конфигурация машин (методов) добавляет сложность, а также ценность (производительность), когда параметры являются типами значений. Однако параметры ссылочного типа заставляют потребителя вызывать ошибки в кэше, чтобы в любом случае получить значения из кучи - поэтому просто настройте потребителя со ссылочными свойствами. Факт из машиностроения: зависимость от параметров является своего рода предоптимизацией, потому что сама переработка (изготовление компонентов) - это отходы. Обратитесь к моей статье W для получения дополнительной информации. http://www.powersemantics.com/w.html .

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

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

По сути, нет ничего плохого в моделировании обработки, когда кучка бесполезных офисных работников, которые пересылают электронную почту друг другу, не сохраняя след электронной почты, за исключением всей дополнительной работы и головной боли, возникающих при обработке логистики и проблем с возвратом. Правильно смоделированный распределенный процесс присоединяет к продукту документ (активная маршрутизация), описывающий, из каких операций он поступил и будет выполнять. Активная маршрутизация является копией маршрутизации источника процесса, которая записывается до начала процесса. В случае дефекта или другого экстренного изменения активная маршрутизация модифицируется, чтобы включить шаги операции, на которые она будет отправлена. Это тогда учитывает весь труд, который пошел в производство.

RBJ
источник