Re[15]: DTO внутри BusinessObject
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.01.07 10:52
Оценка: 6 (1)
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, IT, Вы писали:


IT>>Зачем? Просто не передавай данные, которые не используются.

GZ>Ну нельзя так. Об этом уже говорили. В результате мы получаем вообще четырехзначную логику. Да/Нет/Пустое/Не загружен. В результате получается что мы избавляемся от главного плюса business entity — а именно абстрагирование от внутренней структуры объекта. В результате при вызове функции, мы должны всегда будем помнить — загрузили ли мы данные в BE для данной конкретной функции. Упрощения не будет, и как результат — разница между DataSet и business entity нивелируется.

Гм. Позволю себе напомнить про SQL, как протокол передачи данных между клиентом и сервером.
Вся сила SQL — именно в том, что в него встроен автоматический вывод типов. Т.е. когда я делаю
select FirstName, LastName from user

я явно указываю, какие поля вернуть. Проблемы "пустое"/"непустое" просто не существует. Можно считать, что каждый запрос неявно вводит отдельный тип DTO. При вызове функции ошибиться невозможно.

Я вижу проблему современных коммуникационных протоколов именно в их чрезмерно жесткой типизации. С одной стороны, приятно иметь компайл-тайм гарантию, что в коде не будет обращения к Address пользователя, полученного аналогом вышеуказанного запроса. С другой стороны, нет возможности, к примеру, разделить операторы фильтра и проекции. Для каждого возможного запроса мы вынуждены явно вводить новый тип результата. Ну либо изобретать членоудлинители типа проверки наличия заполнения значения конкретного свойства.

Одним из возможных выходов является отказ от явной типизации коммуникаций. Почему бы клиенту не использовать всё тот же SQL для общения с сервером приложений? Просто это будет несколько более другой SQL. Точнее, он будет работать не над настоящими table и view, а над бизнес-моделью. К слову, тот же LDAP, насколько я помню, работает примерно так (только язык запросов у них не SQL).

А вопрос компайл-тайм проверки решается средствами того, что и осуществляет этот компайл-тайм. Т.е. языка. См. DLinq в качестве примера. Метаданные о структуре запроса становятся известны компилятору, который может провести статическую валидацию запросов.

Имхо, это всё намного круче объектно-ориентированных транспортов, которые вынуждают к сексу с DTO на ровном месте. Если это не обладает ни identity, ни state, ни bahavior, то какого хрена мы называем это Object, пусть даже и Data Transfer?
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[48]: DTO внутри BusinessObject
От: GlebZ Россия  
Дата: 31.01.07 11:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот, кстати, из моего опыта многие архитекторы совершенно неверно оценивают вот эти перспективы изменений, и получают совершенно ублюдочные системы.

Аналогично.
Re[16]: DTO внутри BusinessObject
От: GlebZ Россия  
Дата: 31.01.07 14:27
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Гм. Позволю себе напомнить про SQL, как протокол передачи данных между клиентом и сервером.

S>Вся сила SQL — именно в том, что в него встроен автоматический вывод типов. Т.е. когда я делаю
S>
S>select FirstName, LastName from user
S>

S>я явно указываю, какие поля вернуть. Проблемы "пустое"/"непустое" просто не существует. Можно считать, что каждый запрос неявно вводит отдельный тип DTO. При вызове функции ошибиться невозможно.
Чудный пример. SQL — оперирует кортежами. Наборами типизированных данных. Можно сказать — SQL это генерация кортежей с помощью других кортежей. В некотором смысле — BE это некоторая эмуляция кортежа, но с одним, достаточно важным исключением. В BE мы можем абстрагироваться. Мы можем вызвать нужную процедуру имея только знания о типе BE и не зная внутренней структуры. И как ты указал, у нас есть часть гарантий компилятора в нахождении ошибок. Именно это важно и востребованно в сложной бизнес-логике. Во многом, именно это конфликтует с кортежами. В случае если бизнес-логика проста, то и выпендриваться не нужно. Значительно быстрее и надежнее реализовать через DataSet или другую систему кортежей. Если это сложная система над которой работает несколько человек, то Business Entity упрощает жизнь.

