Здравствуйте, eao197, Вы писали: E>Но тогда в GC-приложении должен быть свой SObjectizer. 0. Скорее всего. E>Поэтому я и говорю, что если потребуется и будет заинтересованность, то сделаем 1. Заинтересованность будет однозначно. Хотя такой синтаксис в назвваниях и обозначениях немного отпугивает (некоторых уже не отпугивает после boost и stl , но для других — тяжеловато читать).
E>Мне просто интересно, захочет ли кто-то программировать в агентах, например, в C#, Python, Ruby или OCaml-е, или Lisp-е. 2. Нет... Пока нет. Не стоЯт еще такие задачи — есть более простые и "родные" способы для достижения подобных целей.
E>Второй вариант -- использовать для взаимодействия другие механизмы (SOAP, XML-RPC или CORBA).
Это правильно!
E>Тогда GC приложению вообще без разницы, написан ли сервер на C++ и SObjectizer-е или на чем-то еще. Такой вариант можно применять прямо сейчас. И в некоторых проектах у нас так и было. 3. Еще бы и хелп небольшой написать. Тогда п.2, возможно отменяется.
E>Главная политическая проблема SObjectizer в том, что SObjectizer существует только на C++ и только для C++. В частности, возможности SObjectizer для создания распределенных приложений можно использовать исключительно в С++. Конечно, SObjectizer не мешает использовать в этом же приложении иные способы взаимодействия (CORBA, COM, SOAP, XML-RPC). Но и не помогает. А если в приложение встраивается ручная поддержка CORBA или SOAP, то встает вопрос: “К чему тогда вообще использовать SObjectizer?” И ответ на этот вопрос, особенно когда требуется интероперабельность с написанными на других языках приложениями, часто бывает не в пользу SObjectizer.
Выделенное и есть один из признаков отсутствия инфраструктуры.
E>Еще одна проблема наследуется SObjectizer от C++. В последнее время у C++ появились очень серьезные конкуренты. С одной стороны, это Java и .Net/C# с огромным количеством готовых библиотек и IDE нового поколения. Очень многих программистов от C++ отталкивает отсутствие настолько же удобных IDE (с автодополнением, автоподсказкой, поддержкой рефакторинга) как IDEA и Eclipse для Java, или VisualStudio+ReSharper для C#. В С++ с этим дела обстоят неважно. A у SObjectizer еще хуже — ведь сейчас нет ни одной IDE, способной поддерживать специфические особенности SObjectizer (хотя бы так, как VisualStudio помогла использовать MFC)... E>[/q]
К сожалению и к счастью одновременно — это правда.
Здравствуйте, GU Glez, Вы писали:
GG>1. Заинтересованность будет однозначно. Хотя такой синтаксис в назвваниях и обозначениях немного отпугивает (некоторых уже не отпугивает после boost и stl , но для других — тяжеловато читать).
Поживем -- увидим. А что касается нотации, так пока ни у кого проблем не было, быстро привыкают.
E>>Мне просто интересно, захочет ли кто-то программировать в агентах, например, в C#, Python, Ruby или OCaml-е, или Lisp-е. GG>2. Нет... Пока нет. Не стоЯт еще такие задачи — есть более простые и "родные" способы для достижения подобных целей.
Можно ли раскрыть термин "подобных"? Или пример привести?
E>>Второй вариант -- использовать для взаимодействия другие механизмы (SOAP, XML-RPC или CORBA). GG>Это правильно!
Тогда, имхо, часть на SObjectizer усложняется. Появляются два вида взаимодействия -- асинхронное на уровне сообщений, когда границы между процессами размыты, и синхронное.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали: GG>>[...]. E>Можно ли раскрыть термин "подобных"? Или пример привести?
Хм... пример... Я хотел сказать, что "Подобные" — означает нечто похожее по уровню. Сейчас так вот сразу сказать не могу — не так много я на C# в частности и на .NET вообще. Но суть одна — теперь на .NET можно, очень много сделать в программировании клиент-серверных (и не только) приложений без лишнего гемора (т.е. что думаю, то и пишу не заботясь о низкоуровневых деталях). И все это решается в контексте одной-двух парадигм — что многих и привлекает.
E> E>Тогда, имхо, часть на SObjectizer усложняется. Появляются два вида взаимодействия -- асинхронное на уровне сообщений, когда границы между процессами размыты, и синхронное.
А это уже интересно. И вообще, чем это плохо или хорошо надо обдумавать и двигаться дальше. По мне так — если есть реальные проекты с GC, то вот на них и надо бы эксперемент проводить; если нет, то что-то стряпать более-менее все равно можно (GUI хотя бы), и вперед... если есть такая возможность, конечно.
Спасибо за экскурс
>> Это могло бы помочь оценить возможности SObjectizer.
ничто так не поможет как возможность пощупать
Так что жду выхода в свет, с туториалом и более менее реалистичным тестовым проектом.
Не скажу что жду уже сейчас Задача в которой бы, я думаю, этот фреймворк мне помог была полтора года назад... От Corba я тогда отказался — посчитал слишком тяжёлой и не нужной...
Время движется — может интерессные идеи появятся и этот фреймворк будет востребован... К тому времени думаю он ещё лучше будет
С уважением Denys Valchuk
IMHO чем больше мнений тем оптимальней выбор варианта... :)
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Dj.ValDen, Вы писали:
DV>>ничто так не поможет как возможность пощупать
E>)
DV>>Так что жду выхода в свет, с туториалом и более менее реалистичным тестовым проектом.
E>Т.е. имеющийся SObjectizer Book чем-то не достаточен?
может я не правильно выразился
я имел ввиду удобный хелп
Book хорош
Но как книга, а как хелп — нет. Одно другое не исключает — так что книгу не удаляйте
Но удобный хелп, в виде chm, html или ещё чего очень помог бы...
Я ещё сторонник UML описания
E>И что бы хотелось видеть в качестве тестового проекта?
Естественно, что то наглядное и не требующее установки спец оборудования
Может даже и ваши примеры из книжки... Если честно я не люблю смотреть на код как на письмо
Вот письма я пишу чёрным по белому и ничего лишнего — а код предпочитаю с подсветкой синтаксиса
С уважением Denys Valchuk
IMHO чем больше мнений тем оптимальней выбор варианта... :)
Здравствуйте, Dj.ValDen, Вы писали:
DV>я имел ввиду удобный хелп DV>Но удобный хелп, в виде chm, html или ещё чего очень помог бы... DV>Вот письма я пишу чёрным по белому и ничего лишнего — а код предпочитаю с подсветкой синтаксиса
Все это есть в виде html Reference, сгенерированного через doxygen. Как мне кажется, весьма подробный.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
[примечание: часть переписки, опубликованная здесь по согласию сторон]
ЕО>Там я один вопрос как раз затрагиваю, о возможности портирования SObjectizer на какой-нибудь из managed языков. Поскольку у тебя, как я вижу, вполне лояльное отношение к C#, то интересно было бы узнать, заинтересовался ли бы ты лично SObjectizer-ом, будь он реализован на C#.
Мое мнение насчет реализации подобной наработки на C# примерно такое:
— очень интересный подход диспечеров, в принципе — это краеугольный камень
технологии.
Остальное — суть эмуляция вещей, которые сейчас в дотнет делают через
reflection или на делегатах. Даже разделение класса и агента похоже вызвано
необходимостью отделить декларативные конструкции от "обычных".
Для дотнета, я уверен, была бы интересна богатая система диспечеризации
сообщений, а так же, разумеется, организация очередей сообщений к конкретным
объектам.
Из очевидных переделок под дотнет:
— события должны предоставляться делегатами, а не именами.
— сами сообщения лучше регистрировать по типу, а не по имени.
— другая терминология, события в дотнете — это "источник". Ваши send_msg
можно заменить/дополнить подписыванием вашего run-time на интересующие
события объектов.
— то, что вы называете событиями, в дотнете зовется обработчик оного — event
handler.
— возможным станет описывать в конфигурации, объекты какого типа создавать и
как их соединять друг с другом и с диспечером.
Да, кстати, а есть ли в твоей схеме возможность непосредственной стыковки?
Т.е. я имею в виду тот момент, что далеко не всегда требуются услуги
диспетчера. Например, я создаю комплексный объект, который суть модуль
других объектов. И мне может захотеться непосредственным образом соединить
события (обработчики) с сообщениями (событиями и их аргументами).
Ты поднимал вопросы асинхронности обработки сообщений и сетовал, что нет
возможности узнать результат обработки сообщения (или сам факт доставки). В
дотнете есть целый механизм вокруг IAsyncResult и динамического вызова
обработчиков. Далее. Необязательно синхронные вызовы делаются в том же
потоке!!! Можно вызвать событие другом потоке и дождаться завершения
обработки. С точки зрения объемлющего кода это будет выглядеть как
синхронное сообщение. На самом деле, конечно, все должно зависеть от
настроек. Т.е. некоторым событиям (методам) абсолютно все-равно в каком
потоке исполняться. В дотнете подобная доп. информация размечается
атрибутами. Так же можно атрибутами специфировать участие методов (событий)
в подписвании, вместо so_on_subscription().
В общем, если получиться гладко "вшить" диспетчеры в существующую
инфраструктуру .Net, то это все имеет смысл. Т.е. необходимо как-то
предусмотреть систему типов таким образом, чтобы практически одинаково
работать как с непосредственными прямым подключениями (синхронное
распространение событий), так и через диспетчера. Возможно, что
библиотека под дотнет совершенно неузнаваемо изменит первоначальное лицо и будет
прилично отличаться от оной на С++
Но это не страшно, если останется суть. А суть, насколько я понял, в
организации механизмов асинхронной доставки сообщений подписчкам. Большое
количество другой, дополнительной функциональности в SO лишь обслуживает
основную задачу, решая различные технические моменты. В общем, в дотнет
многие из тех моментов уже решены, поэтому библиотека может выйти гораздо
компактнее.
Как я бы предложил попробовать переделать на дотнет: самому выступить в роли
предвзятого юзера-программиста библиотеки и написать несколько
высокоуровневых тестов (сценариев) именно так, как ты бы хотел все это
видеть синтаксически (т.е. максимально кратко и выразительно). Даже факт
компиллируемости необязателен. А я с удовольствием подсказывал бы, как тот
или иной момент выразить на C# в частности или в дотнет вообще.
Насчет — заинтересовался бы лично? Скорее да, если речь пойдет об
организации системы асинхронно взаимодействующих объектов.
Здравствуйте, vdimas, Вы писали:
V>Мое мнение насчет реализации подобной наработки на C# примерно такое: V>- очень интересный подход диспечеров, в принципе — это краеугольный камень V>технологии.
Думаю, что можно и так сказать. Но диспетчер -- это всего лишь механизм для реализации основной идеи: время и место запуска обработчика какого-то события определяется не программистом, а SObjectizer-ом.
Второй краеугольный камень -- это взаимодействие на основе сообщений. Может быть даже он главнее. Во-первых, поэтому возможно само существование диспетчера. Во-вторых, появляется возможность делать относительно прозрачную распределенность.
Следствием всего этого дела является, имхо, более простой способ создания многопоточных приложений. В чем-то похожий на подход Erlang-а. Но отличающийся от встроенных механизмов поддержки многопоточности в Ada или Java. Если диспетчеры обеспечивают для агента гарантию запуска его обработчиков только на контексте одной нити в один момент времени, то проблем взаимной синхронизации вообще нет. К этому привыкаешь и необходимость ручной работы с mutex-ами или condition variables начинает казаться слишком утомительной
V>Остальное — суть эмуляция вещей, которые сейчас в дотнет делают через V>reflection или на делегатах. Даже разделение класса и агента похоже вызвано V>необходимостью отделить декларативные конструкции от "обычных".
Не уверен, что точно понимаю о чем ты говоришь. Понятие агента (и соответственно специального класса agent_t) было выделено по очень простым причинам:
-- чтобы у агента можно было запрашивать специальную информацию (имя класса агента, например);
-- чтобы агентов можно было помещать в одну коллекцию в рамках кооперации агентов;
-- чтобы у агентов можно было вызывать специальные обработчики событий (so_on_subscription, so_on_deregistration).
В общем, в результате обычной декомпозиции ООП
Декларативные конструкции (описание с помощью макросов класса агента) было выделено отдельно, так же по очень простой причине -- чтобы описания классов агентов (а я думаю, что эти описания нужны) обрабатывались независимо и один раз. Я обдумывал разные способы, например, чтобы у агента был виртуальный метод so_describe_class, в котором делались бы описания класса агента и этот метод бы вызывался при регистрации агента. Но это бы просто перенесло ту же самую декларативность в другое место.
Сами же обработчики событий должны быть обычными нестатическими методами. Как раз для манипуляции обработчиками событий вовсе не требовалось выделение отдельного класса agent_t.
V>Из очевидных переделок под дотнет: V>- события должны предоставляться делегатами, а не именами.
Мне кажется, что имена как раз добавляют декларативности.
V>- сами сообщения лучше регистрировать по типу, а не по имени.
Здесь не все так просто. Один обработчик события может быть подписан на разные типы сообщений. А один тип (C++ класс/структура) может использоваться для реализации разных сообщений.
V>- другая терминология, события в дотнете — это "источник". Ваши send_msg V>можно заменить/дополнить подписыванием вашего run-time на интересующие V>события объектов.
Вот это не полностью понимаю. Возможно, из-за слишком поверхностного знания дотнета.
V>- то, что вы называете событиями, в дотнете зовется обработчик оного — event V>handler.
Термин event handler у нас так же есть
Просто у нас нет события без обработчика и обработчика события без события Поэтому для краткости проще называть и события, и обработчики просто событиями.
V>- возможным станет описывать в конфигурации, объекты какого типа создавать и V>как их соединять друг с другом и с диспечером.
Да это, в принципе, и в C++ возможно. Просто во время выпуска первой версии SObjectizer не было времени докрутить эту идею до реализации.
V>Да, кстати, а есть ли в твоей схеме возможность непосредственной стыковки? V>Т.е. я имею в виду тот момент, что далеко не всегда требуются услуги V>диспетчера. Например, я создаю комплексный объект, который суть модуль V>других объектов. И мне может захотеться непосредственным образом соединить V>события (обработчики) с сообщениями (событиями и их аргументами).
Нет, такого нет и я думаю, что это уже будет не столько SObjectizer. Скорее тебе нужно что-то в стиле libsigc++.
V>Необязательно синхронные вызовы делаются в том же V>потоке!!! Можно вызвать событие другом потоке и дождаться завершения V>обработки. С точки зрения объемлющего кода это будет выглядеть как V>синхронное сообщение. На самом деле, конечно, все должно зависеть от V>настроек. Т.е. некоторым событиям (методам) абсолютно все-равно в каком V>потоке исполняться. В дотнете подобная доп. информация размечается V>атрибутами. Так же можно атрибутами специфировать участие методов (событий) V>в подписвании, вместо so_on_subscription().
С синхронностью все не так просто
Если синхронный вызов делается из нити, не относящейся к диспетчерам SObjectizer, то особых проблем нет. Но если синхронный вызов идет из обработчика событий агента, то в результате можно получить тупик, если в конце-концов потребуется задействовать нить диспетчера, на которой был инициирован синхронный вызов. Контроль и диагностирование таких тупиков может быть слишком дорогой операцией (при том, что потенциально она будет слишком редкой).
V>В общем, если получиться гладко "вшить" диспетчеры в существующую V>инфраструктуру .Net, то это все имеет смысл. Т.е. необходимо как-то V>предусмотреть систему типов таким образом, чтобы практически одинаково V>работать как с непосредственными прямым подключениями (синхронное V>распространение событий), так и через диспетчера. Возможно, что V>библиотека под дотнет совершенно неузнаваемо изменит первоначальное лицо и будет V>прилично отличаться от оной на С++
Очень на то похоже
V>Но это не страшно, если останется суть. А суть, насколько я понял, в V>организации механизмов асинхронной доставки сообщений подписчкам. Большое V>количество другой, дополнительной функциональности в SO лишь обслуживает V>основную задачу, решая различные технические моменты. В общем, в дотнет V>многие из тех моментов уже решены, поэтому библиотека может выйти гораздо V>компактнее.
Очень возможно. Особенно с учетом автоматической сборки мусора в дотнете. Собственно, в этом и привлекательность потрирования SObjectizer в managed среды, что многие вещи там уже готовы или проще. Смущает возможная производительность, т.к. вызов обработчика события -- это весьма существенный оверхед. Хотя, судя по общему мнению, JIT собирается творить чудеса
Тут важно другое оценить -- заинтересованы ли пользователи managed языков в подобных инструментов. Насколько я могу судить, многие разработки на Java ведутся в рамках Web-технологий и по разным существующим спецификациям (J2EE со товарищи), на готовых фреймворках и серверах приложений. Поэтому я не очень понимаю, заинтересуется ли кто-нибудь из Java разработчиков чем-то подобным SObjectizer-у. У C#, имхо, список возможных предметных областей гораздо шире, а список готовых инструментов -- наоборот.
V>Насчет — заинтересовался бы лично? Скорее да, если речь пойдет об V>организации системы асинхронно взаимодействующих объектов.
Спасибо за столь развернутое мнение.
Еще вопрос: а как бы ты оценил саму статью? Стиль, форму подачи материала, его объем?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Аноним, Вы писали:
А>Ребята не имею ничего личного к автору,
Я имею — в хорошем смысле. А>при общении с ним убеждался в его проффесионализме,
Аналогично. А> Софт, написанный на этом движке, (работал с ним лично)
Аналогично. А>это один единый гармонично работающий глюк. Не поддающийся логичному лечению
У меня работает, как часы. Ни одного глюка за несколько лет не замечено. Может, дело-таки не совсем в Евгении?
Сразу — концепция управления потоками мне очень понравилась.
Концепция управления состояниями очень не понравилось.
С последнего и начну.
С моей точки зрения, как раз взаимодействие на основе сообщений создает идеальный фундамент для реализации состояний в виде отдельных классов — в них можно реализовывать те и только те методы, которые имеют смысл для данного состояния.
Т.е. идеальный в моих глазах подход выглядит так — агент — это идентификатор. Состояние — это объект, который в данный момент зарегистрирован под этим идентификатором. Набор методов вида
ProcessMessage(Message msg)
где вместо Message задается имя конкретного подкласса, как раз и является описанием и состояния и событий, которые оно в состоянии обрабатывать. Это наиболее естественный способ создания такого класса (событие — обработчик) и способ определения допустимых сообщений в одном флаконе.
А вот на отсутствие обработчика для сообщения система должна реагировать в обязательном порядке.
Благо это не сложно сделать.
Также хотелось бы заметить, что есть и другие варианты решения подобной задачи. Например — com+ events. Там есть две модели обработки — синхронная (гут) и асинхронная на основе MQ (даже лучше).
Соответственно, в идеальной системе такого рода эти модели было бы неплохо предусмотреть. Опять же, хорошо бы иметь возможность отследить судьбу асинхронной обработки.
На сим пока закончу, ибо выдохся.
Только один поинт — приплетать сюда events из .net я бы не стал. Не нужны они тут.
Здравствуйте, eao197, Вы писали:
E>Думаю, что можно и так сказать. Но диспетчер -- это всего лишь механизм для реализации основной идеи: время и место запуска обработчика какого-то события определяется не программистом, а SObjectizer-ом.
Нет, все же программистом
Просто программист использует "другой" инструмент. Знаешь, насчет той статьи, я бы добавил туда более четкого позиционирования технологии (может быть в ущерб подробностям реализации). Т.е., прежде, чем что-то обсуждать, было бы неплохо понять — что именно мы собираемся обсуждать. SObjectizer — это инструмент. Инструмент для чего? Вон ниже mrozov вообще выдвигает свои соображения насчет распределенной жизни объектов и их состояний. Только мне его рассуждения показались очень уж частными, т.е. опять же — моментами, с которыми сталкивался он лично, но которые не обязательно хорошо подходят для других задач.
E>Второй краеугольный камень -- это взаимодействие на основе сообщений. Может быть даже он главнее.
Женя, я делаю акцент на том, что рассматривал твой вопрос с т.з. реализации SObjectizer на дотнет. А в нем взаимодействие на основе сообщений УЖЕ реализовано. Т.е. мы можем вызывать методы асинхронно (просто посылать сообщение), синхронно (послать сообщение и дожаться ответа), и откликаться на события, на которые подписаны (на одно событие может быть подписано куча подписчиков). Событие — это обратный вызов (call back), т.е. все то, что делает твоя система. Однако, при этом подробности потоков исполнения, блокировки и пр. реализованы лишь в 2-х моделях: STA и MTA. Твои диспеччеры позволяют создавать произвольное количество "групп" — аппартаментов, и позволяют создавать диспеччеры, которые этими аппартаментами управляют. Вот на какой именно уровень ты залез. И мне это кажется весьма любопытным. Более того, есть еще один момент. В дотнет нужно явно указывать — синхронно или асинхронно я вызываю события. Мне бы хотелось... вынести это из вызывающего кода, что-ли.
Далее. Ты все время говоришь об взаимодействии на основе сообщений. Вообще-то считается, что вызов метода объекта — это и есть посылка ему некоего сообщения. (Обратный вызов, т.е. событие для подписчика, разумеется тоже). Просто в твоей системе все делается через обратный край воронки: SendMsg(), а в дотнете эта воронка двухсторонняя: с обоих сторон обычные вызовы обычных методов, а между ними — транспорт с пакетами сообщений, STA и MTA диспетчеры.
Согласись, что SendMsg("ClosePipe", param) проигрывает этому: ClosePipe(param) сразу по многим пунктам.
Одиин из них: я вообще с очень давних времен не люблю строковые константы в коде. Когда их несколько сотен (илил даже несколько тысяч) — ими невозможно управлять, в то время как сигнатурами методов помогают управлять современные IDE.
E>Во-первых, поэтому возможно само существование диспетчера. Во-вторых, появляется возможность делать относительно прозрачную распределенность.
Да, для С++ так и есть. На отсутствие НОРМАЛЬНЫХ сетевых высокоуровневых библиотек для С++ Страуструп жаловался более 10 лет назад, но воз и ныне там, к большому сожалению. Для дотнета распределенность достигается весьма прозрачно. Слово прозрачно — ключевое. Для алгоритма не имеет значения, с локальным объектом идет работа, или с его удаленным прокси. Правда есть одна оговорка — это прозрачно до тех пор, пока имеющиеся возможности устраивают. Как только чего-то нехватает в дотнет, то приходится довольно много делать "ручками", даже в нем. (Собственно, как и везде — неудивительно).
Ценность твоего опыта — в нескольких реальных проектах (насколько я понял) на своей технологии. Ты уже разглядывал в упор все эти подводные камни, о которых большинство даже сильных спецов знает лишь благодаря своей эрудиции.
В общем, прежде, чем обсуждать технические моменты, а главное — сам вопрос: "нужен ли SObjectizer дотнету", ты лично (да именно ты и только ты ) должен собрать как можно больше информации о том, как аналогичное сделано в этом дотнете и какие именно работы по организации распределенных систем были бы полезны/интересны дотнетному сообществу.
Смотри, как сделать простейшую распределенную систему на дотнете, которая очень близко копирует именно твою архитектуру:
// это сигнатура сообщенияpublic delegate void CurrencyChangedMsg(object sender, string currencyCode, double currency);
// это наш главный диспетчерpublic interface ICurrencyMarket {
event CurrencyChangedMsg CurrencyChanged;
}
Затем, интересующие агенты получают каким-либо образом ссылку на экземпляр CurrencyMarket, и подписываются на сообщения, например так:
public class AirportTabloid : Form {
blah blah blah
void ConnectToCurrencyMarkets() {
// подписываемся на события от 3-х разных диспетчеров во всем мире.
ICurrencyMarket market = (ICurrencyMarket)RemotingServices
.Connect("tcp://currency.market.com:8085/Dispatcher", typeof(ICurrencyMarket))
market.CurrencyChanged += OnCurrencyChanged;
market = (ICurrencyMarket)RemotingServices
.Connect("http://www.currency.jp/currency", typeof(ICurrencyMarket))
market.CurrencyChanged += OnCurrencyChanged;
market = (ICurrencyMarket)RemotingServices
.Connect("iiop://privatbank.ru:11500/Dispatcher", typeof(ICurrencyMarket))
market.CurrencyChanged += OnCurrencyChanged;
}
void OnCurrencyChanged(object sender, string currencyCode, double currency) {
TextBox tb = FindByCurrencyCode(currencyCode);
if(tb!=null)
tb.Text = currency.Format("C");
}
}
(обрати внимание на разные заголовки URL )
Видишь, в чем основное отличие от твоей имплементации на С++? В том, что программист орудует НЕПОСРЕДСТВЕННО прикладными абстракциями, а не их строковыми идентификаторами.
E>Следствием всего этого дела является, имхо, более простой способ создания многопоточных приложений. В чем-то похожий на подход Erlang-а. Но отличающийся от встроенных механизмов поддержки многопоточности в Ada или Java. Если диспетчеры обеспечивают для агента гарантию запуска его обработчиков только на контексте одной нити в один момент времени, то проблем взаимной синхронизации вообще нет. К этому привыкаешь и необходимость ручной работы с mutex-ами или condition variables начинает казаться слишком утомительной
Да-да, это нам было знакомо еще с COM, действительно, порой очень удобно. Но, к сожалению, у программистов не было возможности явно управлять всеми этими механизмами. Ведь мне может захотеться одну группу методов исполнять в одном треде, а другую — в другом. Т.е. часто бывает так, что синхронизировать мютексами надо не весь объект, а его отдельные прикладные аспекты (абстракции). В общем, было бы интересно даже просто поучаствовать в обсуждении этого дела.
V>>Остальное — суть эмуляция вещей, которые сейчас в дотнет делают через V>>reflection или на делегатах. Даже разделение класса и агента похоже вызвано V>>необходимостью отделить декларативные конструкции от "обычных".
E>Не уверен, что точно понимаю о чем ты говоришь. Понятие агента (и соответственно специального класса agent_t) было выделено по очень простым причинам: E>-- чтобы у агента можно было запрашивать специальную информацию (имя класса агента, например); E>-- чтобы агентов можно было помещать в одну коллекцию в рамках кооперации агентов; E>-- чтобы у агентов можно было вызывать специальные обработчики событий (so_on_subscription, so_on_deregistration). E>В общем, в результате обычной декомпозиции ООП
В дотнет есть TransparentProxy и СontextBoundObject. Это я даю наименования классов, которые относятся к данной теме и функциональность которых может показаться тебе очччень любопытной.
V>>Из очевидных переделок под дотнет: V>>- события должны предоставляться делегатами, а не именами.
E>Мне кажется, что имена как раз добавляют декларативности.
Нет, имена добавляют лишний строковую информационную замусоренность. В больших проектах удобнее навигироваться по элементам программы, а не по значениям строковых констант. К тому же, мне нравится более сильная статическая связь элеменетов программы (типизированность). Т.е. компилятор не пропустит вызов не того сообщения не с теми параметрами.
E>Здесь не все так просто. Один обработчик события может быть подписан на разные типы сообщений. А один тип (C++ класс/структура) может использоваться для реализации разных сообщений.
В общем, посмотри на пример. В дотнет ты можешь подписаться на событие, если сигнатура твоего метода совпадает с сигнатурой события. Т.е. ты можешь подписать на один и тот же метод-обработчик события от РАЗНЫХ источников совершенно разного типа (в примере указан один тип для 3-х удаленных серверов, но это могли бы быть совершенно разные 3 типа), которые могут плеваться совершенно разными типами сообщений. Главное — чтобы совпадали сигнатуры.
V>>- другая терминология, события в дотнете — это "источник". Ваши send_msg V>>можно заменить/дополнить подписыванием вашего run-time на интересующие V>>события объектов.
E>Вот это не полностью понимаю. Возможно, из-за слишком поверхностного знания дотнета.
Я в примере показал как это выглядит внешне. Ну а как оно выглядит внутренне — это надо знакомится с System.Runtime.Remoting в mscorlib, лучше всего рефлектором + MSDN.
E>Просто у нас нет события без обработчика и обработчика события без события Поэтому для краткости проще называть и события, и обработчики просто событиями.
Хм... а разве не может быть так, что в какой-то момент на какое-то событие нет заинтересованных обработчиков (агентов)? Вполне нормальная ситуация...
V>>- возможным станет описывать в конфигурации, объекты какого типа создавать и V>>как их соединять друг с другом и с диспечером.
E>Да это, в принципе, и в C++ возможно. Просто во время выпуска первой версии SObjectizer не было времени докрутить эту идею до реализации.
В дотнет это будет просто как никогда. В моем примере мне бы хотелось вместо хардкодного тела метода ConnectToCurrencyMarkets() описать все это в стандартном файле конфигурации... Неплохо так же иметь к нему визуальный редактор
V>>Да, кстати, а есть ли в твоей схеме возможность непосредственной стыковки? V>>Т.е. я имею в виду тот момент, что далеко не всегда требуются услуги V>>диспетчера. Например, я создаю комплексный объект, который суть модуль V>>других объектов. И мне может захотеться непосредственным образом соединить V>>события (обработчики) с сообщениями (событиями и их аргументами).
E>Нет, такого нет и я думаю, что это уже будет не столько SObjectizer. Скорее тебе нужно что-то в стиле libsigc++.
И да и нет... Я ведь не зря говорил про "гладкую" стыковку с механизмом дотнета. В общем, оба способа должны внешне выглядеть одинаково. И не важно как это будет называться, SObjectizer или boost::signal. Какой конкретно механизм используется для каждого конкретного соединения диспетчера и агента должно зависеть только лишь от их взаимного расположения и суммарных взаимных политик и настроек.
E>С синхронностью все не так просто E>Если синхронный вызов делается из нити, не относящейся к диспетчерам SObjectizer, то особых проблем нет. Но если синхронный вызов идет из обработчика событий агента, то в результате можно получить тупик, если в конце-концов потребуется задействовать нить диспетчера, на которой был инициирован синхронный вызов. Контроль и диагностирование таких тупиков может быть слишком дорогой операцией (при том, что потенциально она будет слишком редкой).
Я же говорю — тебе виднее
Твой опыт весьма уникален. Но я так же уверен, что есть возможности для разруливания всего этого дела. Мне тут же в голову полезли детали, но не хочу сейчас их обсуждать, ибо это будет очень сыро с моей стороны (навскидку).
E>Тут важно другое оценить -- заинтересованы ли пользователи managed языков в подобных инструментов. Насколько я могу судить, многие разработки на Java ведутся в рамках Web-технологий и по разным существующим спецификациям (J2EE со товарищи), на готовых фреймворках и серверах приложений. Поэтому я не очень понимаю, заинтересуется ли кто-нибудь из Java разработчиков чем-то подобным SObjectizer-у. У C#, имхо, список возможных предметных областей гораздо шире, а список готовых инструментов -- наоборот.
Далеко не всем будет интересно, но заинтересованные найдутся, разумеется. Пока что люди заинтересованы не столько тактико-техническими характеристиками своих систем, сколько самим фактом реализации таких систем. А для этого и встроенных возможностей дотнета вполне хватает. А вот когда захочется делать эффективно, но по прежнему просто — потребуютс тулзы, типа обсуждаемого.
Дима, интересный ответ получился, нужно его покурить... Пока же несколько простых уточнений.
E>>Здесь не все так просто. Один обработчик события может быть подписан на разные типы сообщений. А один тип (C++ класс/структура) может использоваться для реализации разных сообщений.
V>В общем, посмотри на пример. В дотнет ты можешь подписаться на событие, если сигнатура твоего метода совпадает с сигнатурой события. Т.е. ты можешь подписать на один и тот же метод-обработчик события от РАЗНЫХ источников совершенно разного типа (в примере указан один тип для 3-х удаленных серверов, но это могли бы быть совершенно разные 3 типа), которые могут плеваться совершенно разными типами сообщений. Главное — чтобы совпадали сигнатуры.
Я как раз говорил о том, что обработчик пожет получать сообщения разных типов (типы источники сообщений вообще не при чем). В твоей терминологии бы это означало, что обработчик имел бы сразу несколько сигнатур.
И еще один момент -- сообщения, в отличии от сигнатур методов, проще расширять.
E>>Просто у нас нет события без обработчика и обработчика события без события Поэтому для краткости проще называть и события, и обработчики просто событиями.
V>Хм... а разве не может быть так, что в какой-то момент на какое-то событие нет заинтересованных обработчиков (агентов)? Вполне нормальная ситуация...
Так в том-то и дело, что событие -- это факт реакции конкретного агента на конкретное сообщение. Если агент не заинтересован в сообщении или агента просто нет, то нет и события, а сообщения уходят либо в пустоту, либо другим агентам.
E>>Нет, такого нет и я думаю, что это уже будет не столько SObjectizer. Скорее тебе нужно что-то в стиле libsigc++.
V>И да и нет... Я ведь не зря говорил про "гладкую" стыковку с механизмом дотнета. В общем, оба способа должны внешне выглядеть одинаково. И не важно как это будет называться, SObjectizer или boost::signal. Какой конкретно механизм используется для каждого конкретного соединения диспетчера и агента должно зависеть только лишь от их взаимного расположения и суммарных взаимных политик и настроек.
Дело в том, что сейчас в SObjectizer есть механизм т.н. insend-событий -- это когда SObjectizer вызывает обработчик события прямо внутри send_msg и на контексте той же нити. Тот, кто вызывает send_msg даже не знает, что insend-события уже отработали. Для отправителя сообщения внешне ничего не изменилось.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
V>>В общем, посмотри на пример. В дотнет ты можешь подписаться на событие, если сигнатура твоего метода совпадает с сигнатурой события. Т.е. ты можешь подписать на один и тот же метод-обработчик события от РАЗНЫХ источников совершенно разного типа (в примере указан один тип для 3-х удаленных серверов, но это могли бы быть совершенно разные 3 типа), которые могут плеваться совершенно разными типами сообщений. Главное — чтобы совпадали сигнатуры.
E>Я как раз говорил о том, что обработчик пожет получать сообщения разных типов (типы источники сообщений вообще не при чем). В твоей терминологии бы это означало, что обработчик имел бы сразу несколько сигнатур.
Да, в моей терминологии это было бы — несколько "входных точек", то бишь, несколько методов, по одному на каждую сигнатуру. Знаешь, как подобное разруливается в Windows.Forms? Там используется одна сигнатура на большинство событий, вот она:
public delegate void EventHandler(object sender, EventArgs e);
Итак, sender — кто угодно, EventArgs — абсолютно пустой класс, просто корень базовой иерархии для других аргументов событий. Понятное дело, что через эту схему можно прогнать произвольное кол-во типов сообщений, совместимых с одной и той же сигнатурой "точки входа", то бишь метода-обработчика (event handler).
Но мне подобные схемы не нравятся так же, как использование void* в С++. Пусть MS выбрала именно такую сигнатуру по уважительной причине (тонны типов конролов и тонны сообщений), свое ПО я предпочитаю выражать во вполне конкретных типах и напрягать компилятор на первоначальную проверку логики программы, то бишь использовать типизацию.
E>И еще один момент -- сообщения, в отличии от сигнатур методов, проще расширять.
Ок, как насчет еще большей модификации приведенной схемы:
public class MsgBase {}
public delegate void MsgHandler(MsgBase msg); // вот такая сигнатура
Но мне такая схема совершенно не нравится. Ведь все-равно внутри обработчика придется делать некий swtch-case (if-else) по типу сообщения и обрабатывать каждый тип по-своему. Так почему бы не выполнить явную функциональную декомпозицию и не подписать разные сообщения сразу на "нужные" точки входа?
Ну и опять же — типизированность. В моем подходе ты принципиально не сможешь подписаться на сообщение, которое не умеешь обрабатывать.
Да, важный момент. Насколько я понял, в твоих реальных системах ты часто использовал только лишь имя (идентификатор) сообщения. Да, это важный класс сообщений, которые интересны самим только фактом своего возникновения.
public delegate void Notify();
public IMyServer {
event Notify Event1, Event2, Event3 ... EventN;
}
public MyClient {
void Connect(IMyServer server) {
server.Event1+=OnEvent1To3;
server.Event2+=OnEvent1To3;
server.Event3+=OnEvent1To3;
server.Event4+=OnEvent4ToN;
...
server.EventN+=OnEvent4ToN;
}
// здесь мы обрабатываем одну группу сообщенийvoid OnEvent1To3() { ... }
// здесь - другуюvoid OnEvent4ToN() { ... }
}
Итак, у нас есть одна сигнатура — пустая, и куча событий (терминология дотнет), использующих эту сигнатуру. И есть 2 обработчика событий, OnEvent1To3 мы подписали первые 3 события, на OnEvent4ToN — остальные.
Согласись, довольно-таки гибко и главное, подобный код — самодокументируем по сути, его легко понять. Я уверен, что ты все понял.
E>>>Просто у нас нет события без обработчика и обработчика события без события Поэтому для краткости проще называть и события, и обработчики просто событиями.
V>>Хм... а разве не может быть так, что в какой-то момент на какое-то событие нет заинтересованных обработчиков (агентов)? Вполне нормальная ситуация...
E>Так в том-то и дело, что событие -- это факт реакции конкретного агента на конкретное сообщение. Если агент не заинтересован в сообщении или агента просто нет, то нет и события, а сообщения уходят либо в пустоту, либо другим агентам.
Понятно, опять расхождение в терминологии. Я тебя понял, я примерно это и имел в виду.
V>>И да и нет... Я ведь не зря говорил про "гладкую" стыковку с механизмом дотнета. В общем, оба способа должны внешне выглядеть одинаково. И не важно как это будет называться, SObjectizer или boost::signal. Какой конкретно механизм используется для каждого конкретного соединения диспетчера и агента должно зависеть только лишь от их взаимного расположения и суммарных взаимных политик и настроек.
E>Дело в том, что сейчас в SObjectizer есть механизм т.н. insend-событий -- это когда SObjectizer вызывает обработчик события прямо внутри send_msg и на контексте той же нити. Тот, кто вызывает send_msg даже не знает, что insend-события уже отработали. Для отправителя сообщения внешне ничего не изменилось.
Ну, замечательно... Для GUI этот способ весьма востребован.
Здравствуйте, vdimas, Вы писали:
E>>И еще один момент -- сообщения, в отличии от сигнатур методов, проще расширять.
V>Ок, как насчет еще большей модификации приведенной схемы: V>
V>public class MsgBase {}
V>public delegate void MsgHandler(MsgBase msg); // вот такая сигнатура
V>
Как только появляется сигнатура с одним параметром msg, то сразу напоминает SObjectizer.
V>Но мне такая схема совершенно не нравится. Ведь все-равно внутри обработчика придется делать некий swtch-case (if-else) по типу сообщения и обрабатывать каждый тип по-своему. Так почему бы не выполнить явную функциональную декомпозицию и не подписать разные сообщения сразу на "нужные" точки входа?
V>Ну и опять же — типизированность. В моем подходе ты принципиально не сможешь подписаться на сообщение, которое не умеешь обрабатывать.
Да я понимаю о чем ты говоришь. Это на самом деле так (опять вспоминаются вечные споры динамическая типизация+duck typing против статической типизации).
Хотя в данном конкретном случае я говорил о добавлении в MsgBase новых полей, а не новых наследников. По аналогии с протоколами -- новая версия протокола остается совместимой с предыдущей версией, но добавляет новые поля, которые старая версия может проигнорировать. Подобное расширение, перенесенное на методы будет означать, что каждое новое расширение нужно будет добавлять новый метод-отправитель сообщения:
По поводу типизации я думал вот чего сделать в свое время, чтобы отсылка была не через send_msg напрямую, а чтобы в каждое сообщение отсылалось с помощью статического метода в типе сообщения:
а все обращения к send_msg скрывались бы внутри send().
Но здесь и трудоемкость большая (для C++) и сложно один тип использовать для нескольких сообщений с разными именами типов. Главная причина отсутствия, все же, в трудоемкости. Но я надеюсь, что когда для агентов в C++ начнет применяться кодогенерация, такая штука в SObjectizer появится.
V>Согласись, довольно-таки гибко и главное, подобный код — самодокументируем по сути, его легко понять. Я уверен, что ты все понял.
Угу, понял. Вот так это могло бы выглядеть в SObjectizer на C++.
Дима, у меня предложение: пока тему статической vs динамической типизации не развивать.
Я понял твою точку зрения. Но есть и еще такой фактор, что используемый сейчас в SObjectizer подход позволяет добавить в статически типизированный C++ какие-то черты динамической типизации. Иногда полезно. Хотя во мне может еще отставаться остаточное впечатление (стереотип) с тех времен, когда у предшественника SObjectizer-а был визуальный дизайнер, а все конструирование осуществлялось как прописывание имен в соответствующих формочках.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, VVB16, Вы писали:
VVB>Жаль что при создании SObjectizer вы сразу не стали использовать ACE.
Сейчас разрабатывается обновленная версия SObjectizer, в которой ACE как раз используется в качестве нижнего уровня.
VVB>Там как раз ActiveObjects есть и механизмы для организации их работы.
Дело в том, что ACE и SObjectizer предоставляют разные подходы к организации работы активных объектов. Подход ACE, имхо, ориентирован в первую очередь на обработку потоков данных из коммуникационых каналов. И все преимущества подхода ACE начинают сказываться, когда применяются высоуровневые фреймворки ACE, т.к. Task и Streams.
SObjectizer же предназначен для обработки логики в случаях, когда эта логика может описываться конечными автоматами. И здесь SObjectizer по сравнению с ACE дает некоторое удобство программисту, т.к. в ACE все ообщение через очерди сообщений нужно делать вручную (начиная от организации самих очередей и операций записи/чтения, заканчивая необходимостью вручную упаковывать данные в ACE_Message_Block). А в SObjectizer можно легко обмениваться прикладными сообщениями без знания этих низкоуровневых деталей.
Так же, ACE предлагает очень низкоуровневые средства для организации распределенных приложений. Нужно будет самостоятельно программировать весь data flow и преобразование данных. SObjectizer здесь так же серьезно упрощает работу программисту.
В общем, после моего знакомства с ACE я считаю, что ACE должна быть фундаментом, на котором будет стоять SObjectizer. Но SObjectizer будет предоставлять другие возможности, нежели ACE.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Мне понравилась статья в RSDN о SObjectizer и собственно сама
платформа. Хотелось бы узнать можно получить SObjectizer для
разработки не комерческих продуктов в качестве одного из компанентов,
к примеру учебно-исследовательские работы, диплом.
Здравствуйте, vim, Вы писали:
vim>Мне понравилась статья в RSDN о SObjectizer и собственно сама vim>платформа. Хотелось бы узнать можно получить SObjectizer для vim>разработки не комерческих продуктов в качестве одного из компанентов, vim>к примеру учебно-исследовательские работы, диплом.
Приятно слышать такие слова. Спасибо за отзыв.
Получить SObjectizer можно. Но есть несколько наших внутренних вопросов, которые мы должны решить прежде чем выпустить SObjectizer наружу -- это окончательный выбор лицензии для SObjectizer и выбор хостинга, на котором будет располагаться дистрибутив SObjectizer-а. Думаю, что в течении одной-двух недель мы сможем решить эти вопросы и опубликовать дистрибутив SObjectizer для свободного скачивания в Интернете.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.