SObjectizer: прошлое, настоящее, будущее
Евгений Охотников | 14.08.2014
История проекта SObjectizer, архитектура продукта, принцип работы, примеры использования, особенности процесса разработки и тестирования, мягкая диктатура, релизная политика, просчеты и извлеченные уроки, прицел на будущее.
Команда проекта: Гродзицкий Николай, Охотников Евгений, Сивко Борис, Суднеко Артур, Томашенко Денис, Шмаков Николай
Прошлое
Очень давнее прошлое
Историю SObjectizer можно начинать с 1995 года, когда в отделе АСУТП Гомельского КБ Системного Программирования собралась команда для разработки объектно-ориентированной SCADA-системы. Этой командой был придуман способ построения приложения из агентов, обменивающихся асинхронными сообщениями. Способ этот был реализован в виде SCADA-системы под названием SCADA Objectizer, где слово Objectizer отражало активное использование ООП.
На разработку первой версии SCADA Objectizer в очень непростых экономических условиях ушло около трех лет. В 1999 году в эксплуатацию была успешно запущена разработанная на SCADA Objectizer система управления производством комбикорма на одном из местных комбинатов хлебопродуктов. К началу 2000 года была сделана вторая, более продвинутая версия SCADA Objectizer.
Две первые версии пытались идти по традиционному пути SCADA-пакетов: было разделение на GUI-пакет конструктора АСУТП и отдельную систему исполнения. К сожалению, сил на развитие системы в таком виде у команды не хватило.
В 2000 году был проведен эксперимент и создана третья версия Objectizer, в которой описание АСУТП создавалось не в GUI-конструкторе, а на специализированном декларативном языке. Это описание транслировалось в C++ код, который компилировался и линковался с системой исполнения. На выходе получался программный модуль, решающий конкретную прикладную задачу. Эксперимент был очень интересным, подтолкнувшим к переосмыслению механизма агентов, пониманию их удобства для разработки распределенных приложений, но …
Но все работы над SCADA Objectizer в КБСП фактически прекратились к концу 2000 года, когда распалась команда, занимавшаяся разработкой SCADA Objectizer. Более подробно история этого периода описана в старой статье в “Компьютерной Газете”.
Давнее прошлое
Новый виток в развитии истории SObjectizer начался в 2001 году, когда двое бывших разработчиков SCADA Objectizer из КБСП оказались в компании “Интервэйл”.
В одной из первых разработок, которую автор статьи выполнял в компании “Интервэйл”, потребовалось реализовать обмен асинхронными сообщениями между несколькими рабочими нитями приложения. Тогда стало очевидно, что идеи агентного подхода могут быть востребованы не только в АСУТП, и что механизм использования агентов и асинхронной передачи сообщений между ними может очень успешно применяться в многопоточных приложениях, в том числе и в распределенных.
Поэтому весной 2002 года появилась новая реализация старых идей под названием SObjectizer-4. Эта версия более-менее активно развивалась с 2002 по 2004 годы, и на ее основе было разработано и запущено в эксплуатацию несколько проектов в компании “Интервэйл”.
В 2005 году стало очевидно, что развитие SObjectizer-4 внутри компании “Интервэйл” замедлилось. Поэтому, после длительных размышлений и сомнений, было принято решение выпустить SObjectizer-4 как проект Open Source. Так, в 2006 году SObjectizer появился на SourceForge под BSD-лицензией, а в журнале RSDN Magazine – большая статья об этом проекте.
Недавнее прошлое
С 2002 года по настоящее время SObjectizer-4 активно применяется в нескольких больших проектах внутри компании “Интервэйл”. Время показало, что в SObjectizer-4 допущено несколько просчетов, которые усложняют его использование и являются серьезными препятствиями к увеличению производительности SObjectizer-4 и построенных на его основе приложений:
- Использовался один общий системный словарь, в котором находились описания всех коопераций, агентов, сообщений, событий и т.д. Доступ к этому словарю требовал синхронизации, что снижало общую производительность: слишком много времени рабочие нити ждали освобождения словаря.
- Все сущности в SObjectizer-4 идентифицировались строковыми именами. Это так же увеличивало накладные расходы за счет необходимости частого сравнения строковых имен.
- Мешало отсутствие контроля со стороны компилятора. Пользователь мог ошибиться в содержимом строковой константы, но эта ошибка проявлялась только во время исполнения. Хотелось, чтобы большая часть подобных опечаток обнаруживалась во время компиляции, что позволило бы снизить количество проверок во время работы SObjectizer.
- Также, в некоторых случаях, серьезным препятствием было наличие одного общего системного словаря, который представлял из себя глобальную переменную. Это не позволяло запустить в приложении несколько независимых друг от друга экземпляров SObjectizer-4.
В 2010 году стартовали работы по созданию новой версии – SObjectizer-5. Основные работы по созданию SObjectizer-5 были проведены в течении 2010-2011 годов, после чего SObjectizer-5 стал активно использоваться в разработке новых программных модулей, постепенно вытесняя SObjectizer-4. Однако первый публичный релиз SObjectizer-5 состоялся на SourceForge лишь в мае 2013 года после того как SObjectizer-5 в достаточной мере стабилизировался.
Области применения и результаты
Внутри компании “Интервэйл” SObjectizer-4 и SObjectizer-5 применяются в ряде проектов, которые можно охарактеризовать как mission critical.
Самым крупным из них является транспортная платформа для обслуживания SMS- и USSD-трафика. На начало 2013 года данная платформа могла показывать пропускную способность до 1500 SMS в секунду в пиковые периоды и работала под нагрузкой в несколько миллионов SMS/USSD-сообщений в день.
Меньшим по размеру и по нагрузкам, но не менее требовательным к качеству и надежности, был комплекс для обслуживания платежных транзакций в адрес операторов мобильной связи для одного из крупнейших российских банков.
Оба этих проекта представляют из себя многокомпонентные программные комплексы, развернутые на нескольких серверах. По сути, это два сложных, распределенных приложения, полностью построенных на основе SObjectizer. Примечательно то, что над данными проектами работала совсем небольшая команда, численность которой в лучшие времена составляла всего лишь шесть человек.
В последние годы бытует мнение, что C++ не является подходящим инструментом для разработки приложений подобного рода. Однако опыт использования SObjectizer говорит, что это далеко не так. У языка C++ есть свои недостатки, и для каких-то прикладных задач в C++ может просто не оказаться нужных инструментов. Однако, при наличии таковых, разработка нагруженных распределенных приложений на C++ оказывается вовсе не сложной, и с большими проектами могут справиться небольшие команды. Что, собственно, и подтверждалось проектами, которые были выполнены как на SCADA Objectizer, так и на SObjectizer-4 и SObjectizer-5.
Настоящее
Что такое SObjectizer-5
Состав
Под названием SObjectizer-5 скрывается несколько взаимосвязанных разработок. Есть ядро SObjectizer-5 – это проект so_5. Именно so_5 содержит средства для создания агентов и сообщений, а также среду исполнения, которая поддерживает обмен и обработку сообщений агентами.
Над so_5 построены дополнительные библиотеки, их принято называть подпроектами. Эти библиотеки не расширяют понятие агентной модели, но зато существенно упрощают разработку больших распределенных приложений на основе SObjectizer.
Библиотека so_log_2 является тонкой оберткой над ACE Logging и упрощает логирование информации из SObjectizer-агентов.
Библиотека so_5_transport предоставляет набор транспортных агентов, скрывающих специфику работы с TCP/IP-соединениями от прикладных агентов.
Библиотека mbapi_4, используя возможности so_5_transport, дает разработчику еще более высокоуровневый механизм обмена прикладными сообщениями. На основе mbapi_4 разрабатываются распределенные приложения с прозрачным перемещением сообщений через границы процессов и узлов сети. То есть, агенту, отправляющему через mbapi_4 сообщения другому агенту, даже не нужно знать, находится ли получатель в том же самом процессе или же в другом процессе на другом узле сети.
Библитека so_sysconf_4 позволяет размещать фабрики для прикладных агентов в отдельных DLL, а затем строить приложение из этих DLL, как из кубиков в конструкторе LEGO.
В целом, SObjectizer-5 представляет из себя слоеную конструкцию, основа которой – проект so_5, отвечающий лишь за поддержку агентной модели. Этой основы может быть вполне достаточно, например, для разработки мелких утилит или приложений, базисом к которых служат другие фреймворки, такие как Qt или wxWidgets.
Если основы в виде проекта so_5 недостаточно, то можно добавлять к ней дополнительные слои – so_log_2 и so_5_transport. Если и этого недостаточно, то еще и mbapi_4 и/или so_sysconf_4.
Агентная модель
Агентная модель, вокруг которой построен SObjectizer, состоит из нескольких базовых понятий.
Агент – это объект класса, унаследованного от специального базового класса agent_t.
Сообщение – это объект класса, унаследованного от специального базового класса message_t. Сообщения в SObjectizer передаются как динамически созданные объекты. Ответственность за их удаление берет на себя SObjectizer.
Сообщения делятся на две категории: обычные сообщения с данными внутри и сигналы, то есть пустые сообщения, для которых важен лишь сам факт их возникновения. Например, информация о вычитанном из сокета пакете данных передается посредством обычного сообщения (прочитанный пакет находится внутри сообщения), а уведомление о том, что пользователь хочет прервать работу приложения – сигналом (никаких данных внутри сообщения нет).
Почтовый ящик (mbox) – это место, куда сообщения отсылаются и откуда они забираются агентами. Почтовые ящики в SObjectizer позволяют организовать взаимодействие как на основе модели publish-subscribe, так и по принципу peer-to-peer.
Отсылка сообщения может быть сиюминутной (сообщение сразу попадает в mbox) и отложенной (сообщение попадает в mbox только по прошествии указанного времени).
Понятие состояния. На идеологическом уровне состояние определяет, какие сообщения и каким именно образом агент будет обрабатывать, находясь в этом состоянии. В коде каждое состояние описывается экземпляром специального типа state_t из состава SObjectizer.
Событие – это реакция агента на конкретный тип сообщения в конкретном состоянии. Эта реакция реализуется посредством обработчика события (обычно это метод агента).
Диспетчер – это объект, который отвечает за предоставление агентам рабочего контекста (т.е. рабочей нити), на котором будет запущен обработчик события. В состав SObjectizer входят пять штатных диспетчеров, реализующих разные политики предоставления агентам рабочих контекстов: от самого простого, в котором все агенты работают на контексте одной общей нити, до самого сложного, который использует пул потоков и позволяет выполнять несколько обработчиков событий одного агента параллельно на нескольких нитях. При запуске SObjectizer пользователь может создать произвольное количество диспетчеров, дав каждому из них уникальное имя. А затем привязывать своих агентов к разным диспетчерам в зависимости от того, какой диспетчер наиболее удобен для выполнения работы агента.
Взаимодействие между агентами может быть асинхронным (до недавнего времени это был единственный способ общения агентов друг с другом и все еще остается наиболее предпочтительным) и синхронным (с бесконечными или ограниченным по времени ожиданием ответа). При синхронном взаимодействии, однако, есть опасность возникновения тупиков, поэтому этот способ следует применять с особой осторожностью.
Еще одно важное понятие — это кооперация агентов. Иногда над одной задачей работают сообща несколько агентов. Например, первый агент читает сокет, второй агент обрабатывает и преобразовывает полученные данные, а третий агент пишет новые данные в базу данных. Эти три агента объединяются в одну кооперацию, и в таком виде они единовременно добавляются в SObjectizer (регистрируются) и изымаются из SObjectizer (дерегистрируются).
Принцип работы
В общих чертах принцип работы SObjectizer (точнее, его ядра, so_5) довольно прост.
Пользователь запускает среду исполнения SObjectizer (SObjectizer Environment) и регистрирует необходимое количество коопераций с прикладными агентами. При регистрации агенты привязываются к диспетчерам, состав и количество которых так же определяется пользователем.
Агенты отсылают сообщения в почтовые ящики (mboxes). В почтовом ящике для каждого типа сообщения хранится список его получателей, т.е. агентов, которые подписались на сообщения этого типа из этого почтового ящика. Для каждого получателя создается заявка на обработку этого экземпляра сообщения.
Заявки отдаются диспетчерам, к которым привязаны агенты-получатели. Там заявки складываются в соответствующие очереди (у каждого диспетчера своя система очередей, наиболее подходящая для диспетчера). Рабочие нити диспетчеров разбирают содержимое очереди заявок и, когда доходят до соответствующей заявки, вызывают обработчик события у агента-получателя, передавая в него экземпляр сообщения.
На практике все несколько сложнее. Например, при вызове обработчика события, проверяется, а может ли агент вообще обработать это сообщение в своем текущем состоянии. Также SObjectizer следит за тем, в какой момент экземпляр сообщения можно безопасно уничтожить (ведь это объект в динамической памяти, которую нужно освободить, когда этот объект перестает быть нужным). Но общий принцип именно таков.
Несколько слов о синхронном взаимодействии агентов. Синхронность существует только для агента, который инициирует запрос. Этот запрос трансформируется в специальное внутреннее сообщение SObjectizer, и обработчик запроса обрабатывает его как обычное асинхронное сообщение (т.е. через очередь заявок диспетчера). Все это время отправитель запроса “спит” в ожидании ответа, а SObjectizer “будит” его после того, как заявка с запросом будет обработана.
Пример агента
Допустим, что есть агент, занимающийся опросом датчика температуры воздуха. Этому агенту можно отослать синхронный запрос и получить текущее значение датчика. Но время выполнения такого запроса исчисляется несколькими секундами. Приостанавливать на это время работу прикладного агента, которому потребовалось текущее значение, нежелательно. Ниже показано, как может выглядеть вспомогательный агент-прокси, который будет кэшировать значение температуры воздуха, опрашивая счетчик только если полученная ранее информация устарела. Кроме того, агент-прокси будет работать с внешним миром асинхронно, то есть. когда у него запрашивают информацию, он в ответ отсылает сообщение с текущим значением.
Дабы не опрашивать датчик при каждом запросе, агент-прокси делает не более одного опроса в течении минуты. Если с момента последнего опроса прошло меньше минуты, то агент просто сразу отдает сохраненное значение.
Агент-прокси имеет два состояния: st_expired, которое означает, что у агента нет актуального значения температуры, и при поступлении запроса нужно заново опрашивать датчик, и st_actual, которое означает, что текущее значение актуально, и его можно сразу отдавать в ответ на запрос.
Агент-прокси реагирует на два сообщения. Первое сообщение, msg_get_current_data, – это запрос текущего значения. В этом сообщении агенту-прокси передается mbox, на который нужно будет отослать ответное сообщение с текущим значением.
Второе сообщение, msg_data_expired, – это сигнал о том, что с момента прошлого опроса прошла минута, и значение перестало быть актуальным.
Агент-прокси отсылает два сообщения. Первое сообщение, msg_current_data, используется для выдачи текущего значения температуры. Второе сообщение-сигнал, msg_acquire_value, выдается в виде синхронного запроса к агенту-датчику.
using namespace so_5; using namespace so_5::rt; // Запрос текущего значения. struct msg_get_current_data : public message_t { // Обратный адрес, на который нужно отсылать ответ. const mbox_ref_t m_return_mbox; msg_get_current_data( mbox_ref_t return_mbox ) : m_return_mbox( std::move(return_mbox) ) {} }; // Ответное сообщение с текущим значением температуры. struct msg_current_data : public message_t { float m_value; msg_current_data( float value ) : m_value(value) {} }; // Сигнал о том, что текущее значение перестало быть актуальным. struct msg_data_expired : public signal_t {}; // Сигнал агенту-датчику о необходимости опросить датчик температуры. struct msg_acquire_value : public signal_t {}; class a_temperature_meter_proxy_t : public agent_t { private : // Состояния агента. const state_t st_expired = so_make_state( "expired" ); const state_t st_actual = so_make_state( "actual" ); // Адрес агента, отвечающего за взаимодействие с датчиком. const mbox_ref_t m_meter_mbox; // Последнее полученное от датчика значение. float m_last_value; public : // Конструктор. a_temperature_meter_proxt_t( // Обязательный параметр SObjectizer Environment, в рамках // которого агент будет работать. so_environment_t & env, // Адрес агента, отвечающего за работу с датчиком. mbox_ref_t meter_mbox ) : agent_t( env ) , m_meter_mbox( std::move(meter_mbox) ) {} // Настройка агента для работы внутри SObjectizer. // Вызывается в процессе регистрации агента для того, // чтобы агент мог перейти в начальное состояние и // настроить свои подписки. virtual void so_define_agent() override { // Изначально агент должен находиться в состоянии expired. so_change_state( st_expired ); // Подписка на сообщения. // Этот агент реагирует только на сообщения, которые // отсылаются в его персональный mbox. // Реакция на запрос значения, когда у агента нет // актуальных данных от датчика. so_subscribe( so_direct_mbox() ).in( st_expired ) .event( // Метод, который будет обработчиком события. &a_temperature_meter_proxy_t::evt_get_data_from_meter ); // Далее реакция на сообщения, которые агент обрабатывает // имея актуальную информацию от датчика. so_subscribe( so_direct_mbox() ).in( st_actual ) // На запрос данных можно просто вернуть текущее значение. .event( // Обработчик события задается лямбда-функцией, // т.к. он настолько прост, что нет смысла // заводить отдельный метод. [this]( const msg_get_current_data & evt ) { // Сразу отсылаем ответное сообщение. evt.m_return_mbox->deliver_message( new msg_current_data( m_last_value ) ); } ) // На уведомление об истечении времени жизни последнего // замера нужно поменять состояние агента. .event( signal< msg_data_expired >, // Опять очень простой обработчик, который // может быть представлен лямбда-функцией. [this]() { so_change_state( st_expired ); } ); } // Обработчик события запроса температуры, когда // последнее прочитанное значение уже не актуально. void evt_get_data_from_meter( const msg_get_current_data & evt ) { // Получаем текущее значение у реального агента. // Ждем ответа не более 10 секунд. Если ответ не поступит, // то возникнет исключение, которое обработает SObjectizer. m_last_value = m_meter_mbox->get_one< float >() .wait_for( std::chrono::seconds( 10 ) ) .sync_get< msg_acquire_value >(); // Данные у нас есть, переводим агент в состояние // наличия актуальной информации. so_change_state( st_actual ); // И заказываем отложенное сообщение для того, чтобы // вернуться затем в состояние expired. so_environment()->single_timer< msg_data_expired >( // Сигнал будет доставлен в персональный mbox агента. so_direct_mbox(), // Через 60 секунд (значение задается в миллисекундах). 60 * 1000 ); // Текущее значение нужно вернуть получателю. evt.m_return_mbox->deliver_message( new msg_current_data( m_last_value ) ); } };
Сравнение с аналогами
Фреймворков, позволяющих разрабатывать ПО с использованием Actor Model, довольно много (см., например, соответствующий список). Однако, если ограничиться только языком C++, то количество аналогов существенно сокращается. Если добавить сюда еще и то, что за последний год признаки жизни подавало всего три OpenSource фреймворка для C++ (SObjectizer, C++ Actor Framework (CAF) и Theron), то аналогов оказывается не так уж много.
При сравнении нельзя не учитывать один важный фактор: влияние языка Erlang на все, что появилось в этой области в последние 10 лет. Фактически, современные фреймворки, как для C++, так и для других языков программирования, пытаются перенести принципы функционирования Erlang-овских процессов в другие языки программирования. Где-то это получается лучше, где-то хуже. Но в целом клоны Erlang остаются клонами, лишь более-менее приближающимися к оригиналу.
SObjectizer же появился тогда, когда широкой общественности не было известно про Erlang. Это оригинальная разработка, в которой так же, как и в Erlang, происходит обмен сообщениями между сущностями. Но на этом сходство заканчивается. Поэтому главное отличие SObjectizer от аналогов – это то, что SObjectizer не пытается повторить Erlang в C++.
Отсюда происходят все остальные, более мелкие отличия. Например, подход к организации группы взаимодействующих агентов. В SObjectizer для этого используются кооперации агентов. В клонах Erlang разработчик создает акторов поодиночке, а для того, чтобы они работали единой группой, используются аналоги Erlang-овских супервизоров.
Еще один пример важного отличия – это понятие диспетчера и возможность привязывать агентов к тем диспетчерам, которые наиболее подходят для конкретной задачи.
Далее идут состояния у агентов и упор на асинхронное взаимодействие между агентами. Это приводит к разработке агентов в виде конечных автоматов с наборами состояний и переходами из одного состояния в другое в процессе обработки событий. Для каких-то задач это более удобно, чем работа в стиле Erlang, где можно отослать сообщение другому процессу, а затем синхронно висеть на ожидании ответа. Для каких-то задач, напротив, стиль Erlang более удобен.
Кроме того, очень важен акцент, который делают разработчики аналогичных фреймворков. Так, разработчики CAF и Theron акцентируют внимание на высокой скорости передачи сообщений между агентами и на том, что их основная задача — это выжимание максимальной производительности из современного многоядерного железа. То есть, данные фреймворки в первую очередь позиционируются для parallel computing.
В то же время во главу угла в SObjectizer всегда ставилось удобство разработки приложений, в которых агенты выполняют собственные прикладные действия, независимо друг от друга. При этом прикладные действия могут быть очень разные: как ресурсоемкие вычисления, так и блокирующие вызовы внешних функций или обращения к внешним ресурсам. Отсюда, например, и наличие различных типов диспетчеров: они нужны для того, чтобы различные типы агентов мирно сосуществовали друг с другом в рамках одного процесса, не оказывая существенного влияния друг на друга. Таким образом, SObjectizer в первую очередь позиционируется для concurrent computing.
Кроме того, SObjectizer находился в реальной повседневной эксплуатации несколько дольше своих C++ аналогов, поэтому, например, разделение на слои (so_5, so_5_transport, mbapi_4, so_sysconf_4) произошло уже довольно давно, тогда как CAF начал движение в этом направлении лишь несколько месяцев назад.
И еще об одном важном отличии: так как SObjectizer никогда не был исследовательским проектом и всегда ориентировался на решение практических задач, при разработке SObjectizer уделялось внимание простоте его использования. Поэтому SObjectizer в меньшей степени использует новые возможности C++11 и менее требователен к уровню поддержки компилятором стандарта C++11 в отличии от, скажем, CAF. Порог вхождения в SObjectizer относительно невысок, в том числе и за счет того, что SObjectizer не требует от программиста отличного знания тонкостей C++. Это неоднократно оправдывало себя на практике, когда новички быстро осваивали SObjectizer и оперативно подключались к разработке больших SObjectizer-проектов.
Текущее состояние
До 2013 года SObjectizer, уже будучи Open Source проектом, все же оставался внутренней разработкой компании “Интервэйл”. Это накладывало свой отпечаток как на приоритеты в развитии SObjectizer, так и на объем ресурсов, которые удавалось выделять на разработку SObjectizer. Но с середины 2013 года SObjectizer развивается как самостоятельный OpenSource-проект.
Сейчас над SObjectizer работает команда из пяти человек. Автор статьи занимается только SObjectizer в режиме full time, остальные члены команды активно помогают. В связи с этим разработка идет в режиме мягкой диктатуры: ответственные решения принимаются лидером разработки, но мнение каждого из членов команды принимается во внимание.
Вся разработка базируется на базе инфраструктуры, предоставляемой ресурсом SourceForge. Исходные тексты – в SVN-репозитории SourceForge. Баг-трекинг, списки задач, дискуссии и документация в Wiki – на сайте SourceForge.
В качестве релизной политики выбран периодический выпуск сборок всех подпроектов SObjectizer. В сборку входят все последние стабильные версии подпроектов на момент релиза сборки. При наличии возможности сборки выпускаются раз в 1-2 месяца. Если после выпуска сборки в каком-то из подпроектов обнаруживаются критически важные ошибки/проблемы, то после их исправления вне очереди выпускается обновленная сборка.
Пока все основные усилия команды сконцентрированы на ядре SObjectizer – проекте so_5. Эта часть SObjectizer сейчас развивается наиболее активно. За период с декабря 2013 по август 2014 было выпущено три серьезных обновления so_5, которые существенно расширили функциональность и подняли производительность ядра SObjectizer. Остальные подпроекты лишь слегка адаптировались под новые версии so_5, что было не очень сложно, так как команда разработки очень внимательно и трепетно относится к проблемам сохранения совместимости и минимизации проблем при обновлении SObjectizer.
Работа над очередной версией so_5 обычно строится следующим образом:
- Перед началом работ формируется список “хотелок” новой версии (т.н. wish-list). Обычно этот wish-list оформляется в виде отдельной темы в списках обсуждений проекта на SourceForge.
- По ходу работ над новой версией основная часть wish-list воплощается в жизнь. Какие-то не вошедшие в новую версию “хотелки” переносятся в будущие релизы (не все можно сделать сразу, в том числе и по причине ограниченности ресурсов), от каких-то отказываются из-за различных причин (например, при тщательной проработке может выясниться, что реальной пользы от “хотелки” не будет, или же для ее воплощения в жизнь придется жертвовать совместимостью с предшествующими версиями).
- Для разработки новой версии в SVN-репозитории создаются новые ветки, изменения из которых, по готовности, сливаются в основную ветвь разработки.
- При разработке новой версии баг-трекинг практически не используется, так как любая выявленная на этом этапе проблема рассматривается как show-stopper и разработка приостанавливается до тех пор, пока проблема не будет устранена. Таким образом, просто нет необходимости в списке проблем, так как в конкретный момент есть всего одна актуальная проблема, на решении которой сосредоточенны все имеющиеся силы. Штатный баг-трекер SourceForge задействуется для фиксации проблем, выявленных в уже состоявшихся релизах.
Основное внимание при разработке новых версий SObjectizer уделяется двум вещам: тестированию и документированию. По субъективным оценкам, на каждый новый кусок функциональности около 40% времени уходит на проектирование и реализацию, а оставшиеся 60% — это покрытие кода тестами, устранение выявленных при тестировании проблем, разработка демонстрационных примеров и документирование.
В основном, тестирование ядра SObjectizer выполняется посредством юнит-тестов и небольших тестовых программ, работающих по принципам юнит-тестов (т.е. либо успешно отрабатывающих, либо же аварийно завершающихся при обнаружении ошибки). Используемая в разработке SObjectizer система сборки Mxx_ru имеет встроенную поддержку такого рода тестов, что позволяет запускать наборы тестов (как полные, так и частичные) как часть процесса сборки SObjectizer.
В некоторых подпроектах, например, so_5_transport и so_sysconf_4 использование юнит-тестирования затруднено, и там активно используются тесты, которые нужно запускать вручную. Это не очень удобно, поэтому есть желание в большей степени автоматизировать процесс тестирования этих проектов. Но для этого пока в должной степени “не дошли руки”.
Будущее
Будущее, к сожалению или к счастью, никому не ведомо, поэтому о том, что случится с SObjectizer в ближайшей или отдаленной перспективе, можно только гадать. Говорить сейчас можно разве что о ближайших планах, которые есть у команды разработки SObjectizer, но что именно из этого получится покажет время.
Итак, после релиза версии 5.4.0 есть планы заняться демо-проектом, который способен продемонстрировать возможности SObjectizer в решении какой-либо практической задачи. Что это будет – вопрос пока открытый. Возможно, клиент для AMQP, возможно, инструмент для работы с MQTT или CoAP, а может быть что-то еще. Выбор еще предстоит сделать, и основным критерием будет наглядность демонстрации возможностей SObjectizer при небольшой трудоемкости.
Параллельно с этим планируется вести работы над следующей версией ядра SObjectizer, so-5.4.1, релиз которой запланирован на конец октября 2014 года, после чего появится возможность вплотную заняться развитием подпроектов SObjectizer, а именно, so_5_transport и mbapi_4.
Отдельно будут выполняться работы по распространению информации о SObjectizer. До сих пор информация о нем не выходила дальше 3-4 русскоязычных ресурсов для разработчиков ПО. Эту ситуацию предстоит изменить. В первую очередь, за счет улучшения и увеличения объема документации и обучающих материалов, а также публикаций анонсов и новостей о выходе новых версий SObjectizer на популярных англоязычных ресурсах.
В целом, команде SObjectizer есть чем заняться до конца 2014 года, а в начале 2015 года можно будет подводить первые итоги “свободного плавания” SObjectizer в качестве самостоятельного проекта, и, если к проекту будет интерес со стороны пользователей и сторонних разработчиков, выбирать путь его дальнейшего развития.
Оставьте комментарий