Почему объекты передачи данных (DTO) являются анти-шаблоном?

132

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

Зачем? Какие есть альтернативы?

ntownsend
источник
11
Возможно, потому, что бизнес-объекты сами могут передавать свои данные, большое вам спасибо!
Зойдберг,
13
«Антипаттерн» вполне может быть моей кандидатурой на «фразу, 15 минут которой истекли давным-давно». Сейчас это синоним «Я не хочу оправдывать свое мнение», например, «Хорошо известно, что ...»
Крейг Стунц
6
Зойдберг, отправка объектов с методами по сети, дала нам CORBA, DCOM и другие возможности, о которых я пытаюсь стереть память. Проблема в том, что рано или поздно люди захотят вызвать эти методы.
Craig Stuntz
10
DTOS воплощают принцип DRY, который несчастливо в J2EE стоит за сделай повторяться.
joeforker
Вы можете прочитать это: Объект передачи данных - это позор
yegor256

Ответы:

139

В некоторых проектах все данные хранятся дважды . Один раз как объекты домена и один раз как объекты передачи данных.

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

KLE
источник
5
Уточните, пожалуйста, «огромную стоимость». Кроме того, скажите, почему затраты не могут быть устранены с помощью методов генерации кода для создания классов DTO.
Джон Сондерс,
70
+1. Дважды? Только если вам повезет :-) Проекты, которые дублируют сущности предметной области как DTO, также имеют тенденцию иметь почти такие же, но очень немного разные компоненты пользовательского интерфейса, дополняющие их. Это 3. И если, не дай бог, будет какое-то удаленное взаимодействие (веб-сервисы / xml-rpc / что-то еще), вы легко сможете добраться до 4 или 5.
ChssPly76
17
В настоящее время я работаю с корпоративной 14-слойной архитектурой лазаньи (НЕ ДЕТСКАЯ). Могу заверить вас, что около 11 слоев, предназначенных в основном для передачи данных, не предоставляются бесплатно.
KarlP
10
Кроме того, хотя я очень люблю генераторы кода при работе с дурацкими проектами, они а) наверняка делают что-то неправильно с самого начала. б) они не приходят бесплатно.
KarlP
7
Извините, но это просто неверно, и неправильный ответ получил высокую оценку и был принят. Прежде всего, вы можете использовать отражение для генерации DTO на лету. Во-вторых, вы можете использовать «корневое определение», например, в системе CASE или в oAW и генерировать BO и DTO (ы). В-третьих, вы можете использовать XSD и JAXB для создания DTO и использовать DTO в качестве основы для BO, или вы можете сгенерировать оба из XSD ... в любом случае, если кто-то осмелится передать EJB, только что полученный из БД, через провод к клиентской программе ... в среде, с которой я работаю, его голова скоро окажется на серебряной пластине ...
Энджел О'Сфер
128

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

Я знаю, что это вопрос, ориентированный на Java, но в языках .NET анонимные типы, сериализация и LINQ позволяют создавать DTO «на лету», что сокращает время настройки и накладные расходы на их использование.