S>Я вижу проблему современных коммуникационных протоколов именно в их чрезмерно жесткой типизации.

+1

S>А вопрос компайл-тайм проверки решается средствами того, что и осуществляет этот компайл-тайм. Т.е. языка. См. DLinq в качестве примера. Метаданные о структуре запроса становятся известны компилятору, который может провести статическую валидацию запросов.

К сожалению, вывод типов для полноценного использования — недоделанный,

S>Имхо, это всё намного круче объектно-ориентированных транспортов, которые вынуждают к сексу с DTO на ровном месте. Если это не обладает ни identity, ни state, ни bahavior, то какого хрена мы называем это Object, пусть даже и Data Transfer?

Потому как identity, state у него есть. Behaviour — нет. Идентификация (по крайней мере у меня) происходит через идентфикатор. Иначе мы и не сможем послать его обратно. Состояние — он и есть состояние.

И вообще, есть протокол который делался именно для пересылки данных. Называется XML. Он самоописывающийся(можно просмотреть что там лежит). Он может быть полностью(xsd) или частично(anyType) типизирован. Он может трансформироваться (XQuery). Он сам по себе — набор кортежей, только не плоских как в RDBMS, а иерархических. У него только один единственный недостаток. Он плохо адаптирован в языки программирования.
Re[48]: Оффтоп о басне Крылова
От: akasoft Россия  
Дата: 31.01.07 17:31
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Да потому, что все эти семь слоев радуги оправдывают "возможностью перейти на другую СУБД с минимальными затратами". А эта возможность не нужна почти никогда. Зато желание "добавить колонку", которое возникает в среднем 20-25 раз в год, требует в 15 раз больше изменений, чем в старой доброй "однослойной" модели. Потому, что надо чинить все 7 слоев и 8 адаптеров между ними.


О! Это хорошая иллюстрация тупика в проекте Янус.

На мой взгляд, именно поддержка FireBird привела к тому, что разработчики, владеющие Access/SQL Express перестали развивать проект, потому что они не могут обеспечить преемственность с FB.

А отрубить FB — это отрубить часть пользователей, как-то работающих на нём.

Итого: лебедь, рак и щука....
... << RSDN@Home 1.2.0 alpha rev. 673>> SQL Express 2005
Re[17]: DTO внутри BusinessObject
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.02.07 03:48
Оценка: 6 (1)
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, Sinclair, Вы писали:

GZ>Чудный пример. SQL — оперирует кортежами. Наборами типизированных данных. Можно сказать — SQL это генерация кортежей с помощью других кортежей.
Совершенно верно. По сравнению с этим, автоматическое конструирование типов в С++ — детский лепет.
GZ>В некотором смысле — BE это некоторая эмуляция кортежа, но с одним, достаточно важным исключением. В BE мы можем абстрагироваться.
Абстрагироваться от чего?
Если в BE нет поведения, то она вообще ничем от кортежа не отличается.

GZ>Мы можем вызвать нужную процедуру имея только знания о типе BE и не зная внутренней структуры.

Ну, никакой внутренней структуры ты на самом деле не знаешь. Какие данные на какой странице, какие индексы есть, а каких нету — тебе этого не видно. Видно только, что есть user с такими-то полями.

GZ>И как ты указал, у нас есть часть гарантий компилятора в нахождении ошибок. Именно это важно и востребованно в сложной бизнес-логике. Во многом, именно это конфликтует с кортежами. В случае если бизнес-логика проста, то и выпендриваться не нужно. Значительно быстрее и надежнее реализовать через DataSet или другую систему кортежей. Если это сложная система над которой работает несколько человек, то Business Entity упрощает жизнь.

