Я разрабатываю кросс-платформенную модель данных C ++ с почти 1000 различными типами элементов данных (но < 100 различных структур данных / классов). Чтобы обработать сообщения Модель-Контроллер (то есть уведомление для Контроллера о том, что какой-то элемент данных изменился), я думаю об использовании boost: signal2. Я думаю, что это поможет создать единый шаблон Observer, который остается одинаковым для разных платформ ОС. Первоначальная реализация выполняется в Mac OS / IOS, а последующий пользовательский интерфейс разработан для .net и unix.
Вопросы:
1) Чтобы настроить наблюдение за моделью данных, какой тип объекта должен подключать контроллер к объекту / слоту signal2? Должны ли присутствовать определенные функции / методы / селекторы в элементе данных контроллера для КАЖДОГО? Должны ли эти функции быть функциями C, C ++ или Objective-C / C ++?
2) Какой уровень детализации должен иметь сигнал? Должен ли каждый элемент данных иметь свой собственный? Или управление моделью связанных структур / записей должно поддерживать единый сигнал для каждого типа структуры / записи? Например — должны ли настройки приложения иметь ОДИН сигнал для всех данных предпочтений — передача информации о том, какой элемент данных был изменен?
3) Должен ли процесс отправки сигналов (или слотов, принимающих сигналы) выполняться в ОТДЕЛЬНОЙ РЕЗЬБЕ?
4) Я понимаю, что у Какао есть своя собственная система наблюдения значения ключа. Но будет ли такая система выгодной для СОЕДИНЕНИЯ с парадигмой Observer, основанной на сигналах модели2, или просто избыточной?
ОБНОВИТЬ:
Что касается «гранулярности» реальных объектов signal2 (не наблюдателей), я думаю, что начинать нужно с одного на документ и одного для префиксов приложения. Мои данные документа уже имеют концепцию «ключа», поэтому возможно обобщение общих случаев пользовательского интерфейса, когда компонент пользовательского интерфейса привязан к конкретному элементу данных модели.
У этого вопроса довольно много аспектов, поэтому я буду решать, что могу.
Почему мы хотим иметь возможность наблюдать что-то в Objective-C и .NET?
Я думаю, что поучительно думать о Зачем мы хотели бы наблюдать модель данных на языке 4-го поколения? Помимо развязки подсистем, в некоторых случаях мы также можем привязывать элементы интерфейса пользовательского интерфейса непосредственно к модели данных, избегая необходимости писать большой объем кода в контроллерах. Это возможно в приложении WPF, построенном на .NET, и в AppKit на MacOSX. Есть меньше возможностей в UIKit на iOS.
Мета-модель
Первая очевидная вещь, на которую следует обратить внимание, состоит в том, что два языка времени выполнения, на которые вы хотите ориентироваться (Objective-C и .NET), обеспечивают реализации на уровне языка шаблона наблюдателя, построенного вокруг объекта. свойства. Если вы хотите интегрировать их без написания тысяч строк кода, вы тоже захотите это сделать.
Это настоятельно говорит о том, что все ваши классы моделей C ++ должны наследоваться от метамодели, которая предоставляет механизм универсальных свойств. Завершится этим механизм наблюдения за ними.
Альтернативой будет создание огромного количества установщиков / получателей шаблонов в C ++ и связывание объектов для их использования в .NET и Objective-C.
адаптеры
Как для .NET, так и для Objective-C вы должны разработать общий класс адаптера, который использует отражение для выполнения своей грязной работы. В случае Objective-C вы делаете это путем переопределения методов в NSObject
пересылать наборы свойств / получать сообщения в механизм свойств базовой модели. Я верю, что в .NET вы можете использовать отражение, чтобы добавить свойства, соответствующие свойствам вашей модели, в адаптеры.
[В сторону] IDL / ORM
Конечно, к тому моменту, когда у вас есть модель данных, построенная поверх метамодели, вы могли бы также использовать какой-нибудь IDL или ORM для описания и автоматической генерации очень большого числа классов моделей? Огромное количество классов, с которыми вы имеете дело, также предлагают это.
Зернистость наблюдателей
С точки зрения детализации, вы можете сделать и то, и другое — это действительно зависит от того, каким образом ваша модель данных изменяется, и пользовательский интерфейс должен реагировать на это. KVO в Objective-C разработан для изменения именованных свойств объекта, но ограничен тем, что наблюдатель имеет один метод делегата для всех объектов и свойств, которые он наблюдает. Это, однако, только проблема для ваших компонентов пользовательского интерфейса Objective C.
Интеграция с этим определенно стоит того, если вы не хотите писать массу методов адаптера для событий с измененным значением, которые соединяют C ++ и Objective C: Помните, что, хотя между C ++ и Objective-C ++ существует бесплатное взаимодействие, классы Objective-C ++ могут ‘ • Наследуя интерфейсы классов C ++, вы не можете отправить сообщение объекту C из C ++ напрямую, без моста и некоторого неприятного приведения в модуле компиляции target-C ++.
С .NET вы, вероятно, столкнетесь со всеми подобными махинациями с промежуточным уровнем управляемого C ++.
Многопоточность
Единственный разумный способ сделать это с участием более одного потока — поставить в очередь сигналы для обработки в потоке пользовательского интерфейса. В конце концов, если вы генерируете сигналы в другом потоке, вам нужно будет сделать это позже, чтобы обновить пользовательский интерфейс. Использование отдельного потока для частей модели и View / Controller приложения звучит как рецепт для взаимоблокировок. Также будет очень сложно отладить источник сигнала, если он давно пропадет в другом потоке. Ваша жизнь будет намного проще, если держать все в одном.
Других решений пока нет …