Покритикуйте архитектуру обмена данными для smart клиента
Разве только
Smart клиент- ну, не очень мне нравиться это термин и прочие hype-овые слова
В чем smart-овость-то клиента ?
а что критиковать в стандартном решении ?тогда можно ссылку на описание стандартного решения
Разве только
--------------------------------------------------------------------------------
Smart клиент
ну вроде это устоявшийся термин для таких клиентов на платформе Microsoft (на Java он называется rich client). Как ты называешь такие клиенты?
тогда можно ссылку на описание стандартного решения
Хм, да вроде сейчас все так делают - общение с сервером через DTO, RemoteFacade и ORM.
В книжках про паттерны это есть точно, у Фаулера, например, но я думаю, вы про Фаулера знаете...
ну вроде это устоявшийся термин для таких клиентов на платформе Microsoft (на Java он называется rich client). Как ты называешь такие клиенты?
Да, про майкрософт знаю, что они так называют. Претензия к ним, а не к вам. С терминами вообще проблема - что Rich, что Fat, а что Smart - уже путаница получается. Отчасти потому, что начинает размываться граница между обычным Old Fat Clients и web-клиентами, Уже есть, например, термин Rich Internet Client (RIC) и Rich Internet Application (RIA которые иногда внешне почти и не отличаются от обычного десктоп-приложения. Термин Smart я и для Java встречал, кажется (вроде это как Rich Internet Client).
В общем, конечно, по контексту бывает более менее понятно, что имеется ввиду.
Хм, да вроде сейчас все так делают - общение с сервером через DTO, RemoteFacade и ORM.у Фаулера с клиента на сервер тоже идут DTO, у RemoteFacade-а для этого есть набор методов CreateOrder, UpdateOrder и т.д. У него не упоминает ClientContext. В описанном в первом посте подходе передача данных с сервера на клиента осуществляет ClientContext автоматически, без специализированных методов, через один метод RemoteFacade-а.
В книжках про паттерны это есть точно, у Фаулера, например, но я думаю, вы про Фаулера знаете...
После того, как пользователь поработал с данными, изменения, зарегистрированные в ClientContext, отправляются на сервер.
А как ClientContext отправляет данные на сервер? Не через RemoteFacade и DTO?
В описанном в первом посте подходе передача данных с сервера на клиента осуществляет ClientContext автоматически, без специализированных методов, через один метод RemoteFacade-а.
Это мне немного непонятно. Вы имели ввиду "ClientContext осуществляет передачу данных с клиента на сервер автоматически без специализированных методов, через один метод RemoteFacade-а" ? Нечто вроде удаленного DataBinding? Или как?
Это мне немного непонятно. Вы имели ввиду "ClientContext осуществляет передачу данных с клиента на сервер автоматически без специализированных методов, через один метод RemoteFacade-а" ? Нечто вроде удаленного DataBinding? Или как?это видится так: ClientContext накапливает изменения в виде ("тип объекта", "значения primary key", "имя свойства(поля)", "значение свойства"). После команды отправки на сервер эта структура отправляется на сервер и там распихивается по объктам LINQ to SQL.
P.S. значения primary key-я не будут меняться, хотя можно и такое поддержать
это видится так: ClientContext накапливает изменения в виде ("тип объекта", "значения primary key", "имя свойства(поля)", "значение свойства"). После команды отправки на сервер эта структура отправляется на сервер и там распихивается по объктам LINQ to SQL.То есть вы собираете абсолютно все изменения на клиенте и отправляете их на сервер одной булкой, вместо того чтобы вызывать на RemoteFacade update методы для каждого измененного объкта по отдельности? Типа один generic update-метод на все объекты. Хм, why not?
То есть вы собираете абсолютно все изменения на клиентеуточню: отправляются изменения зарегистрированные в данном ClientContext-е. Контекстов на клиенте может быть несколько. Контекст подписывается на изменения в DTO объектах при вызове метода RemoteFacade-а. Это может выглядить как-то так
OrderDTO orderDTO = clientContext.InvokeRemoteFacade(facade => facade.GetOrder(orderId
Или для удобства проделигировать методы RemoteFacade-а в ClientContext-е, но это уже детали имплиментации, там по ходу видно будет как лучше.
1) в вашей программе ясен _точный момент_ отправки модифицированных данных от клента на сервер? необходимо избежать частых ремоутных вызовов.
2) есть ли error-handling при неудачном implicit synchronization ? клиент в курсе, что этот магический механизм не сработал ?
3) корректна ли логика программы в случае, когда одну и ту же запись меняют два разных клиента ?
зы. имею вопросик чисто из любопытства. клиент работает непосредственно в DTO сущностями? или ему предоставляете другие бизнес-объекты? мне казалось, что DTO не очень удобны в использовании, а удобны лишь для ремоутного обмена информации.
1) в вашей программе ясен _точный момент_ отправки модифицированных данных от клента на сервер?кому ясен? Программист, да, должен четко осознавать, когда происходят удаленные вызовы. Для пользователя хочется сделать так: везде, где идет удаленный вызов писать сообщение "Loading..", а удаленный вызов делать в отдельном потоке.
необходимо избежать частых ремоутных вызовов.да, это известно.
2) есть ли error-handling при неудачном implicit synchronization ? клиент в курсе, что этот магический механизм не сработал ?
пока ничего специально не будем делать, удаленный метод, который передает изменения данных на сервер, кидает исключение, а далее общий механизм обработки исключений.
3) корректна ли логика программы в случае, когда одну и ту же запись меняют два разных клиента ?
На мой взгляд, это отдельная проблема, не связанная с удаленным клиентом. LINQtoSQL предлагает оптимистическую блокировку. Пессимистическую блокировку, блокировки с низкой степенью детализации (Coase Grained Lock и тому подобное, будем реализовывать на сервере поверх LINQtoSQL, если в этом будет необходимость. На механизм общения удаленного клиента и сервера, вроде, это никак не завязано.
зы. имею вопросик чисто из любопытства. клиент работает непосредственно в DTO сущностями? или ему предоставляете другие бизнес-объекты? мне казалось, что DTO не очень удобны в использовании, а удобны лишь для ремоутного обмена информации.
у нас этот вопрос пока тоже не решен. Пока мы не закрываем возможность использования TDO в качестве клиентский объектов.
DTO не очень удобны в использовании
чем не удобны?
клиент работает непосредственно в DTO сущностями? или ему предоставляете другие бизнес-объекты? мне казалось, что DTO не очень удобны в использовании, а удобны лишь для ремоутного обмена информации.А зачем клиенту работать с бизнес-объектами? Что вы подразумеваете здесь под бизнес-объектами и какая разница у вас между бизнес- и DTO-объектом? Возьмем Order: что у вас будет означать бизнес-объект Order, а что OrderDTO?
кому ясен? Программист, да, должен четко осознавать, когда происходят удаленные вызовы. Для пользователя хочется сделать так: везде, где идет удаленный вызов писать сообщение "Loading..", а удаленный вызов делать в отдельном потоке.У нас была не очень хорошая реализация данного механизма, потому что обмен данными для чтения и записи шёл по одному каналу. Это часто приводило к тому, что во время "Loading..." вызывались колбэки обновлений бизнес объектов. Программисты GUI за этим, конечно, не следили. В общем, чётко осознавать где и что происходит в event driven подходе бывает непросто.
На мой взгляд, это отдельная проблема, не связанная с удаленным клиентом. LINQtoSQL предлагает оптимистическую блокировку. Пессимистическую блокировку, блокировки с низкой степенью детализации (Coase Grained Lock и тому подобное, будем реализовывать на сервере поверх LINQtoSQL, если в этом будет необходимость. На механизм общения удаленного клиента и сервера, вроде, это никак не завязано.Но тут есть и другая проблема. Что если два клиента открыли один документ, оба его изменили, и потом сохраняют? Мне кажется, что это очень тяжёлая для решения ситуация. Особенно, если данные обрабатываются пакетами и требуется некоторая транзакционность действий. (В одном месте товар удалили, а в другом его добавили.)
3) корректна ли логика программы в случае, когда одну и ту же запись меняют два разных клиента ?
На мой взгляд, это отдельная проблема, не связанная с удаленным клиентом. LINQtoSQL предлагает оптимистическую блокировку. Пессимистическую блокировку, блокировки с низкой степенью детализации (Coase Grained Lock и тому подобное, будем реализовывать на сервере поверх LINQtoSQL, если в этом будет необходимость. На механизм общения удаленного клиента и сервера, вроде, это никак не завязано.
+1. К клиенту это отношения не имеет.
Пока мы не закрываем возможность использования TDO в качестве клиентский объектов.
На клиенте теоретически два типа объектов, хранящих данные. Один - это грубо говоря то, что пришло с сервера (DTO как раз оно) - тут типы из бизнес-логики. А другой - это то, что вводит пользователь, и тут типы данных те, которые зашиты в визуальные компоненты. В этом случае одна из задач клиента - преобразование из одного типа в другой и обратно. Можно, конечно, данные с визуальных компонентов посылать сразу на сервер и преобразовывать там, но ничего хорошего в этом нету, потому что тогда сервер должен знать, на какой платформе реализован клиент. Грубо говоря, RemoteFacade'ы становятся зависимыми от типов данных клиента.
Но тут есть и другая проблема. Что если два клиента открыли один документ, оба его изменили, и потом сохраняют?За такими конфликтами следит либо LINQtoSQL (его может быть недостаточно либо дополнительная система управления конкурентным доступом. Система поддержки удаленного клиента действует поверх этого всего, она просто накапливает изменения на клиенте и скопом передает их, затем применяет эти изменения к серверным объектам.
За такими конфликтами следит либо LINQtoSQL (его может быть недостаточно либо дополнительная система управления конкурентным доступом. Система поддержки удаленного клиента действует поверх этого всего, она просто накапливает изменения на клиенте и скопом передает их, затем применяет эти изменения к серверным объектам.Это всё красиво звучит, но надо обязательно продумать, что при этом увидят два пользователя, если оба отредактируют один документ и сохранят его. Сложность всегда в таких мелочах, а не в том, как обеспечить целостность объекта с точки зрения программы.
Оставить комментарий
6yrop
Классическая трехзвенная архиектура:Smart клиент на WPF
Application Server на .NET
SQL Server
Клиент и сервер общаются через WCF.
На сервере обычный ORM (LINQ to SQL). Удаленные вызовы обслуживаются RemoteFasade-ом.
Типовой метод для запросов данных с сервера
interface RemoteFasade
{
…
ClaimDTO GetOrder(int orderId);
…
}
Метод GetOrder возвращает на клиента граф связанных объектов. В методе GetOrder идет копирование данных из LINQ to SQL в DTO объекты, есть предположение, что для этого можно написать общие методы, принимающие лямбда выражения в качестве аргументов, т.е. такое ручное копирование с использованием общих методов.
Теперь о том, как данные будут приходить обратно от клиента к серверу. На клиенте есть некий ClientContext. После десериализации объектов на клиенте, для каждого DTO объекта ClientContext подписывается на изменения в DTO объекте. Пользователь редактирует данные, изменения попадают в DTO объекты, а ClientContext регистрирует у себя все изменения. После того, как пользователь поработал с данными, изменения, зарегистрированные в ClientContext, отправляются на сервер. На сервере эти изменения попадают в объекты LINQ to SQL.
Замечание: Обычно паттерны Unit of work и Identity Map идут вместе. В данном случае ClientContext фактически реализует Unit of work на клиенте, но Identity Map вроде пока не нужна.