я понял, наконец

MiksIr

miksir@home:~$
А HTTP-запрос тоже DTO должен отправлять? Или в AMQP-очередь себя добавлять?
"Как" отправить - одно. "Что" отправить - другое. DTO отвечает на вопрос "что отправить". И это "что" - данные, которые нужно отправить так, что бы их потом можно было восстановить.

А модель может знать, как записать себя в MySQL, PostgreSQL или MongoDB.
Так у тебя в голове DTO это что-то сродни модели? Так бы и сказал, а то тратишь наше время.
К слову сохранение в базу как таковое показывает, что DTO часто не нужно вообще, хватит и мапинга.

Да. Конфиг маппинга.

Ты так говоришь, как будто это что-то плохое.
А что хорошего то? Тебе не кажется, что DTO и конфиг мапинга как-то дублируют друг друга по функционалу? Если у нас такой продвинутый конфиг мапинга, то зачем вообще DTO? Подать в сериализатор доменные модели и пусть разгребает... и так делают, разве нет? А к DTO прибегают, когда конфиг мапинга становится слишком сложен, что бы переварить все данные к отправке. Так, ввели DTO как замену конфига мапинга, но добавили конфиг мапинга дто. Нахрена? Может в DTO что-то подправить?

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

fixxxer

К.О.
Партнер клуба
Так у тебя в голове DTO это что-то сродни модели?
Это аналогия (хотя с Read Model действительно много общего).
Все это напоминает мне давние дискуссии в защиту ActiveRecord. Что ActiveRecord говно, вроде до всех дошло, а тут ровно в аналогичной ситуации почему-то еще нет.
Подать в сериализатор доменные модели
Не доменные модели, а read models, не в сериализатор, а в маппер, не выиграл, а проиграл, а на дереве Гоголь сидит, а так да =)
 
Последнее редактирование:

whirlwind

TDD infected, paranoid
Ребят, ну очевидно же, что сериализация в DTO не позволяет хорошо работать с абстракцией транспорта. В соседней теме слюной брызгали по поводу SRP и ISP. Ну вот вам самый элементарный пример. На VO/DTO можно посмотреть и с точки зрения изнутри системы. Если у вас хороший SRP, то много классов, между которыми эти самые VO гуляют в качестве аргумента. Выгоднее передавать эти самые VO, чем раскрывать детали в контрактах. Это как объявлять в прототипах first name, last name вместо user, year, month, day вместо date и т.д. Очевидно, что в случае необходимости расширить модель (а это типичный кейс в бизнес приложениях), то это изменение затронет весь ваш код насквозь. А то что вы в VO пытаетесь добавить функционал транспортного уровня это вообще малая часть проблемы. В случае сериализации внутри VO, любое расширение затронет не только сам VO который у вас уже работает. Вам придется его модифицировать, вместо добавления новой реализации сериализатора. Тут целый букет нарушений SOLID, в том числе OCP. Если вы не меняли REST на какой нибудь ZMQ, это не значит что такой задачи не возникнет в будущем. В чем проблема подстраховаться заранее?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Это аналогия (хотя с Read Model действительно много общего).
Все это напоминает мне давние дискуссии в защиту ActiveRecord. Что ActiveRecord говно, вроде до всех дошло, а тут ровно в аналогичной ситуации почему-то еще нет.

Не доменные модели, а read models, не в сериализатор, а в маппер, не выиграл, а проиграл, а на дереве Гоголь сидит, а так да =)
Ваше личное мнение для меня важно, но копать я не перестану, обоснование важнее.
Я все еще считаю реализации AR общим решением лучше, чем доктрину, в виде слоя доступа. Обсуждать нечего потому что опыт важнее мнения.
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А HTTP-запрос тоже DTO должен отправлять? Или в AMQP-очередь себя добавлять?

А модель может знать, как записать себя в MySQL, PostgreSQL или MongoDB.

Конечно. А еще могут быть нюансы, как какое поле сохранить в MySQL или PostgreSQL. Нерешамая проблема без Active Record!

Да. Конфиг маппинга.

Ты так говоришь, как будто это что-то плохое.
Наша тема - синтаксические конструкции языка и паттерны дизайна для передачи указателей на память в параметры вызовов. Зачем пудрить мозги эмоциональными фразами про HTTP-запрос, AR, MySQL, AMQP?
Получается, что не очень ты разбираешься в том, что пишешь. OK, закончу на этом.
 
Последнее редактирование:

MiksIr

