Выдвижение изменений данных по сравнению с изменениями данных в приложении - PullRequest
4 голосов
/ 29 октября 2010

Предположим, у вас есть приложение, состоящее из двух слоев:

  • A: слой данных, в котором хранятся все данные, загруженные из базы данных или из файла
  • B: Aслой, который отображает данные в удобном пользовательском интерфейсе, например, в графическом отчете

. Теперь данные изменяются в слое A. У нас есть 2 подхода, чтобы убедиться, что отчеты со слоя B корректно обновляются.

Первый подход - это PUSH-подход.Уровень A уведомляет уровень B через наблюдателей, чтобы уровень B мог обновлять свои отчеты.

У подхода PUSH есть несколько недостатков:

  • Если данные меняются несколько раз (например, во время загрузки илив алгоритмах, которые изменяют много данных), наблюдатели выполняются много раз.Эту проблему можно решить, введя своего рода буферизацию (не вызывайте наблюдателей, пока вы все еще изменяетесь), но это может быть очень сложно, и правильные буферизационные вызовы часто забываются.
  • Если изменяется большое количество данных,вызовы наблюдателя могут вызвать накладные расходы, которые неприемлемы в приложении.

Другой подход - подход PULL.Слой A просто запоминает, какие данные были изменены, и не отправляет никаких уведомлений (слой A помечен как грязный).После действия, которое было выполнено пользователем (может быть запуск алгоритма или загрузка файла или что-то еще), мы проверяем все наши компоненты пользовательского интерфейса и просим их обновить себя.В этом случае уровень B запрашивается для обновления.Сначала он проверит, не загрязнен ли какой-либо из его нижележащих слоев (слой A).Если это так, он получит изменения и обновится сам.Если слой А не был грязным, отчет знал, что он не имеет ничего общего.

Лучшее решение зависит от ситуации.В моей ситуации подход PUSH кажется намного лучше.

Ситуация становится намного сложнее, если у нас более двух слоев.Предположим, у нас есть следующие 4 слоя:

  • A: слой данных, в котором хранятся все данные, загруженные из базы данных или из файла
  • B: слой, который использует слой данных(уровень A), например, для фильтрации данных из A с использованием сложной функции фильтрации
  • C: уровень, который использует уровень B, например, для объединения данных из уровня B в более мелкие фрагменты информации
  • D: отчет, который интерпретирует результаты уровня C и представляет его в хорошем графическом виде для пользователя

В этом случае нажатие на изменения почти наверняка приведет к гораздо более высоким издержкам.

С другой стороны, для того, чтобы вытащить изменения, необходимо:

  • уровень D должен вызвать уровень C, чтобы спросить, является ли он грязным
  • уровень C должен вызвать уровень B дляспросить, является ли он грязным
  • слой B должен вызвать слой A, чтобы спросить, не загрязнен ли он

Если ничего не изменилось, количество вызовов, которые нужно выполнить, прежде чем вы узнаете, что на самом деле ничегобыл изменен, и вы не чAve, чтобы сделать что-нибудь довольно большое.Похоже, что производительность, которую мы пытаемся избежать, не используя PUSH, теперь возвращается к использованию в подходе PULL из-за множества вызовов, чтобы спросить, не является ли что-то грязным.

Существуют ли шаблоны, которые решают проблему?такая проблема в хорошем и высокопроизводительном (низком объеме) способе?

Ответы [ 2 ]

3 голосов
/ 29 октября 2010

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

Я запрашиваю два ваших утверждения:

Вы подразумеваете, что управление уведомлениями PUSH излишне сложно. Я ожидал бы, что во многих случаях у вас, как правило, есть мастер вычислений, который собирает данные и выполняет вычисления. Двигатель должен обязательно остановиться в какой-то момент, и в этот момент он может отправить событие «Готовность к новым данным», которое может содержать более подробную информацию о том, что изменилось.

Вы говорите, что сделать 4 межслойных вызова слишком дорого. На чем основано это? по сравнению с чем? Если вас беспокоит фактор множителя (10 экземпляров D), вызов (5 экземпляров C), вызов (2 экземпляра B), вызов (1 экземпляр), так что A получает 100 вызовов, тогда, конечно, мы оптимизируем? На каждом уровне может быть написано: «Если я звоню или слышу ответ недавно, звонить не нужно».

Если учесть преимущества масштабирования слоев, несколько дешевых запросов могут быть не чрезмерными.

0 голосов
/ 16 марта 2011

Нажмите через менеджер данных и сожмите изменения, которые происходят менее чем за n наносекунд.Диспетчер данных реализует публикацию-подписку.

Это означает, что производители данных зависят только от диспетчера данных, а потребители данных получают только данные.

(существует изменение зависимостей для потребителей.)

Это делает весь поток данных явным образом в вашем коде клея.Подписки могут быть настроены заранее, поэтому пользователям не нужно знать, как это работает.

Менеджер данных может использовать свой собственный поток для вызова уведомлений подписчиков, что позволяет аккуратно отделить производителей от потребителей.Вы можете легко сжимать изменения, потому что менеджер данных использует только 1 поток для уведомления, он может быть «уведомлен» через таймер, а когда он просыпается, он видит только последнее состояние.

...