Denjs писал(а): ↑26.04.2011 22:45
гм... выводы и ограничения... т.е. фактически в вашей архитектуре :
1) информационное взаимодействие между объектами в вашей архитектуре ограничивается информированием других объектов об изменении значений своих атрибутов. Наверное, атрибут может быть и сложным (структурой, объектом класса) но это один атрибут.. так?
Именно так. Задумывается, что компонент (точнее его программист) может заявить атрибут любого типа.
Главное, чтобы предоставил адаптеры-преобразователи из других типов.
Denjs писал(а): ↑26.04.2011 22:45
2) информирование другого объекта обязано привести к установке другого значения у приемного объекта? ну наверное понятно что при этом можем вызваться обработчик установки атрибута...
Это зависит от того, что реализовал программист "приёмного" объекта.
Если оставил реализацию базового класса, то - да: он "умеет" только установить новое значение атрибута и в свою очередь разослать его тем, кто на него подписан.
А если программист реализовал методы получения нового значения, то это будет просто вызов метода. С параметром.
А уж будет он устанавливать атрибут у своего объекта или нет - это его дело.
Может вообще написать компонент "чёрная дыра" у которого есть атрибуты с любым именем, он готов принимать туда значения любого типа и все они будут там пропадать не вызывая никаких последствий.
Denjs писал(а): ↑26.04.2011 22:45
3) возврат какого-либо вычисляемого значения исходному объекту не возможен? т.е. объект не может "сказать" подписавшимся на его события объектам - "вот вам значение : посчитайте его пожалуйста" - и получить на выходе массив значений?
Я склонен считать такой стиль всё-таки наследием структурного программирования.
"Вызовем функцию, передадим параметры, получим результат".
Если уж на то пошлО, то у компонента вычислителя есть выход - цепляйтесь к нему и получайте результат.
Хотите - синхронно, хотите - асинхронно.
Denjs писал(а): ↑26.04.2011 22:45
4) объекты подписчики обязаны знать ссылку на объект, на событие изменения атрибута которого они подписываются?
Если хотят (если программист компонента захочет), то возможна и работа компонента с контейнером, поиск других компонентов по имени, подписка к ним, отписка, удаление, создание новых компонентов - на это ограничений нет.
Но предполагается, что абсолютному большинству компонентов для своей работы знать о том откуда они получают данные - не обязательно.
И устанавливать связи будет некий "настройщик", "конфигуратор" системы.
Denjs писал(а): ↑26.04.2011 22:45
5) "
"прямой" вызов методов компонента" - суть call-back, о минусах которого говорилось не раз, поломано не мало дров, и костылей к которому написано очень много. Понятно что это "просто", имеет свои плюсы, и все минусы мало кого останавливают (даже в Qt-шных софтинах) от его использования.
Я вообще про call-back думал по-другому.
Что ты отдаёшь какую-то работу на сторону и по завершению просишь "дёрнуть вот эту вот мою функцию".
А тут - просто вызовы виртуальных функций (если говорить в терминах C++) одних компонентов другими.
Denjs писал(а): ↑26.04.2011 22:45
Ну и вопросы межпроцессного взаимодействия при прямом вызове тоже остаются за кадром... а тут ещё надо атрибут менять у приемного объекта.
Я потому и говорю, что контейнер будет очень простым, потому что он не будет заморачиваться такими вопросами.
Его задача - хранить ссылки на компоненты и предоставлять определённый сервис. И всё.
Все остальные "вопросы" - к компонентам.
А там будет и межпроцессное взаимодействие, и CORBA, и чёрт-в-ступе, но! Самое главное: их можно стыковать друг с другом в рамках контейнера.
Denjs писал(а): ↑26.04.2011 22:45
Теперь моё сравнение с Qt-шным механизмом сигнал-слотов...
(1) : в сигналах Qt вы можете передавать несколько атрибутов, или не передавать атрибутов вообще...
Это похоже на WinAPI: куча функций с кучей аргументов.
"Редкий программист долетит до середины MSDN..."
Громоздко, одним словом.
Denjs писал(а): ↑26.04.2011 22:45
Сигнал в Qt - это не только информирование мира об изменении собственого состояния. Это может быть ещё и "команда".
Что значит "команда"?
Denjs писал(а): ↑26.04.2011 22:45
Испускание сигнала не обязано менять состояние атрибутов исходного объекта. Но если в обработчике атрибута написано "испускать сигнал" - он конечно будет испущен.
В вашей архитектуре - сигнал обновления будет испускаться, если новое значение атрибута будет равно старому?
Так и тут никто не заставляет действительно изменять атрибут исходного объекта.
"Сигнал обновления будет испускаться" тогда когда программист компонента в коде вызовет функцию send базового класса.
Хочешь - вызови send с тем же самым значением и оно разошлётся всем подписанным.
А уж как они будут на него реагировать (на повторяющиеся значения) - это их дело.
Может действительно как на команду, а может проигнорируют.
Кстати, можно изменить атрибут и "втихаря": т.е. положить в переменную новое значение, но не вызывать send.
Тогда это изменение обнаружит только тот, кто САМ прочитает значение атрибута.
Может в этом тоже найдётся какой-нибудь алгоритмический смысл.
Кстати, чтение атрибута - это же тоже вызов метода. И вовсе не обязательно, что это будет просто возврат текущего значения переменной.
Вполне возможно, что метод полезет куда-нибудь в базу данных или в устройство - узнать его состояние.
=== Denjs ===
(2) : в Qt прием сигнала не обязан менять состояние приемного объекта. Вы просто обрабатываете полученные значения в функции-слоте.
============
Абсолютно аналогично.
=== Denjs ====
(3) : в Qt в чистом виде, возврат значения возможен только при прямом вызове.
============
Своё мнение про возврат значения я уже изложил выше.
Добавлю: в решавшихся мною задачах практически всегда получалось так, что данные для вычисления даёт один компонент, вычисляет второй, а результат нужен... не тому, первому компоненту, а другому - третьему.
==== Denjs ====
(4) : при сборке системы - в идеале - кроме "объекта-сборщика" который "видит всех" - никто ничего не обязан знать.
т.е. объекты взаимодействуют друг с другом не зная с кем они работают.
==============
Тоже абсолютно аналогично.
За исключением:
1) Неких "системных" компонентов. Системных не с точки зрения операционной системы, а с точки зрения разрабатываемой системы.
2) Компонентов, которые специально созданы для работы друг с другом помимо интерфейса контейнера.
=== Denjs ====
Удаление объекта не приводит к сегфолту программы (см пункт 5).
=============
Я к этому тоже стремлюсь. Потому и обдумываю всяческие proxy-объекты, компоненты-заглушки, сообщающие, что объекта больше нет - короче какой-то корректный механизм удаления объекта из контейнера.
=== Denjs ===
(5) : Собственно сигнал-слоты судя по описаниям и проектировали для того, что бы избавить народ от необходимости использовать call-back. Да, если (теоретически !!!) "встанет" EventLoop - то это конечно приведет к нарушению работы в программе.. но я вот о таких случаях даже не слышал...
============
Так сигнал-слот - это, получается, что-то вроде очереди (шины) сообщений? Раз там присутствует цикл выборки событий.
А насчёт "встанет". Сам он может быть "вылизан" и содержит минимальное число ошибок, а критических и вообще нет.
Но что если его заблокирует некорректно написанный компонент?
=== Denjs ===
ещё раз - я пытаюсь не "макать вас в недостатки", но стараюсь дать хоть сравнительный анализ... если кто сделает такое по другим тезнологиях - например в бусте -же тоже наверняка есть "не call-back" механизмы взаимодействия?
в споре должна рождаться истина, иначе это все зазря)))
============
Я именно для этого и затеял эту тему.
Ну и плюс, если всё-таки дойдёт до программёжа - чтобы спрашивать у знатоков как реализовать тот или иной сложный момент.
Мне сейчас некоторые вещи из задуманного - не очевидны.
==== Denjs ====
скажите - межпроцессное взаимодействие вы тоже сможете на "чистых плюсах" написать? загрузка библиотек? что-то ещё?...
==============
Межпроцессное взаимодействие, как я уже написал выше - это к контейнеру не относится. Этим занимаются компоненты.
Вот загрузка библиотек - да, будет относительно небольшой кусок платформенно-зависимого кода.
Без этого никуда. Не Java всё-таки.
====== Denjs ======
>> И сложности будут только с системно-зависимыми компонентами или окружением движка. <<---- вот вот... вам надо решить что именно и как вы будете использовать системно зависимого, и насколько вы сможете от жтого отказаться ради портируемости.
=================
Задумка такая, что движок, которым занимаюсь я - портируется относительно легко.
А вот компонентами - занимаются их авторы и соответственно и портированием тоже. Или соавторы - если исходник компонента лежит в Сети с какой-нибудь свободной лицензией - бери и адаптируй под свою платформу. Становись соавтором.
Опять-таки, если речь не идёт о каком-то системном, платформенно-аппаратно-библиотечно-зависимом алгоритме, то он скомпилируется любым C++-компилятором, постольку поскольку в нём есть только код архитектуры контейнера (а он, предполагаем, уже на этой платформе присутствует) и самые стандартные конструкции C++.
=== sash-kan ===
извините, что встреваю в дускуссию.
просто до боли она знакома.
по листу рассылки eas-а.
с приведённой ссылкой никто не знакомился?
чего ради встрял? просто чтоб, возможно, кому-то время сэкономить.
===============
Честно говоря путанное объяснение архитектуры. Или может она сама такая.
Но это не значит, что там смотреть нечего. Может что-то и подсмотрю, однако применение этой платформы для меня сразу "убивается" такой фразой:
"среда обмена сообщениями, сериализованными в текстовый вид".
Я всё-таки стремлюсь к максимальной скорости взаимодействия компонентов друг с другом.
Это расширяет класс задач, которые можно решать с помощью движка и компонентов к нему.
Я и от CORBA из-за этого ухожу, хотя там почти всё, что сейчас у меня вызывает самые большие раздумья - уже реализовано.
Но маршалинг-анмаршалинг в пределах одного процесса, считаю мягко говоря лишним.