Хобрук: Ваш путь к мастерству в программировании

Лучший способ поддерживать пользовательский интерфейс в актуальном состоянии?

Этот вопрос является уточнением моего вопроса "Различные способы наблюдения за изменениями данных".

У меня все еще есть много классов в моем приложении C++, которые часто обновляются (или могут быть обновлены) в сложных математических процедурах и сложных частях бизнес-логики.

Если я выберу подход «наблюдатель» и отправлю уведомления каждый раз, когда значение экземпляра изменяется, у меня есть 2 больших риска:

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

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

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

Опять же, бизнес-логика может выполняться из любого места в приложении, поэтому на практике нам, возможно, придется добавить дополнительный вызов (указывающий всем окнам, что они должны обновить себя) почти после каждого действия, выполняемого пользователем.

Оба подхода имеют схожие, но противоположные недостатки:

  • С подходом «наблюдатель» мы рискуем обновить пользовательский интерфейс слишком много раз.
  • С подходом «отметить-грязный» у нас есть риск вообще не обновлять пользовательский интерфейс.

Оба недостатка можно устранить, внедрив каждое действие приложения в дополнительную логику (для наблюдателей: отправка уведомлений о начале-конце, для отметок-грязных: отправка уведомлений об обновлении себя).

Обратите внимание, что в не оконных приложениях это, вероятно, не проблема. Вы могли бы, например. используйте подход пометки-грязности, и только если для какого-либо расчета нужны данные, может потребоваться дополнительная обработка в случае, если данные грязные (это своего рода подход к кэшированию).

Однако для оконных приложений нет сигнала о том, что пользователь «смотрит на ваш экран» и что окна следует обновить. Таким образом, нет действительно хорошего момента, когда вам нужно смотреть на грязные данные (хотя вы могли бы проделать некоторые трюки с событиями фокуса).

Какое хорошее решение для решения этой проблемы? И как вы решали подобные проблемы в своем приложении?

Обратите внимание, что я не хочу вводить оконные методы в часть расчета/модели данных моего приложения. Если для решения этой проблемы необходимы оконные методы, их следует использовать только в части пользовательского интерфейса моего приложения.

Любая идея?


  • Может ли наблюдатель просто установить событие или что-то, что пробуждает поток, ожидающий события. Именно этот поток затем берет на себя работу по уведомлению всех пользовательских интерфейсов. 08.09.2010

Ответы:


1

Подход, который я использовал несколько лет назад, был с большим приложением для Windows, заключался в использовании WM_KICKIDLE. Все вещи, которые можно обновлять, используют абстрактный базовый класс с именем IdleTarget. Затем IdleTargetManager перехватывает сообщения KICKIDLE и вызывает обновление списка зарегистрированных клиентов. В вашем случае вы можете создать список конкретных целей для обновления, но я нашел достаточно списка зарегистрированных клиентов.

Единственная проблема, с которой я столкнулся, была с графиком в реальном времени. Использование только сообщения о бездействии приведет к увеличению загрузки ЦП до 100% из-за постоянного обновления графика. Используйте таймер, чтобы заснуть, пока следующее обновление не решит эту проблему.

Если вам нужна дополнительная помощь - я доступен по разумным ценам... :-)

08.09.2010
  • Хорошая идея. Что хорошо в этом, так это то, что он четко отделяет часть бизнес-логики (которая вообще не знает о каком-либо пользовательском интерфейсе) от части пользовательского интерфейса. 08.09.2010

  • 2

    Еще один момент, о котором я подумал.

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

    • Выполнять работу
    • Совершить

    где уведомления отправляются только при фиксации.

    У него есть недостаток, заключающийся в том, что он заставляет переписывать некоторый код...

    08.09.2010

    3

    Вы можете использовать шаблон наблюдателя с объединением. Однако это может быть немного некрасиво для реализации на C++. Это будет выглядеть примерно так:

    m_observerList.beginCoalescing();
    m_observerList.notify();
    m_observerList.notify();
    m_observerList.notify();
    m_observerList.endCoalescing(); //observers are notified here, only once
    

    Таким образом, даже если вы вызываете notify три раза, наблюдатели фактически не уведомляются до endCoalescing, когда наблюдатели получают уведомление только один раз.

    08.09.2010
    Новые материалы

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

    Как я опубликовал свое первое приложение в App Store в 13 лет
    Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..

    Что в лицо
    Очерк о возвращении физиогномики и о том, почему мы должны это приветствовать. История начинается со странной науки. Р. Тора Бьорнсдоттир, Николас О. Рул. Видимость социального класса по..

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