Я не против бизнес-логики. Просто как правило с клиента никакой особенной бизнес логики и нету. Выбирай себе список пользователей и всё. Сложности бизнес-логики в этом случае начинаются в предикатах. У нас например есть такой метод "вернуть всех моих пользователей" и есть "вернуть всех пользователей моих пользователей".
Это как раз то, о чем я говорил: нам приходится делать два разных метода. Захоти мы "сузить" в некоторых случаях пользовательские профили — оп-ля, методов уже четыре: GetIntermediateUsersPartial, GetIntermediateUsersFull, GetAllNestedUsersPartial, GetAllNestedUsersFull.
Ну так эта бизнес-логика запросто прячется "внутрь" почти так же, как сейчас!
Можно вообще закрыть всем, кроме админа, доступ к пользователям выше текущего.
Тогда непосредственных пользователей мы будем видеть так:
select * from MyUsers where owner=me


GZ>К сожалению, вывод типов для полноценного использования — недоделанный,

А что там недоделано?
GZ>Потому как identity, state у него есть. Behaviour — нет. Идентификация (по крайней мере у меня) происходит через идентфикатор. Иначе мы и не сможем послать его обратно. Состояние — он и есть состояние.
Ну ладно. В некоторых случаях identity у него есть. Во многих — нету. Как можно послать обратно результат group by или join ?

GZ>И вообще, есть протокол который делался именно для пересылки данных. Называется XML. Он самоописывающийся(можно просмотреть что там лежит). Он может быть полностью(xsd) или частично(anyType) типизирован. Он может трансформироваться (XQuery). Он сам по себе — набор кортежей, только не плоских как в RDBMS, а иерархических. У него только один единственный недостаток. Он плохо адаптирован в языки программирования.

Это не протокол. Это транспорт. Точно так же, как TDS. Протокол должен бы включать в себя некоторые соглашения; что-то типа языка запросов. Язык запросов SOAP (как и прочие строготипизированные штуки) мне не очень нравится. Его основное преимущество — невыносимая легкость биндинга к языкам программирования. Есть конечный набор правил, по которым мы сериализуем параметры метода и возвращаемые данные. В принципе, это всё — то же самое, что и дком/корба/RMI и т.п.
Теоретически можно было бы сделать и такую штуку: изобразить "серверную модель" в виде огромного всеобъемлючщего XML; от клиента едут XQuery-запросы, в ответ на которые приезжает соответствующее данные. Со всей гибкостью и всё такое. Я пока не уверен, что это намного лучше, чем старый добрый SQL.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: DTO внутри BusinessObject
От: GlebZ Россия  
Дата: 01.02.07 08:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

GZ>>Мы можем вызвать нужную процедуру имея только знания о типе BE и не зная внутренней структуры.

S>Ну, никакой внутренней структуры ты на самом деле не знаешь. Какие данные на какой странице, какие индексы есть, а каких нету — тебе этого не видно. Видно только, что есть user с такими-то полями.
В том-то и дело что не видишь что юзер. Кортеж — это набор типизированных полей. А тут нужен строгий тип.

S>Тогда непосредственных пользователей мы будем видеть так:

S>
S>select * from MyUsers where owner=me
S>

Есть другой вид бизнес-логики: послать задание для трех человек, которые при выполнении должны отчитаться четвертому, и после получения полного отчета — четветый должен сделать полный отчет по данному заданию и отослать лицам выдавшим задание. На такую бизнес-логику — SQL не навернешь. В остальном сущая правда.

S>Ну ладно. В некоторых случаях identity у него есть. Во многих — нету. Как можно послать обратно результат group by или join ?

Согласен.

S>Это не протокол. Это транспорт. Точно так же, как TDS. Протокол должен бы включать в себя некоторые соглашения; что-то типа языка запросов. Язык запросов SOAP (как и прочие строготипизированные штуки) мне не очень нравится. Его основное преимущество — невыносимая легкость биндинга к языкам программирования. Есть конечный набор правил, по которым мы сериализуем параметры метода и возвращаемые данные. В принципе, это всё — то же самое, что и дком/корба/RMI и т.п.

