Классическая трехзвенная архиектура:
Smart клиент на WPF
Application Server на .NET
SQL Server
Клиент и сервер общаются через WCF.
На сервере обычный ORM (LINQ to SQL). Удаленные вызовы обслуживаются RemoteFasade-ом.
Типовой метод для запросы данных с сервера
interface RemoteFasade
{
…
ClaimDTO GetOrder(int orderId);
…
}
Метод GetOrder возвращает на клиента граф связанных объектов. В методе GetOrder идет копирование данных из LINQ to SQL в TDO объекты, есть предположение, что для этого можно написать общие методы, принимающие лямбда выражения в качестве аргументов, т.е. такое ручное копирование с использованием общих методов.
Теперь о том, как данные будут приходить обратно от клиента к серверу. На клиенте есть некий ClientContext. После десериализации объектов на клиенте, для каждого DTO объекта текущий ClientContext подписывается на изменения в DTO объекте. Пользователь редактирует данные, изменения попадают в DTO объекты, а ClientContext регистрирует у себя все изменения. После того, как пользователь поработал с данными, изменения, зарегистрированные в ClientContext, отправляются на сервер. На сервере эти изменения попадают в объекты LINQ to SQL.
Замечание: Обычно паттерны Unit of work и Identity Map идут вместе. В данном случае ClientContext фактически реализует Unit of work на клиенте, но Identity Map вроде пока не нужна.
Re: Покритикуйте архитектуру обмена данными для smart клиент
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Метод GetOrder возвращает на клиента граф связанных объектов. В методе GetOrder идет копирование данных из LINQ to SQL в TDO объекты, есть предположение, что для этого можно написать общие методы, принимающие лямбда выражения в качестве аргументов, т.е. такое ручное копирование с использованием общих методов.
Да, такое представляется возможным для автоматизации, но это не самое узкое место.
AP>На клиенте есть некий ClientContext. После десериализации объектов на клиенте, для каждого DTO объекта текущий ClientContext подписывается на изменения в DTO объекте. Пользователь редактирует данные, изменения попадают в DTO объекты, а ClientContext регистрирует у себя все изменения. После того, как пользователь поработал с данными, изменения, зарегистрированные в ClientContext, отправляются на сервер. На сервере эти изменения попадают в объекты LINQ to SQL.
Здесь меня немного пугает обилие кода, связанным с поддержкой сообщений об изменении DTO объектов и довольно плотной подпиской на все сообщения ClientContext-ом. Накопление истории изменений и применение ее на сервере тоже может оказаться громоздким. Если кроме ClientContext-а, кому-то еще будут нужны сообщения об изменениях объектов, то это может окупиться. Если нет — могу предложить вариант, где ClaimDTO и граф объектов являются надстройкой над типизированным DataSet-ом. Если объекты будут хранить состояния в соответствующих DataRow объектах, то никакой подписки на изменения можно вообще не делать и вместо истории изменений на сервере разгребать изменения в переданном DataSet-е. При использовании LINQ to SQL, такой DataSet вообще не обязан повторять схему БД, может содержать любую избыточную информацию и служить буфером для изменений в ClaimDTO или в схеме БД.
Так же могу порекомендовать обратить внимание на "Entity Framework" и его возможность к транспортировке объектов отдельно от контекста с последующим сохранении изменений (здесь). В этом случае сами DTO объекты могут быть переданы на сервер в качестве изменений.
Re: Покритикуйте архитектуру обмена данными для smart клиент
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Классическая трехзвенная архиектура: AP>Smart клиент на WPF AP>Application Server на .NET AP>SQL Server AP>Клиент и сервер общаются через WCF.
AP>На сервере обычный ORM (LINQ to SQL). Удаленные вызовы обслуживаются RemoteFasade-ом.
AP>Типовой метод для запросы данных с сервера AP>interface RemoteFasade AP>{ AP>… AP>ClaimDTO GetOrder(int orderId); AP>… AP>} AP>Метод GetOrder возвращает на клиента граф связанных объектов. В методе GetOrder идет копирование данных из LINQ to SQL в TDO объекты, есть предположение, что для этого можно написать общие методы, принимающие лямбда выражения в качестве аргументов, т.е. такое ручное копирование с использованием общих методов.
AP>Теперь о том, как данные будут приходить обратно от клиента к серверу. На клиенте есть некий ClientContext. После десериализации объектов на клиенте, для каждого DTO объекта текущий ClientContext подписывается на изменения в DTO объекте. Пользователь редактирует данные, изменения попадают в DTO объекты, а ClientContext регистрирует у себя все изменения. После того, как пользователь поработал с данными, изменения, зарегистрированные в ClientContext, отправляются на сервер. На сервере эти изменения попадают в объекты LINQ to SQL.
AP>Замечание: Обычно паттерны Unit of work и Identity Map идут вместе. В данном случае ClientContext фактически реализует Unit of work на клиенте, но Identity Map вроде пока не нужна.
Я бы не советовал вам связываться с Unit of work и отсылкой изменений в DTO на сервер. Во-первых у вас происходит инфляция слоя Application server, он вырождается в голый ORM. Во-вторых, вас ждут большие сложности с синхронизацией клиентских и серверных контекстов, сохранением данных и обеспечением конкурентнго доступа. Когда-то мы пытались реализовать подобную архитектуру (правдв еще на FW 1.0 и remoting), но в итоге отказались от нее.
Вместо этого предлагаю вам подумать о развитии сервиса RemoteFacade. В нем желательно выделить сервисы данных, которые возвращают DTO для организации UI на клиенте и сервисы бизнес-операций. Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе.
Такой подход значительно облегчает как разработку серверной логики (тот же самый Unit of work), так и разработку клиента. Однако он не подходит, если вам необходимо обеспечить работу клиента offline.
Здравствуйте, stump, Вы писали:
S>Вместо этого предлагаю вам подумать о развитии сервиса RemoteFacade. В нем желательно выделить сервисы данных, которые возвращают DTO для организации UI на клиенте и сервисы бизнес-операций. Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе.
1) Remote доступ предполагает максимально маленькое кол-во обращений к RemoteFacade, а если Stump из RemoteFacade делать Service, то это просто капут.
И если клиенский код будет пару сотен раз вызывать AddOrderLine что бы создать один заказ, то такая система будет очень и очень долго работать.
2) Считаю что ни о какой инфляции слоя App Service речи не может быть, так как данный сервис как выполнял свои функции (валидация, добаввление и т.д.) так и выполняет.
Там было написано русским по белому...
Re[2]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, stump, Вы писали:
S>Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе.
Плохая идея. Потребуется распространение транзакции на клиента и куча связаных с этим неприятностей.
Sapienti sat!
Re[3]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, stump, Вы писали:
S>>Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе. C>Плохая идея. Потребуется распространение транзакции на клиента и куча связаных с этим неприятностей.
Никакого распространения транзакций. Одна бизнес операция — одна транзакция.
Здравствуйте, C...R...a...S...H, Вы писали:
CRA>Здравствуйте, stump, Вы писали:
S>>Вместо этого предлагаю вам подумать о развитии сервиса RemoteFacade. В нем желательно выделить сервисы данных, которые возвращают DTO для организации UI на клиенте и сервисы бизнес-операций. Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе. CRA>1) Remote доступ предполагает максимально маленькое кол-во обращений к RemoteFacade, а если Stump из RemoteFacade делать Service, то это просто капут. CRA>И если клиенский код будет пару сотен раз вызывать AddOrderLine что бы создать один заказ, то такая система будет очень и очень долго работать.
Это другой вопрос — вопрос гранулярности операций фасада. С одной строны чем более гранулярен сервис фасада тем он более универсален в использовании. С другой строны меннее гранулярные сервисы позволяют создавать более эффективный UI. Налицо противоречие и тут надо учитывать много факторов, и среди них удобство использования сервиса, его функциональная полнота и (в качестве главного ограничивающего фактора) стек технологий, используемый для удаленного взаимодействия.
Когда в одной из систем мы в качестве транспорта между клиентом и сервером заменили remoting на web сервисы, мы получили падение производительности в 100 раз. Потом был рефакторинг remote facade в строну большей грануляции и мы вернули производительность на исходный уровень.
CRA>2) Считаю что ни о какой инфляции слоя App Service речи не может быть, так как данный сервис как выполнял свои функции (валидация, добаввление и т.д.) так и выполняет.
Может. При таком подходе бизнес логика перетекает на клиента практически помимо воли разработчика Правда это замечают очень поздно.
Здравствуйте, stump, Вы писали:
S>Здравствуйте, C...R...a...S...H, Вы писали:
CRA>>2) Считаю что ни о какой инфляции слоя App Service речи не может быть, так как данный сервис как выполнял свои функции (валидация, добаввление и т.д.) так и выполняет. S>Может. При таком подходе бизнес логика перетекает на клиента практически помимо воли разработчика Правда это замечают очень поздно.
По сути то что предложил AP, от гранулярного RemoteFacade отличается лишь тем, что в первом случае гранулярностью управляет клиент, а во втором — гранулярность задана жестко дизайном RemoteFacade-а. Ни о каком переносе бизнес логики речи не было. То решение, что предложил я (в качестве основы DTO DataSet, либо набор оторванных объектов EntityFramework-а) в какой-то мере склоняет к бизнес логике на стороне клиента, но даже в этом случае будет не сложно держать бизнес логику на сервере.
Можно подход AP воспринимать как Facade над RemoteFacade-ом, где объектом передачи данных является большой граф объектов, который раскладывается на кучу бизнес операций над RemoteFacade-ом с возможностью выполнения их в рамках одной транзакции. Не вижу ничего плохого в этом подходе.
Конфликты состояний контекстов сервера и клиентов критичны не для всех задач. Местами даже не стоит вопрос о синхронизации состояний на клиентах. В частности, AP вообще ни чего не говорил о состоянии на сервере и синхронизации с клиентами. Быть может в этом случае инфляция AppService в DAL приемлема?
Re[5]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, samius, Вы писали:
S>Здравствуйте, stump, Вы писали:
S>>Здравствуйте, C...R...a...S...H, Вы писали:
CRA>>>2) Считаю что ни о какой инфляции слоя App Service речи не может быть, так как данный сервис как выполнял свои функции (валидация, добаввление и т.д.) так и выполняет. S>>Может. При таком подходе бизнес логика перетекает на клиента практически помимо воли разработчика Правда это замечают очень поздно.
S>По сути то что предложил AP, от гранулярного RemoteFacade отличается лишь тем, что в первом случае гранулярностью управляет клиент, а во втором — гранулярность задана жестко дизайном RemoteFacade-а. Ни о каком переносе бизнес логики речи не было. То решение, что предложил я (в качестве основы DTO DataSet, либо набор оторванных объектов EntityFramework-а) в какой-то мере склоняет к бизнес логике на стороне клиента, но даже в этом случае будет не сложно держать бизнес логику на сервере. S>Можно подход AP воспринимать как Facade над RemoteFacade-ом, где объектом передачи данных является большой граф объектов, который раскладывается на кучу бизнес операций над RemoteFacade-ом с возможностью выполнения их в рамках одной транзакции. Не вижу ничего плохого в этом подходе.
Большой граф объектов, говорите. Ну к примеру (с теми же ордерами) есить бизнес рулез который гласит что нельзя для одного клиента иметь более одного заказа в состоянии "не оплачен". Что у нас получается, пользователь долго формирует ордер на клиенте и потом после отправки на сервер всего графа получает фигу в виде сообщения об ошибке, либо мы тащим на клиента логику реализации этого рулеза.
S>Конфликты состояний контекстов сервера и клиентов критичны не для всех задач. Местами даже не стоит вопрос о синхронизации состояний на клиентах. В частности, AP вообще ни чего не говорил о состоянии на сервере и синхронизации с клиентами. Быть может в этом случае инфляция AppService в DAL приемлема?
В этом случае более приемлема не трех а двух уровневая архитектура. Впрочем верно то, что топикстартер ничего об этом не говорил
samius>>По сути то что предложил AP, от гранулярного RemoteFacade отличается лишь тем, что в первом случае гранулярностью управляет клиент, а во втором — гранулярность задана жестко дизайном RemoteFacade-а. Ни о каком переносе бизнес логики речи не было. То решение, что предложил я (в качестве основы DTO DataSet, либо набор оторванных объектов EntityFramework-а) в какой-то мере склоняет к бизнес логике на стороне клиента, но даже в этом случае будет не сложно держать бизнес логику на сервере. S>>Можно подход AP воспринимать как Facade над RemoteFacade-ом, где объектом передачи данных является большой граф объектов, который раскладывается на кучу бизнес операций над RemoteFacade-ом с возможностью выполнения их в рамках одной транзакции. Не вижу ничего плохого в этом подходе.
stump>Большой граф объектов, говорите. Ну к примеру (с теми же ордерами) есить бизнес рулез который гласит что нельзя для одного клиента иметь более одного заказа в состоянии "не оплачен". Что у нас получается, пользователь долго формирует ордер на клиенте и потом после отправки на сервер всего графа получает фигу в виде сообщения об ошибке, либо мы тащим на клиента логику реализации этого рулеза.
Гранулярность в этом случае регулируется клиентом! Если такая фига не устраивает заказчика, то в этом случае клиентский код может быть подправлен без изменений в серверном коде и интерфейса RemoteFacad-а.
Re[4]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, stump, Вы писали:
S>>>Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе. C>>Плохая идея. Потребуется распространение транзакции на клиента и куча связаных с этим неприятностей. S>Никакого распространения транзакций. Одна бизнес операция — одна транзакция.
А тогда будет следующая проблема:
1. Зовём CreateOrder. В отдельной транзакции.
2. Зовём AddOrderLine. В отдельной транзакции.
3. Зовём AddOrderLine. В отдельной транзакции.
4. Зовём AddOrderLine. В отдельной транзакции. Упс. Вылетел constraint violation.
5. Что делать?
6. Кто виноват?
Sapienti sat!
Re[5]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, stump, Вы писали:
S>>>>Для приведенного вами примера с заказами это могут быть сервис данных заказов, с операциями GetOrder, GetOrderList, и сервис операций заказов, с операциями CreateOrder, DeleteOrder, ChangeOrderState, AddOrderLine и т.д. Впрочем физически оба сервиса можно объединить в одном интерфейсе. C>>>Плохая идея. Потребуется распространение транзакции на клиента и куча связаных с этим неприятностей. S>>Никакого распространения транзакций. Одна бизнес операция — одна транзакция. C>А тогда будет следующая проблема: C>1. Зовём CreateOrder. В отдельной транзакции. C>2. Зовём AddOrderLine. В отдельной транзакции. C>3. Зовём AddOrderLine. В отдельной транзакции. C>4. Зовём AddOrderLine. В отдельной транзакции. Упс. Вылетел constraint violation. C>5. Что делать? C>6. Кто виноват?
Ничего не делать. Будет ордер с двумя позициями. AddOrderLine — это просто пример. Если бизнес логика не позволяет добавлять позиции в существующий ордер, то такого метода просто не будет в интерфейсе фасада.
Описанный сценарий вполне применим на практике. Например бизнес правила разрешают добавлять позиции в ордер только пока он не принят в обработку. Если между шагами 3 и 4 другой пользователь изменил состояние ордера мы получим constraint violation или concurent access exception.
Здравствуйте, stump, Вы писали:
S>Ничего не делать. Будет ордер с двумя позициями. AddOrderLine — это просто пример. Если бизнес логика не позволяет добавлять позиции в существующий ордер, то такого метода просто не будет в интерфейсе фасада.
Ничего не делать — нельзя. Скорее всего, придётся откатывать полусформированый заказ. То есть, руками нужно будет выполнять работу базы.
Опять же, полусформированые объекты (особенно оставленые без присмотра) могут портить отчёты и вносить всякие разные глюки.
Sapienti sat!
Re[7]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, stump, Вы писали:
S>>Ничего не делать. Будет ордер с двумя позициями. AddOrderLine — это просто пример. Если бизнес логика не позволяет добавлять позиции в существующий ордер, то такого метода просто не будет в интерфейсе фасада. C>Ничего не делать — нельзя. Скорее всего, придётся откатывать полусформированый заказ. То есть, руками нужно будет выполнять работу базы.
Кто сказал что он "полусформированый"? Я еще раз повторяю — если бизнес логика конкретной системы не позволяет этого делать, такого метода не будет в фасаде. Основной признак бизнес операции — ее транзакционность со всеми сопустствующими ACID характеристиками. И это прежде всего обозначает, что любая бизнес операция переводит систему из одного валидного состояния в другое валидное состояние.
Если вернутся к многострадальному методу AddOrderLine, то он, несомненно, должен оставить ордер в "сформированном" состоянии, т.е. расчитать НДС пересчитать скидки, тоталы, сабтоталы и т.д. и т.п.
Опять же вернемся к исходному вопросу, обновлять граф объектов на клиенте и затем отсылать их на сервер versus использовать DTO только для биндинга UI и вызывать бизнес методы фасада. Пользователь, добявляя позиции в заказ, хочет тут же видеть удержанные налоги, тоталы и субтоталы, а это все бизнес логика. И тут вам приходится либо гонять туда сюда весь граф DTO объектов после каждого добавления строки в заказ, либо тащить бизнес логику на клиента чтоб выполнять все пересчеты тут. Оба варианта проигрывают бизнес методам. Первый, потому что фактически повторяет его, но при этом не выделяет явного интерфейса. Второй, тем что размывает логику по слоям, если вам потребуется клиент WPF, Silverlight или Web Forms вам придется снова и снова переписывать эту логику.
Здравствуйте, stump, Вы писали:
S>Опять же вернемся к исходному вопросу, обновлять граф объектов на клиенте и затем отсылать их на сервер versus использовать DTO только для биндинга UI и вызывать бизнес методы фасада. Пользователь, добявляя позиции в заказ, хочет тут же видеть удержанные налоги, тоталы и субтоталы, а это все бизнес логика. И тут вам приходится либо гонять туда сюда весь граф DTO объектов после каждого добавления строки в заказ, либо тащить бизнес логику на клиента чтоб выполнять все пересчеты тут. S>Оба варианта проигрывают бизнес методам.
Вот тут я не понял. Это третий вариант, когда DTO вообще не используется? Если да, то не рискуем ли мы последовательностью обращений к RemoteFacade получить набор рассогласованных данных (например, для случая, когда на клиенте принимается решение и для принятия этого решения (например, человеком) требуется широкий контекст данных из разных сущностей).
Re[9]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, samius, Вы писали:
S>Здравствуйте, stump, Вы писали:
S>>Опять же вернемся к исходному вопросу, обновлять граф объектов на клиенте и затем отсылать их на сервер versus использовать DTO только для биндинга UI и вызывать бизнес методы фасада. Пользователь, добявляя позиции в заказ, хочет тут же видеть удержанные налоги, тоталы и субтоталы, а это все бизнес логика. И тут вам приходится либо гонять туда сюда весь граф DTO объектов после каждого добавления строки в заказ, либо тащить бизнес логику на клиента чтоб выполнять все пересчеты тут. S>>Оба варианта проигрывают бизнес методам. S>Вот тут я не понял. Это третий вариант, когда DTO вообще не используется? Если да, то не рискуем ли мы последовательностью обращений к RemoteFacade получить набор рассогласованных данных (например, для случая, когда на клиенте принимается решение и для принятия этого решения (например, человеком) требуется широкий контекст данных из разных сущностей).
Немного выше я говорил о сервисе данных, в задачу которого входит поставлять данные для UI. Естественно что он должен поставлять согласованные данные. Кроме того, для трех-уровневых архитектур характерна работа клиента в disconnected режиме (т.е. без поддержания постоянного соединения, типичный пример web клиент), в этом случае отображаемые данные через какое то время неизбежно устаревают и рассогласовываются. Так построены множество систем и в абсолютном большинстве из них это не является проблемой.
Я не совсем понял про "принятие решения", какое воздействие это оказывает на систему? Если решение выливаетя в вызов какого либо бизнес метода фасада, то любой из таких методов обязан валидировать входные параметры где сразу же всплывет факт рассогласования или устаревания данных. Тут нет никакой проблемы. Зайдите в любой интернет магазин, накидайте товаров в корзину, откройте корзину в двух окнах, в однм удалите товары, а в другом попытайтесь изменить количество в уже несуществующих позициях и посмотрите, что произойдет. Ничего страшного не произойдет.
Здравствуйте, stump, Вы писали:
stump>>>Опять же вернемся к исходному вопросу, обновлять граф объектов на клиенте и затем отсылать их на сервер versus использовать DTO только для биндинга UI и вызывать бизнес методы фасада. Пользователь, добявляя позиции в заказ, хочет тут же видеть удержанные налоги, тоталы и субтоталы, а это все бизнес логика. И тут вам приходится либо гонять туда сюда весь граф DTO объектов после каждого добавления строки в заказ, либо тащить бизнес логику на клиента чтоб выполнять все пересчеты тут. stump>>>Оба варианта проигрывают бизнес методам.
samius>>Вот тут я не понял. Это третий вариант, когда DTO вообще не используется? Если да, то не рискуем ли мы последовательностью обращений к RemoteFacade получить набор рассогласованных данных (например, для случая, когда на клиенте принимается решение и для принятия этого решения (например, человеком) требуется широкий контекст данных из разных сущностей).
stump>Немного выше я говорил о сервисе данных, в задачу которого входит поставлять данные для UI. Естественно что он должен поставлять согласованные данные.
Очевидно, что не только данные для UI требуют согласованности, а так же данные, которые принимают участие в бизнес операции. Но данные, полученные путем последовательных обращений к RemoteFacade-у не могут быть гарантированно согласованными. stump>Кроме того, для трех-уровневых архитектур характерна работа клиента в disconnected режиме (т.е. без поддержания постоянного соединения, типичный пример web клиент), в этом случае отображаемые данные через какое то время неизбежно устаревают и рассогласовываются. Так построены множество систем и в абсолютном большинстве из них это не является проблемой.
согласен stump>Я не совсем понял про "принятие решения", какое воздействие это оказывает на систему? Если решение выливаетя в вызов какого либо бизнес метода фасада, то любой из таких методов обязан валидировать входные параметры где сразу же всплывет факт рассогласования или устаревания данных. Тут нет никакой проблемы. Зайдите в любой интернет магазин, накидайте товаров в корзину, откройте корзину в двух окнах, в однм удалите товары, а в другом попытайтесь изменить количество в уже несуществующих позициях и посмотрите, что произойдет. Ничего страшного не произойдет.
Да, ничего страшного не должно произойти. Однако, всплывает сценарий, когда клиенту RemoteFacad-ом выданы рассогласованные данные. Не потому что сервис данных плохой, а потому, что между обращениями к нему система изменила свое состояние. При обращении клиента к бизнес методам сервера, могут быть поданы рассогласованные данные. Ничего серьезного не должно произойти, но фига будет показана пользователю не потому что пользователь слишком долго думал, а потому что сервис данных возвращает необходимые данные последовательно!
Предпочитаю лишний раз сгонять DTO такому поведению системы.
Re[11]: Покритикуйте архитектуру обмена данными для smart кл
Здравствуйте, samius, Вы писали:
S>Да, ничего страшного не должно произойти. Однако, всплывает сценарий, когда клиенту RemoteFacad-ом выданы рассогласованные данные. Не потому что сервис данных плохой, а потому, что между обращениями к нему система изменила свое состояние. При обращении клиента к бизнес методам сервера, могут быть поданы рассогласованные данные. Ничего серьезного не должно произойти, но фига будет показана пользователю не потому что пользователь слишком долго думал, а потому что сервис данных возвращает необходимые данные последовательно! S>Предпочитаю лишний раз сгонять DTO такому поведению системы.
По моему, эта проблема, что называется высосана из пальца. Если у вас есть сложный композитный UI вам придется делать насколько запросов и есть возможнсть получить "рассогласованные" данные. Там где это действительно критично применяют распределенные транзакции. Но в том то и дело, что распределенные транзакции на практике применяются очень редко, удовольствие дорогое и масштабируемость решений убивают начисто.
Другой вариант, сделать специальный "острозаточенный" интерфейс для каждого такого UI, который вернет вам все данные all-in-one.
samius>>Да, ничего страшного не должно произойти. Однако, всплывает сценарий, когда клиенту RemoteFacad-ом выданы рассогласованные данные. Не потому что сервис данных плохой, а потому, что между обращениями к нему система изменила свое состояние. При обращении клиента к бизнес методам сервера, могут быть поданы рассогласованные данные. Ничего серьезного не должно произойти, но фига будет показана пользователю не потому что пользователь слишком долго думал, а потому что сервис данных возвращает необходимые данные последовательно!
samius>>Предпочитаю лишний раз сгонять DTO такому поведению системы. stump>По моему, эта проблема, что называется высосана из пальца. Если у вас есть сложный композитный UI вам придется делать насколько запросов и есть возможнсть получить "рассогласованные" данные.
Дело не только в композитном UI. Вообще UI и бизнес операции связаны глубже, чем это может показаться. Например, для оформления покупки хорошо бы передать кроме идентификатора товара еще и цену, которая была показана пользователю. Если с момента запроса цена изменилась, то тогда бизнес логика на сервере сможет отреагировать и предупредить клиента об изменении цены. Это будет лучше, чем если со счета покупателя снимется сумма отличная от той, на которую рассчитывал покупатель (здесь может пахнуть скандалом). И если для магазинов, где цены меняются не каждый день, только по ночам и в полном дауне, это не критично, то для систем, где данные меняются несколько раз на дню эта проблема актуальна.
Таким образом, есть класс систем, где на проведение бизнес-операции влияет не только сигнал поданный с клиента "Хочу", но еще и некий контекст данных, известный клиенту. При том, что отчасти этот контекст формируется сервером, крайне желательно, чтобы данные вунтри контекста были согласованы. stump>Там где это действительно критично применяют распределенные транзакции. Но в том то и дело, что распределенные транзакции на практике применяются очень редко, удовольствие дорогое и масштабируемость решений убивают начисто.
Абсолютно согласен, что распределенные транзакции убивают масштабируемость, кроме того, не всегда доступны. stump>Другой вариант, сделать специальный "острозаточенный" интерфейс для каждого такого UI, который вернет вам все данные all-in-one.
Точно. all-in-one — это как раз половина DTO. All-in-one в одну сторону, + all-in-one в другую сторону уже почти DTO. Почти — потому что я уже не вижу четкой грани между r/o DTO и all-in-one-ом либо между r/w all-in-one-ом и обычным DTO.
Бывает, что часть контекста меняется на клиенте перед обращением к бизнес операции; бывает, что вся бизнес операция проводится на стороне клиента, сервер же только фиксирует ее.
Надуманно? Думаю, что нет. Опять таки, зависит от требований. Топикстартер пропал, ну да и ладно с ним, мне самому интересен любой опыт на эту тему.
Сам работаю над системой с ОООООООООООООгромным all-in-one в сторону клиента (если брать частями, то это даже дорого в плане производительности, счет идет на минуты) + солидное изменение на стороне клиента + в прогнозах валидация на AppServer-е, а пока просто фиксация изменений. В общем, соображения в пользу DTO.
Re[8]: Покритикуйте архитектуру обмена данными для smart кли
Здравствуйте, stump, Вы писали:
S>Если вернутся к многострадальному методу AddOrderLine, то он, несомненно, должен оставить ордер в "сформированном" состоянии, т.е. расчитать НДС пересчитать скидки, тоталы, сабтоталы и т.д. и т.п.
Ок. У нас сделана система, которая раз в 30 минут печатает на бумаге все outstanding orders и посылает их на почту. Пользователь добавляет первую строку, вторую, третюю. Тут врубается демон и отсылает полусформированый заказ. Упс.
Опять же, каждое добавление строки или другое изменение — это сетевой вызов. А это тормоза интерфейса, особенно если вызов идёт через Инет по медленным каналам. Ну и нагрузка на сервер, конечно.
Ещё другая деталь. Ладно, мы отослали AddOrderLine, и сервер пересчитал суммы, налоги и скидки. Но как эти изменения отобразить клиенту? Что он должен получить из метода AddOrderLine? Весь изменённый граф объектов или просто void?