4

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

class Object { 
    UI * ui; 
}; 


class UI { 
    Object * object; 
}; 

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

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

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

Так что мне было интересно, есть ли какой-либо шаблон дизайна для отправки уведомлений между развязанными слоями с меньшими накладными расходами?

Прояснение: большинство изменений выполняется на стороне пользовательского интерфейса, элементы пользовательского интерфейса содержат указатель на связанный объект, так что это не проблема. Но некоторые изменения, внесенные в некоторые объекты со стороны интерфейса, приводят к изменениям, которые происходят в связанных объектах в слое данных, которые невозможно предсказать, чтобы запросить обновление пользовательских интерфейсов объекта. Фактически одно изменение пользовательского интерфейса, сделанного для одного объекта, может привести к каскаду изменений для других объектов, поэтому мне нужно иметь возможность уведомлять их возможные представления пользовательского интерфейса для обновления, чтобы отразить эти изменения.

+0

@FabioCeconello - нет, это идея, 'Object' не должно быть связано с UI на всех.Создание пользовательских интерфейсов происходит только на стороне пользовательского интерфейса, по умолчанию создается только пользовательский интерфейс для корневого объекта, и оттуда пользователь может развернуть и свернуть разные ветви. – dtech

+0

Похоже, что фактическая проблема связана с эффективностью регистрации/отмены регистрации UI * производительности *, а не с фактическим дизайном. Вы могли бы ускорить процесс, сохранив массив или коллекцию элементов пользовательского интерфейса, которые соответствуют объекту модели (может быть применим * составной шаблон *), но он может не полностью удовлетворить требование, которое объекты не должны знать об их интерфейсе. – dasblinkenlight

+0

@ dasblinkenlight - это моя дилемма. Пытаясь понять, как и торт, и съесть его тоже. Наличие массива пользовательских интерфейсов для каждого объекта звучит как прямое решение, но оно загрязняет объектную модель и вводит еще больший объем памяти - массив имеет не только указатель, но и размер и емкость. 12 дополнительных байтов на объект без какого-либо пользовательского интерфейса составляют 1 гигабайт памяти в типичном сценарии объекта размером 100 мил на 32-битной платформе, уже 1/3 адресной памяти. Я бы скорее сохранил данные пользовательского интерфейса только для объектов, которые на самом деле имеют его. – dtech

ответ

0

Мне удалось создать чрезвычайно эффективное решение.

Вместо отслеживания всех пользовательских интерфейсов с использованием «реестра UI» я создал объект Proxy и заменил реестр UI реестром прокси.

Объект Proxy создан для каждого объекта, который имеет любое визуальное представление. Он сам расширяет QObject и реализует интерфейс для доступа к свойствам базового Object, обертывая их в свойствах стиля Qt.

Затем Proxy объект используется как свойство для каждого UI читать и писать основные Object свойства, поэтому она работает «автоматически» для каждого интерфейса, который может быть ссылающегося на конкретный прокси.

Это означает, что нет необходимости отслеживать каждый конкретный UI для каждого Object, а время жизни Proxy управляется просто путем подсчета числа UIs которых ссылки на нее.

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

Короче говоря, подвести итог улучшений по сравнению с предыдущей конструкцией:

  • реестра теперь гораздо меньше, от того, чтобы хранить указатель на сам объект и вектор все связанные с ним UIs я сейчас до 8 байт для Proxy - указатель на объект и счетчик для любого числа связанных с ними уведомлений UIs

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

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

  • вещей, которые мне раньше приходилось управлять вручную, как фактические уведомлений и объекты, ответственность за них теперь управляется автоматически

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

Это как торт и съесть его тоже :)

1

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

Это похоже на реестр UI, который вы уже пробовали. Основное различие заключается в том, что компоненты пользовательского интерфейса для обновления идентифицируются не только по их ссылочным Object s, а скорее по типу уведомления.

Это позволяет компромисс между специфичностью и государственным учетом: если модель настроена таким образом, что каждый компонент пользовательского интерфейса, связанный с Objectobj получает уведомление каждого обновление obj, то это эквивалентно реестру UI. С другой стороны, модель может быть организована так, что некоторые компоненты пользовательского интерфейса уведомляются всякий раз, когда какая-либо подкатегория Object публикует обновление, а затем каждый компонент может проверить сам, если ему необходимо изменить его состояние на основе содержимого уведомление. Доведенный до крайности, каждый объект пользовательского интерфейса может быть уведомлен любым сообщением, отправленным любым Object, что будет эквивалентно глобальному подходу «update-UI-state».

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

 Смежные вопросы

  • Нет связанных вопросов^_^