Гейб Мутхарт
источник
15
@John, это неверно. Я делаю это все время. Сериализация использует отражение, которое отлично работает с анонимными типами. Просто передайте его сериализатору как объект. И как только он будет сериализован (например, в xml или json), вы, конечно, можете вернуть его из метода.
Гейб Мутхарт,
8
Гм, Джон, это просто неправда. Вы можете легко сериализовать анонимные типы в JSON. Попробуйте это в приложении MVC: return Json (new {Foo = "Привет!}); Я обещаю, что он работает отлично. Возможно, лучше, чем неанонимные типы, поскольку анонимные типы обычно не имеют циклов в своих графах объектов. , которые нарушают сериализатор JSON.
Крейг Стунц,
1
Сериализация Json не является DTO в этом смысле и поэтому не применяется. Тогда, конечно, мои аргументы выше также применимы, в какой-то момент они просто перестают того стоить.
Джим Бэрроуз,
1
Гейб прав, DTO не является анти-шаблоном как таковой (но может быть использован при неправильном использовании!), Когда нет дублирования данных. Например, BO может агрегировать данные из разных источников в DTO.
astro
3
+1. И есть много других причин, помимо экономии пропускной способности, по которым вам понадобятся DTO. Разрешено ли вам (политикой компании или законом) рассылать каждое поле по сети? Кроме того, в нашей компании наш DAO очень сложен, потому что ему необходимо выполнить все эти оптимизации - работая на уровне обслуживания, я очень рад, что они используют DTO, и не заставляют нас беспокоиться об отношениях, которые имеет Object X к какой-то другой таблице n-to-n.
user64141
25

DTO AntiPattern в EJB 3.0 говорит:

Большой вес Entity Beans в спецификациях EJB до EJB 3.0 привел к использованию таких шаблонов проектирования, как объекты передачи данных (DTO). DTO стали легковесными объектами (которые должны были быть самими компонентами управления данными в первую очередь), используемыми для отправки данных по уровням ... теперь спецификация EJB 3.0 делает модель компонента Entity такой же, как простой старый объект Java (POJO). С этой новой моделью POJO вам больше не нужно будет создавать DTO для каждой сущности или для набора сущностей ... Если вы хотите отправлять сущности EJB 3.0 по уровню, просто реализуйте java.io.Serialiazable

AEM
источник
6
Верно, когда вы переносите объекты между методами в одной JVM в памяти. Неправда, когда вы на самом деле сериализуете по сети и хотите контролировать глубину сериализации и / или сохранять ленивую загрузку.
wrschneider
Да, и даже в одной и той же JVM вам действительно стоит позаботиться о том, чтобы оставаться в том же направлении, если вы используете управление транзакциями JEE / Spring.
Marc
20

Я не думаю, что DTO являются антипаттерном как таковым, но есть антипаттерны, связанные с использованием DTO. Билл Дадни приводит в качестве примера взрыв DTO:

http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf

Здесь также упоминается ряд злоупотреблений DTO:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/

Они возникли из-за трехуровневых систем (обычно использующих EJB в качестве технологии) в качестве средства передачи данных между уровнями. Большинство современных Java-систем, основанных на таких фреймворках, как Spring, используют альтернативный упрощенный вид с использованием POJO в качестве объектов домена (часто аннотированных JPA и т. Д.) На одном уровне ... Использование DTO здесь не требуется.

Джон
источник
3
Вы совершенно правы, что DTO являются хорошим шаблоном , а не анти-шаблоном, когда используются в их правильном контексте. Ваша вторая ссылка сейчас кажется мертвой, но самое большое злоупотребление, которое я видел, - это когда каждый объект домена имел соответствующий «DTO» для взаимодействия с базой данных, который не добавлял никакой ценности и вообще не был DTO!
Дэвид
19

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

Дарин димитров
источник
9

Некоторые считают DTO антипаттерном из-за их возможных злоупотреблений. Их часто используют, когда они не должны / не нужны.

В этой статье расплывчато описаны некоторые нарушения.

Бен С
источник
1
В статье гораздо точнее описываются DTO как шаблон, которым можно злоупотреблять.
Craig Stuntz
Это сводится к ответу только по ссылке, для этого действительно нужна хотя бы цитата из статьи. не знаю, как это удалось не пометить как «Не ответ».
Натан Хьюз
Ссылка мертва, попробуйте web.archive.org/web/20110707143818/https://anirudhvyas.com/root/…
Davi Lima
7

Если вы создаете распределенную систему, то DTO, безусловно, не антипаттерн. Не все будут развиваться в этом смысле, но если у вас есть (например) приложение Open Social, все работают на JavaScript.

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

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

Билер
источник
4

Намерение передачи данных объекта для хранения данных из разных источников , а затем передать его в базу данных (или удаленный фасад ) сразу.

Однако шаблон DTO нарушает принцип единой ответственности , поскольку DTO не только хранит данные, но и передает их из или в базу данных / фасад.

Необходимость отделить объекты данных от бизнес-объектов не является антипаттерном, поскольку, вероятно, в любом случае потребуется отделить уровень базы данных .

Вместо DTO вы должны использовать шаблоны Aggregate и Repository, которые разделяют коллекцию объектов ( Aggregate ) и передачу данных ( Repository ).

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

MovGP0
источник
4

DTO становится необходимостью, а не АНТИШАБЛОНОМ, когда все объекты вашего домена загружают связанные объекты EAGERly.

Если вы не создадите DTO, у вас будут ненужные объекты, перенесенные с вашего бизнес-уровня на ваш клиентский / веб-уровень.

Чтобы ограничить накладные расходы в этом случае, лучше перенесите DTO.

javadev
источник
1

Вопрос должен быть не «почему», а « когда ».

Безусловно, это анти-шаблон, когда только результатом его использования является более высокая стоимость - время выполнения или обслуживание. Я работал над проектами, имеющими сотни DTO, идентичных классам сущностей базы данных. Каждый раз, когда вы хотели добавить одно поле, которое вы рекламируете, чтобы добавить идентификатор, например, четыре раза - в DTO, в сущность, в преобразование из DTO в классы или сущности домена, обратное преобразование, ... Вы забыли некоторые места и данные, полученные противоречивы.

Это не антипаттерн, когда вам действительно нужно другое представление классов предметной области - более плоское, более богатое, более узкое, ...

Лично я начинаю с класса предметной области и передаю его, тщательно проверяя в нужных местах. Я могу аннотировать и / или добавлять некоторые «вспомогательные» классы для сопоставления с базой данных, с форматами сериализации, такими как JSON или XML ... Я всегда могу разделить класс на два, если чувствую в этом необходимость.

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

Ростислав Матль
источник
1

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

jdehaan
источник