miksir@home:~$
Ребят, ну очевидно же, что сериализация в DTO не позволяет хорошо работать с абстракцией транспорта. В соседней теме слюной брызгали по поводу SRP и ISP. Ну вот вам самый элементарный пример. На VO/DTO можно посмотреть и с точки зрения изнутри системы. Если у вас хороший SRP, то много классов, между которыми эти самые VO гуляют в качестве аргумента. Выгоднее передавать эти самые VO, чем раскрывать детали в контрактах. Это как объявлять в прототипах first name, last name вместо user, year, month, day вместо date и т.д. Очевидно, что в случае необходимости расширить модель (а это типичный кейс в бизнес приложениях), то это изменение затронет весь ваш код насквозь. А то что вы в VO пытаетесь добавить функционал транспортного уровня это вообще малая часть проблемы. В случае сериализации внутри VO, любое расширение затронет не только сам VO который у вас уже работает. Вам придется его модифицировать, вместо добавления новой реализации сериализатора. Тут целый букет нарушений SOLID, в том числе OCP. Если вы не меняли REST на какой нибудь ZMQ, это не значит что такой задачи не возникнет в будущем. В чем проблема подстраховаться заранее?
Немного не понял, ты считаешь VO и DTO одним и тем же?

Для передачи по транспорту используется DTO. Передача, это "что", "в каком виде" и "куда". Куда -это ваш транспорт, что - входной набор моделей, или, как у веганов, read моделей, остается в "каком виде". В каком виде можно тоже разбить на две подзадачи - трансформация моделей в ожидаемую структуру и сериализация в строку. Трансформацией занимается DTO билдер, он инкапсулирует знание о том, как входящее превратить в исходящее. Сериализация в строку тоже должна быть инкапсулирована с данными, которые сериализуются, разве нет? И это и есть DTO.

Иначе же получается, что у нас есть просто ненужный DTO, который проще заменить на массив, и есть какой-то хелпер сериализатор, у которого программированием на конфигах заложена конвертация. Но на самом деле тут я вижу некий самообман. Вот представь, что был json, нужно добавить xml, в него некие специфические нюансы, которые нужно отобразить в xml, например, для автоматической генерации схемы всякие min max и т.п. Ты берешь xml сериализатор, и теперь нужно написать конфигов, что бы он с этой конкретной DTO работал правильно. Конфиги, конечно же, удобно вписать прямо аннотациями в это DTO. И если посмотреть на это с другой стороны - у тебя DTO все так же управляет сериализацией, причем не какой-то абстрактной, а конкретной - в xml. Т.е. вот это вот написание аннотаций по сути своей, по ответственности - не особо отличается от метода в DTO - convertToXml или getPreparedArrayForXML. Мы просто набросали красивой шелухи, что бы говорить - как у нас все подстраховано.
 

whirlwind

TDD infected, paranoid
Немного не понял, ты считаешь VO и DTO одним и тем же?
Я понимаю, что ты аппелируешь к Фаулеру. Я его, конечно, уважаю, но ссылка на авторитет не является аргументом в споре.
Делать так как у него в этом паттерне написано - это плохое решение. С большими натяжками я могу принять что пара методов для одного формата могут быть реализованы так как у него, но в конечном итоге это будет подвергнуто рефакторингу. Здесь сработает правило двух ударов от GoF. И я всегда говорил, в любой спорной ситуации тест покажет кто прав. Покажите мне тест на DTO в кейсе нескольких форматов.

VO - это маленький объект, типа Data, Decimal, Money. DTO - это большой объект, который может состоять из примитивов, VO и других объектов. Да, мы можем заменить объект на массив. Но мы так же можем не использовать и тайп хинтинг. Но если ты не осознаешь к чему приводит намеренное ослабление рамок, то я не понимаю о проектах каких масштабов мы говорим. Передача объектом дает возможность делать надежные и лаконичные интерфейсы при сохранении контроля над содержимым. Передача массива - нет.

ЗЫ. А что касается конфигов, это вообще отдельный разговор. Если вы не в курсе, то сегодня существует проблема аналогичная прежней dll hell. Называется config hell. Когда каша из конфигов и аннотаций размазана по всему проекту, для понимания процесса надо скакать между кодом и конфигами, в тестах проходит а на проде падает потому что конфиги разные, привязать класс к другому источнику данных нельзя ибо он IoC-е сингельтон на аннотациях и тп проблемы. Все от "очень удобных" конфигов. Лично я не фанатею.
 
Последнее редактирование:

Yoskaldyr

"Спамер"
Партнер клуба
классический клубный срач :)

@MiksIr спорит с @whirlwind и оба пытаются доказать одно и то же, что слишком много конфигов это зло... Интересно кто победит в итоге :))))
 

whirlwind

TDD infected, paranoid
ЗЗЫ. Про конвертацию тут есть еще такая тонкость, что обычно конвертор содержит несколько методов для конвертации разных DTO. И стратегически выгоднее держать их вместе. В случае необходимости внести изменения на базовом уровне, проще все видеть в одном модуле. Дополняя новыми методами для новых DTO, перед глазами стоят наглядные примеры DTO-соседей.