У него есть и другое преимущество. Оно может быть самоописано. И строготипизированность сделать дозируемой(те же anyType).

S>Теоретически можно было бы сделать и такую штуку: изобразить "серверную модель" в виде огромного всеобъемлючщего XML; от клиента едут XQuery-запросы, в ответ на которые приезжает соответствующее данные. Со всей гибкостью и всё такое. Я пока не уверен, что это намного лучше, чем старый добрый SQL.

У XQuery есть огромное преимущество. Это нормальный модульный функциональный язык с поддержкой рекурсии и т.д. Использовать его можно и как самостоятельную базу данных, и как прослойку к другому источнику RDBMS. К сожалению, по сравнению с современными функц. языками он беден. Все таки это язык предназначенный прежде трансформации запросов. Вот если бы на него накатить метапрограммирование да замыкания, да голову от Федот Федотыча — конкурентов не было бы.
Может самим написать?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[19]: DTO внутри BusinessObject
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.02.07 10:54
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Есть другой вид бизнес-логики: послать задание для трех человек, которые при выполнении должны отчитаться четвертому, и после получения полного отчета — четветый должен сделать полный отчет по данному заданию и отослать лицам выдавшим задание. На такую бизнес-логику — SQL не навернешь.
Ну так это же совсем-совсем другой тип бизнес логики!
Для него как раз жесткий протокол совершенно показан. Но этому протоколу нафиг не упали частичные объекты и вопросы их сериализации. Максимум, что может возвращать такой бизнес-метод — это список OperationResult.
GZ>У него есть и другое преимущество. Оно может быть самоописано. И строготипизированность сделать дозируемой(те же anyType).

GZ>Может самим написать?

1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: DTO внутри BusinessObject
От: GreatDrag Украина  
Дата: 07.02.07 00:33
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>1. За один вызов я должен вернуть/обработать объект состоящий из нескольких элементарных бизнес-объектов и снизить зависимость от латентности сети. Это наиболее частое использование DTO.
GZ>2. Скрытие некоторых не предназначенных для клиента данных. Эта тема уже поднималась на форумах. Не все данные бизнес-объектов должны быть доступны клиентам или должны быть доступны в режиме read-only. Усложняет архитектуру, и я бы не советовал использовать это без явных требований.
GZ>3. Структура используемая в сервере не может быть использована на клиенте. В основном такое встречается в statefull приложениях. Ну например, мне надо было сделать сложновычислимую задачу. Для того, чтобы вся эта шняга быстро вычислялась бизнес-объекты были связаны между собой прямыми указателями. Ессно, на клиенте бизнес-объекты должны быть связаны через идентификаторы. Это и обусловило разность типов на сервере и клиенте.
GZ>4. Кэширование. Размер полных бизнес-объектов был достаточно большой. Кэшировались только те части объекта которые наиболее часто используемы, а не полностью объект. Это сильно повысило эффективность кэша, но и обусловило построение управляемого DTO.
GZ>5. Независимость сервера. Достаточно редкая вещь. Было еще развивающееся решение когда внезапно поступило срочное требование интеграции чужого web-сервера. Решение также равивалось и по данным (то бишь по бизнес-объектам). Для того чтобы обеспечить независимость по данным был сделан слой DTO который отдавал данные в виде утвержденной сторонами XML.

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

