Здравствуйте, Polosatiy, Вы писали:
P>Здравствуйте!
P>Есть обычная задача. БД, Сервер, Клиент (клиент толстый, Swing-овый и некий набор сторонних систем для интеграции.
Счас вам набегут и будут говорить, что вы все сделали неправильно, а правильно -- вобще перейти на .net и юзать DynamicData и Entity Framework Это был оффтоп, а по теме -- такое ощущение, что у вас DTO ради DTO. Нужно избегать этого -- срезы для модели (DTOшки) в вашей архитектуре, по идее, нужны чтобы: а) изолировать клиента от модели сервера (если актуально) б) отвязаться от серверных библиотек (валидации, аудит) в)не тянуть полбазы в память (если актуально).
Если вы заранее знаете, что не все из перечисленного вам надо, то материализованные объекты, вероятно, спасут отца русской демократии и помогут уменьшить число DTO.
Есть обычная задача. БД, Сервер, Клиент (клиент толстый, Swing-овый и некий набор сторонних систем для интеграции.
И конечно же по всем рекомендациям различных архитекторов было оно реализовано так:
— Сервер имеет доменную модель и кучу сервисов для работы с этой моделью, которые выставлены наружу во все стороны.
— Клиент имеет некую солянку из объектов, которую с натяжкой можно назвать доменной моделью. Эта солянка состоит из кучи объектов, каждый из которых фактически является срезом какого-то объекта доменной модели, в основном по количеству параметров. Глубина среза зависит от того, какие данные из модели надо отображать на конкретной форме.
Пример:
— На сервере есть класс доменной модели "User". У него есть куча полей типа имя, логин, пароль. адрес, настройки и т.п.
— На клиенте есть форма, которая позволяет изменить, например, личную инфу по юзеру (имя, логин и пароль). Для этого на клиенте создается объект, который содержит эти 3 поля. Назовем его ClientUser. По сути, умным словом он называется DTO.
— Клиент запрашивает данные типа "дай-ка мне юзера" и отдает объект ClientUser. Сервак достает нужный объект модели и потом незатейливым конвертером конвертит его в ClientUser и отдает клиенту.
— Клиент получает объект и оборачивает его в другой (создает декоратор). Декоратор этот нужен для того, чтобы на сервак не попадали клиентские либы, связанные с валидацией и прочей мутью. Просто используемая либа имеет плохое свойство вклиниваться в объект и заставлять его делать extends SomeSuperObject чтоб она могла работать.
Далее всё это интегрируется в работу клиентского приложения.
Так вот, что меня интересует. Почему бы в этом случае вообще не отказаться от всяких DTO и декораторов? ИМХО, они похожи на большую свалку, которая только и делает что таскает данные от клиента серверу, захламляет проект и вынуждает писать кучу конвертеров, что приводит к появлению ошибок. Так как каждый объект клиента является срезом модели сервера, почему бы просто не юзать одну модель как на сервере, так и на клиенте?
Что соб-сно не нравится в распределенной модели:
1. Придется допилить конвертер так, чтобы он частично инициализировал объекты доменной модели. Только те данные, которые нужно. С тем конвертером что щас это будет выглядеть как конвертация объекта User в объект User, но только с определенными правилами среза, т.е. я буду указывать какие поля брать, а какие нет.
2. Появится некоторая недосказанность по поводу того, какие поля у User можно юзать "здесь", а какие "там". Недосказанность эта будет указываться в конвертере что тоже не есть гуд как мне кажется.
Во всех азбуках проектирования написано, что мол не таскайте доменную модель на клиента, так как структура модели клиента может отличаться от структуры доменной модели. Но в скольких случаях такое бывает? По-моему не больше чем в 2%, если только это не интеграция с какой-нить специальной системой.
Хочется преобразовать это всё к виду "одна распределенная модель данных как для клиента, так и для сервера" и поэтому и интересуюсь у вас что вы думаете по этому поводу и какие могут быть ещё подводные камни при таком подходе. Напрашивается какое-то подобие Hibernate, только для работы с сервером.
какая же каша, простите у Вас в голове ...
зачем ClientUser, конверторы ... в данном случае User просто содержит данные, все эти заморочки нужны если на основе данных с клиента строится сложный объект(т.е. нужны вычисления, алгоритмы, проверки и т.п.) ... тем более если у вас сервер и клиент на джаве то используйте везде User, ну будет у вас на клиенте например UsersModel(List<User>) ....
Здравствуйте, Stormblast, Вы писали:
S>Здравствуйте, Polosatiy
S>какая же каша, простите у Вас в голове ... S>зачем ClientUser, конверторы ... в данном случае User просто содержит данные, все эти заморочки нужны если на основе данных с клиента строится сложный объект(т.е. нужны вычисления, алгоритмы, проверки и т.п.) ... тем более если у вас сервер и клиент на джаве то используйте везде User, ну будет у вас на клиенте например UsersModel(List<User>) ....
Вы себе не представляете ту кашу, которая пытается это всё разрулить.
Что за UsersModel(List<User>)? Извините, не понял.
В этом случае полюбому придется срезать данные у User, чтобы избежать overhead-а и образования второй БД в памяти (ибо Hibernate). Щас он как раз за счет ClientUser и ему подобных срезается.
Здравствуйте, meowth, Вы писали:
M>Здравствуйте, Polosatiy, Вы писали:
P>>Здравствуйте!
P>>Есть обычная задача. БД, Сервер, Клиент (клиент толстый, Swing-овый и некий набор сторонних систем для интеграции.
M>Счас вам набегут и будут говорить, что вы все сделали неправильно, а правильно -- вобще перейти на .net и юзать DynamicData и Entity Framework Это был оффтоп, а по теме -- такое ощущение, что у вас DTO ради DTO. Нужно избегать этого -- срезы для модели (DTOшки) в вашей архитектуре, по идее, нужны чтобы: а) изолировать клиента от модели сервера (если актуально) б) отвязаться от серверных библиотек (валидации, аудит) в)не тянуть полбазы в память (если актуально).
M>Если вы заранее знаете, что не все из перечисленного вам надо, то материализованные объекты, вероятно, спасут отца русской демократии и помогут уменьшить число DTO.
Именно так. Пункт "а" не особо актуален, а вот остальные два точно ибо неохота тащить на клиента либы JPA. DTO в основном отрезают ненужную инфу, чтоб клиент по OutOfMemory не рухнул.
Здравствуйте, Polosatiy, Вы писали:
P>Хочется преобразовать это всё к виду "одна распределенная модель данных как для клиента, так и для сервера" и поэтому и интересуюсь у вас что вы думаете по этому поводу и какие могут быть ещё подводные камни при таком подходе. Напрашивается какое-то подобие Hibernate, только для работы с сервером.
Во-первых стоит почитать топики вроде этого: http://rsdn.ru/forum/design/3145651.aspx
Там много объяснений почему желаемого так трудно добится с ORM вообще. Одно из решений это минимизировать связи между объектами, несмотря на их наличие в БД.
Высказывались на этом форуме и другие мысли. Например строиьт иерархию наследования в зависимости от нужд клиента. Например
UserCredentials->User->UserDetails. Каждый наследник добавляет свойств сущности. ORM с его ленивой загрузкой работает с самой детализированой сущностью. Клиент и Клиент-Серверный транспорт работают только с той сущностью, которая нужна. Таким образом можно избежать null при использовании детализированых классов на клиенте. Другое дело что наследование не решит случаи когда в разных ситуациях нужны совершенно разнообразные наборы свойств, и разрулить эти наборы через наследование не выйдет. Но в таких случаях, вероятно, стоит делать декомпозицию.
Ещё одна выжная мысль, которая постоянно тут высказывается заключается в том что используемый нами инструментарий жестко диктует дизайн. И даже если в теории мы знаем более хороший подход, то наш ORM или сериализатор транспортного протокола банально с ним не справится.
P>Так вот, что меня интересует. Почему бы в этом случае вообще не отказаться от всяких DTO и декораторов? ИМХО, они похожи на большую свалку, которая только и делает что таскает данные от клиента серверу, захламляет проект и вынуждает писать кучу конвертеров, что приводит к появлению ошибок. Так как каждый объект клиента является срезом модели сервера, почему бы просто не юзать одну модель как на сервере, так и на клиенте?
1. В дотНет есть есть АвтоМаппер, возможно в джаве есть что-то подобное. Коротко, коперит данные меджу двумя обьектами использую рефлексию. Если нема то есть кодогенерация. Руками коперить это слегка устарело.
2. В зависимости от технологии интерфейса ДТО можно заменить на беги пропертей. Мы это очень сильно юзаем в GWT. Опять же, если интерфейс не более чем декларация то зачем типизированные ДТОшки?
3. Обьеденяя серверный и клиентский код вы тем самым делаете просто нереальный коплинг. Получаеться что любое изменение на сервере кртитично должно быть потдержано в клиенте. Я бы предпочел этого не делать. Например у нас час от часу появляються левые клиенты.
P>Что соб-сно не нравится в распределенной модели:
P>1. Придется допилить конвертер так, чтобы он частично инициализировал объекты доменной модели. Только те данные, которые нужно. С тем конвертером что щас это будет выглядеть как конвертация объекта User в объект User, но только с определенными правилами среза, т.е. я буду указывать какие поля брать, а какие нет.
У вас усложнить контрактный код. Так например метод может ожедать что у обьекта юзер заполнено поле возраст. А после "среза" этого не оказалось...
P>2. Появится некоторая недосказанность по поводу того, какие поля у User можно юзать "здесь", а какие "там". Недосказанность эта будет указываться в конвертере что тоже не есть гуд как мне кажется.
Не гуд. Это нига не потдерживаемое. Я обычно через пару недель не помню что натворил. Подумайте о людях которые будут саортить код через пару лет.
P>Во всех азбуках проектирования написано, что мол не таскайте доменную модель на клиента, так как структура модели клиента может отличаться от структуры доменной модели. Но в скольких случаях такое бывает? По-моему не больше чем в 2%, если только это не интеграция с какой-нить специальной системой.
Это пока один клиент. Одна версия клиента. Потом (если наступит) будет не 2% ...
Здравствуйте, Polosatiy, Вы писали:
P>Здравствуйте!
P><skipped>
Вот только что прочитал статью по этой теме в свежеприсланном мне MSDN Magazine. Хоть она и про .NET, думаю, вам будет полезно её прочесть, ибо обсуждается там скорее концепция DTO в целом: http://msdn.microsoft.com/en-ca/magazine/ee236638.aspx