Пример: https://github.com/robot-aquila/aquila-transaq/blob/master/src/main/java/ru/prolib/aquila/transaq/impl/TQParser.java
 
Последнее редактирование:

MiksIr

miksir@home:~$
Покажите мне тест на DTO в кейсе нескольких форматов.
Два теста, одни дергает toJson и сравнивает на строку, другой toXML и сравнивает на строку
Что-то не вижу проблемы.
Я даже не исключаю варианта, что будет XmlDTO и JsonDTO и билдер будет знать, как их собрать.
Опять же, я согласен, что toXML у фаулера - это не догма. И все хорошо до тех пор, пока некому toxmlstring не появляется необходимость что-то знать про эти данные... получается, что dto билдер знает про данные, dto знает про данные, и мы еще делаем SpecificDtoToXml (возможно в виде конфигов), который тоже знает про данные? Эм... нафига? Какую задачу то мы этим решаем? Чего ради нарушили инкапсуляцию? Поместить конвертацию DTO в XML в одном месте, как ты сказал? А разве DTO то у нас не в этом одном месте? DTO - локальная штука живущая именно в этом модуле. Не должен модуль запроса в апи1 переиспользовать DTO из модуля запроса в апи2, даже если они одинаковые.
VO - это маленький объект, типа Data, Decimal, Money. DTO - это большой объект, который может состоять из примитивов, VO и других объектов.
Ну наверное разница не в размере все же?
Но если ты не осознаешь к чему приводит намеренное ослабление рамок, то я не понимаю о проектах каких масштабов мы говорим. Передача объектом дает возможность делать надежные и лаконичные интерфейсы при сохранении контроля над содержимым. Передача массива - нет.
Интерфейсы вида getData? или какой интерфейс у DTO которое только данные? Ну да ладно, я понял о чем ты, и сам вижу этот плюс, но! В 99% случаев эти имена полей в коде указаны будут в одном месте - нормализаторе, который конвертит пачку входную в единый массив. А дальше уже тупая сериализация, которой не нужно ничего знать про структуру. Т.е. получается DTO ради DTO?
Не, я еще могу понять случаи, когда DTO в общем и не ваш кусок кода, а генерация из какого-нибудь свагера или grpc, но вообще не уверен, что можно назвать это объектом

Вообще, можно начать с того - что такое объект. Являются ли данные заданной структуры, но без поведения - объектом? Является ли Data Transfer Object - объектом?
 
Последнее редактирование:

MiksIr

miksir@home:~$
классический клубный срач :)

@MiksIr спорит с @whirlwind и оба пытаются доказать одно и то же, что слишком много конфигов это зло... Интересно кто победит в итоге :))))
Да не, не о конфигах речь. Я скорее вижу это так - логично ли положить методы работы с данными, которые делают именно то, для чего предназначены эти данные - к самим данным. Или же логика работы с этими данными должна быть в одном месте, а сами данные - в другом. Почему тогда модели не делать вида ModelData, МodelLogic(ModelData) ... ох, стоп, так делают... в процедурном подходе
 

AmdY

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

whirlwind

TDD infected, paranoid
Вообще, можно начать с того - что такое объект. Являются ли данные заданной структуры, но без поведения - объектом? Является ли Data Transfer Object - объектом?
Да, являются. Почему нет? В ООП вообще все завязано на точку зрения. Это часть абстрагирования. Не только сокрытие деталей, но и взгляд в контексте конкретной задачи. Те же понятия stateless, stateful нам об этом говорят.

Кстати, насчет DTO, там у Фаулера уже есть приписка, что после выхода книги, DTO вроде как переименовали в TO. Имхо, это более корректно.

PS. Не, если рассматривать DTO как request конкретного протокола, то вполне тема. Только тогда транспорт в паттерн надо добавить.
 
Последнее редактирование:

whirlwind

TDD infected, paranoid
Ну т.е. GNU C является объектно-ориентированным, ибо там есть struct - мы можем его считать объектом, и есть способы работы с этими struct
Все зависит от точки зрения...
Открою тайну. На struct в сях можно навесить типа методы. Но это грязные хаки. builtin функции привязки там нет. Все зависи от точки зрения )))
 

MiksIr

miksir@home:~$
Открою тайну. На struct в сях можно навесить типа методы. Но это грязные хаки. builtin функции привязки там нет. Все зависи от точки зрения )))
Не... тут ты хоть что-то "цепляешь". Уже с натяжкой можно назвать объектом - есть данные и прицепленные функции.
Но будет кто-то в здравом уме назвать объектом структуру без прицепленных функций?
А ведь из DTO и пытаетесь сделать такую структуру. Это не DTO, и даже не TO, это transfer structure какое-то...
 

AmdY

Пью пиво
Команда форума
В принципе @MiksIr прав, исторически, наше DTO это не совсем то, о чём думали ребята из Сан со своими java beans. Но не называть же их POPO.
 
Сверху