Тут было сказано много абстрактных слов, и, судя по всему, каждый остался при своем мнении. В связи чем предлагаю следующее: рассмотреть не совсем тривиальный пример, как было раньше с UserObject-UserDTO-etc, а что-то более приближенное к условиям, описанным в посылке. К примеру, пусть ситуация описывается так:
  1. Имеется иерархическая структура с единственным корнем, хранящаяся в БД
  2. В каждом узле могут быть подузлы или листовые объекты. Будем считать, что детей у узла может быть много, потому получать по одному неэффективно (обеспечиваем условие 1 посылки)
  3. С некоторыми узлами связаны наборы прав. Отдача клиенту данных, которые ему не предназначены — понятно недопустима. Для пущей простоты будем считать, что новые данные нашим клиентом не вносятся и существующие не редактируются (обеспечиваем условие 2 посылки)
  4. Условие 3 посылки мне представляется не очень критичным, но, предположим, хранение прямых указателей есть желательным элементом системы. Другими словами, желательно чтобы BE реально представляли собой иерархию, а не просто хранили список ID дочерних объектов.
  5. Листовые объекты содержат некое большое поле (к примеру Description), передавать которое по сети для всех передаваемых объектов неэффективно. То есть нужно получать его только в тот момент, когда клиенту оно реально понадобится (обеспечиваем условие 4 посылки)
  6. Условие 5 довольно редко, и представляет мало практического интереса, как показала дискуссия. Если никто не возражает — плюнем на него
Стоит задача: построить трехуровневую архитектуру, отвечающую сформулированным критериям. Возможные запросы от клиента:
Конечно, на все запросы нужно выдавать только ту информацию, которая доступна текущему пользователю
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[22]: DTO внутри BusinessObject
От: снежок Россия  
Дата: 28.02.07 18:18
Оценка:
GZ>1. За один вызов я должен вернуть/обработать объект состоящий из нескольких элементарных бизнес-объектов и снизить зависимость от латентности сети. Это наиболее частое использование DTO.
Извините пожалуйста за то что я поднимаю эту ветку, но почему то так никто и не сказал что "вернуть/обработать объект состоящий из нескольких элементарных бизнес-объектов" — это чистейшей воды UnitOfWork (который не преобразует BO, а аггрегирует их), а не DTO.
Природа же DTO ближе именно к преобразованию переносимых данных.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[23]: DTO внутри BusinessObject
От: GlebZ Россия  
Дата: 01.03.07 06:09
Оценка:
Здравствуйте, снежок, Вы писали:

GZ>>1. За один вызов я должен вернуть/обработать объект состоящий из нескольких элементарных бизнес-объектов и снизить зависимость от латентности сети. Это наиболее частое использование DTO.

С>Извините пожалуйста за то что я поднимаю эту ветку, но почему то так никто и не сказал что "вернуть/обработать объект состоящий из нескольких элементарных бизнес-объектов" — это чистейшей воды UnitOfWork (который не преобразует BO, а аггрегирует их), а не DTO.
С>Природа же DTO ближе именно к преобразованию переносимых данных.
Причем тут UnitOfWork? UnitOfWork — это средство для согласования транзакции. К данной теме вообще никакого отношения не имеет.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[24]: DTO внутри BusinessObject
От: снежок Россия  
Дата: 01.03.07 07:02
Оценка:
GZ>Причем тут UnitOfWork? UnitOfWork — это средство для согласования транзакции. К данной теме вообще никакого отношения не имеет.
Да, правильно средство согласования, но не совсем . Если имеется несколько разнородных объектов создаваемых в рамках некоторого... пусть будет бизнес-процесса, они аггрегируются в UnitOfWork и UnitOfWork сохраняется в рамках одной системной системной транзакции.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[25]: DTO внутри BusinessObject
От: GlebZ Россия  
Дата: 01.03.07 07:52
Оценка:
Здравствуйте, снежок, Вы писали:

GZ>>Причем тут UnitOfWork? UnitOfWork — это средство для согласования транзакции. К данной теме вообще никакого отношения не имеет.

С>Да, правильно средство согласования, но не совсем . Если имеется несколько разнородных объектов создаваемых в рамках некоторого... пусть будет бизнес-процесса, они аггрегируются в UnitOfWork и UnitOfWork сохраняется в рамках одной системной системной транзакции.
UnitOfWork — кэширует объекты в течении одной системной транзакции. Но обычно, по крайней мере я, один и тот-же объект я стараюсь не заказывать несколько раз. И в данном пункте — получение разных объектов с помощью разных вызовов которые можно объединить в один вызов. Это одна из целей DTO. Непонятно причем тут Unit of Work.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.