Лучшие практики для синхронизации моделей и моделей представления - PullRequest
5 голосов
/ 05 февраля 2011

Я работаю над большим приложением Silverlight, которое использует дуплексный Net.TCP для связи с серверной частью WCF. Я нахожусь в процессе перевода этого приложения из подхода MVC в MVVM. Тем не менее, я борюсь с правильным способом реализации моих ViewModels. Мы используем сгенерированные WCF прокси для нашей модели, которая довольно сложна, включает в себя десятки классов, множество коллекций и различные отношения «многие ко многим». Например, пользователь может принадлежать ко многим комнатам, в комнате может быть много пользователей, у пользователя может быть много SharedFiles, и каждый SharedFile может использоваться совместно с любой комнатой, частью которой в данный момент является пользователь. Такого рода вещи.

Кроме того, поскольку мы используем WCF в дуплексном режиме, изменения в модели могут быть инициированы либо конечным пользователем, либо службой WCF на внутреннем сервере. Другими словами, модель, которую мы используем, на несколько порядков сложнее, чем типичная «Модель», которую вы видите в любой из различных книг / статей / блогов MVVM. И вот тут-то и возникает проблема, потому что поддерживать наш уровень ViewModel в синхронизации с нижележащим уровнем Model становится немного хлопотно.

Вот типичная проблема. Новый «Пользователь» присоединяется к «Комнате», поэтому службы WCF запускают уведомление «SessionAdded» всем остальным пользователям в комнате. Уведомление SessionAdded содержит объект Session, который имеет связанную Комнату и связанный объект User. Этот объект Room, который десериализовывается из службы WCF, в основном такой же, как объект Room на локальном клиенте, и, вероятно, содержит большинство тех же данных, но, конечно, не имеет всех одинаковых данных, и, по крайней мере, некоторые данные (например, нулевая коллекция досок), безусловно, неверны. Поэтому нам нужно как-то взять эти входящие данные и объединить их с нашей существующей моделью. И затем нам нужно создать ViewModel поверх каждого из новых объектов и / или обновить существующие ViewModel новыми объектами и / или их данными.

Прямо сейчас мы обрабатываем это, заставляя различные ViewModel реагировать на соответствующие события уведомления WCF и стараться исправить свои базовые модели и связанные модели представлений. Мы выяснили несколько хитростей, таких как SynchronizedObservableCollection (смутно похожий на here ), который отслеживает (скажем) Room.Sessions ObservableCollection и автоматически создает соответствующие SessionViewModels и помещает их в коллекцию RoomViewModel.SessionViewModels. Мы также используем ViewModelFactory, который кэширует модели представлений и гарантирует, что, скажем, SessionViewModel, который оборачивает данный сеанс, остается прежним, даже если базовый объект Session изменяется. (Если это имеет значение, мы используем подход, основанный на модели представления, так как большая часть того, что нам нужно, - это создание новых элементов пользовательского интерфейса в ответ на изменения в ViewModel, вызванные нашими уведомлениями WCF.)

И все это работает. В принципе. Большую часть времени. Ты знаешь. Но много кода нужно поддерживать, и легко ошибиться. Модульные тесты удобны, если вы помните, что должно произойти, но к тому времени, когда вы закончите обработку своего 20-го каскадного события CollectionChanged, будет трудно отследить, как все это сочетается и что вы тестировали в первую очередь. , Другими словами, все это чертовски хрупко.

Мне кажется, что это тот сценарий, с которым должно было столкнуться множество людей, и мне любопытно, как другие люди столкнулись с ним. Я могу придумать пару подходов, чтобы, возможно, сделать это лучше:

(1) Рассматривать модель на стороне клиента как своего рода базу данных, которая должна быть полностью согласованной, и реализовывать уровень доступа к данным на стороне клиента, задачей которого является поддержание согласованности модели. Все обновления модели, будь то от пользователя или сервера, должны проходить через этот уровень. Это было бы немного похоже на Entity Framework, в котором myRoom.Users.Add(myUser) автоматически установит myUser.Room = myRoom, и наоборот, и так далее. (Это особенно та часть, которую, кажется, кто-то где-то должен был уже разработать, хотя я еще не нашел ее.)

(2) Опирайтесь на что-то вроде Ферма или Obtics , чтобы синхронизировать все фрагменты. Не совсем уверен, как это будет работать, но теоретически это звучит так, как будто это возможно.

И ... что еще? Мне любопытно, какие шаблоны или структуры использовались для решения этой проблемы.

1 Ответ

3 голосов
/ 05 февраля 2011

Я понимаю вашу боль - в настоящее время я разрабатываю сложное приложение для визуализации данных с использованием шаблона MVVM. Один действительно важный вопрос, который нужно задать себе: «Увеличивает ли модель представления всюду, где вы ее используете?», Другими словами, есть ли места, в которых она просто перенаправляет свойства на вашем уровне модели вашему представлению?

Я часто нахожу, что есть области кода, как правило, на уровне детализации (например, свойства объекта Person, Age, Name, Forename), где модель представления фактически не добавляет никакого значения, хотя в более уровень курса, это добавляет ценность, структурируя представления / окна и т.д ...

Я склонен использовать адаптивный подход к MVVM, на верхнем уровне (Windows, панели, формы) у меня всегда есть модель представления, но если части модели представления настолько просты, что модель представления не добавляет ценности, я выставить их на вид напрямую. Кроме того, в некоторых случаях вам необходимо выставить модель непосредственно для просмотра для повышения производительности.

Наконец, если вы обнаружите, что вам нужно заново представить модель представления для решения сложной проблемы связывания, я написал о простом шаблоне mini-MVVM, в котором применяется модель локального представления:

http://www.scottlogic.co.uk/blog/colin/2009/08/the-mini-viewmodel-pattern/

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...